From a3a9d4027bcf375a1687fce158aa5ce0e5413d35 Mon Sep 17 00:00:00 2001
From: David Seus <david.seus@ians.uni-stuttgart.de>
Date: Tue, 2 Apr 2019 18:00:50 +0200
Subject: [PATCH] write LDDsolver method.
---
LDDsimulation/LDDsimulation.py | 81 ++++++++++++++++++++++++++++++++++
LDDsimulation/__init__.py | 3 ++
LDDsimulation/domainPatch.py | 5 ++-
3 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/LDDsimulation/LDDsimulation.py b/LDDsimulation/LDDsimulation.py
index f137716..f6ed481 100644
--- a/LDDsimulation/LDDsimulation.py
+++ b/LDDsimulation/LDDsimulation.py
@@ -80,6 +80,10 @@ class LDDsimulation(object):
self.adjacent_subdomains = None
## Private variables
+ # maximal number of L-iterations that the LDD solver uses.
+ self._max_iter_num = 100
+ # TODO rewrite this with regard to the mesh sizes
+ self.calc_tol = 10^-6
# The number of subdomains are counted by self.init_meshes_and_markers()
self._number_of_subdomains = 0
# variable to check if self.set_parameters() has been called
@@ -145,6 +149,83 @@ class LDDsimulation(object):
# init Dirichlet Boundary values for the first time
self.set_DirichletBC(time = 0, first_init = True)
+ def LDDsolver(self, time: float):
+ """ calulate the solution on all patches for the next timestep
+
+ The heart of the simulation. The function LDDsolver implements the LDD
+ iteration, that is solves the problem given the initial data at timestep
+ time.
+ """
+ iteration = 0
+ # dictionary holding bool variables for each subdomain indicating wether
+ # minimal error has been achieved, i.e. the calculation can be considered
+ # done or not.
+ subdomain_calc_isdone = dict()
+ # before the iteration gets started all iteration numbers must be nulled
+ # and
+ for ind, subdomain in self.subdomain.items():
+ subdomain_calc_isdone.update({ind, False})
+ # the following only needs to be done when time is not equal 0 since
+ # our initialisation functions already took care of setting what follows
+ # for the initial iteration step.
+ if time > 0:
+ # this is the beginning of the solver, so iteration must be set
+ # to 0.
+ subdomain.iteration_number = 0
+ # set the solution of the previous timestep as new prev_timestep pressure
+ subdomain.pressure_prev_timestep = subdomain.pressure
+ # TODO recheck if
+ subdomain.pressure_prev_iter = subdomain.pressure
+ # needs to be set also
+ ### actual iteration starts here
+ # gobal stopping criterion for the iteration.
+ all_subdomains_done = False
+ while iteration < self._max_iter_num and not all_subdomains_done:
+ # we need to loop over the subdomains and solve an L-scheme type step
+ # on each subdomain. here it should be possible to parallelise in
+ # the future.
+ for sd_index, subdomain in self.subdomain.items():
+ # check if the calculation on subdomain has already be marked as
+ # finished.
+ if not subdomain_calc_isdone[sd_index]:
+ # solve the problem on subdomain
+ self.Lsolver_step(subdomain = subdomain,#
+ iteration = iteration,#
+ debug = True
+ )
+ subsequent_iterations_err = self.calc_iteration_error(
+ subdomain = subdomain,#
+ error_type = "L2"
+ )
+ # check if error criterion has been met
+ if subsequent_iterations_err < self.calc_tol:
+ subdomain_calc_isdone[sd_index] = True
+
+ # prepare next iteration
+ # write the newly calculated solution to the inteface dictionaries
+ # for communication
+ subdomain.write_pressure_to_interfaces()
+ subdomain.pressure_prev_iter = subdomain.pressure
+ else:
+ # one subdomain is done. Check if all subdomains are done to
+ # stop the while loop if needed.
+ # For this, set
+ all_subdomains_done = True
+ # then check if all domains are done. If not, reset
+ # all_subdomains_done to False.
+ for subdomain, isdone in subdomain_calc_isdone.items():
+ if not isdone:
+ all_subdomains_done = False
+ #TODO check if maybe I still need to do
+ # subdomain.iteration_number += 1
+ # or adapt the calc_gli_term method to reflect that one subdomain
+ # could be done earlier than others.
+
+
+ # you wouldn't be so stupid as to write an infinite loop, would you?
+ iteration += 1
+ # end iteration while loop.
+
## Private methods
def _init_meshes_and_markers(self, subdomain_def_points: tp.List[tp.List[df.Point]] = None,#
mesh_resolution: float = None) -> None:
diff --git a/LDDsimulation/__init__.py b/LDDsimulation/__init__.py
index e69de29..a0c87a4 100644
--- a/LDDsimulation/__init__.py
+++ b/LDDsimulation/__init__.py
@@ -0,0 +1,3 @@
+from . import domainPatch
+from . import helpers
+from . import LDDsimulation
diff --git a/LDDsimulation/domainPatch.py b/LDDsimulation/domainPatch.py
index 47d72f1..35ddc9d 100644
--- a/LDDsimulation/domainPatch.py
+++ b/LDDsimulation/domainPatch.py
@@ -180,7 +180,10 @@ class DomainPatch(df.SubDomain):
#### PUBLIC METHODS
def write_pressure_to_interfaces(self):
- """ save the interface values of self.pressure to all neighbouring interfaces"""
+ """ save the interface values of self.pressure to all neighbouring interfaces
+
+ This method is used by the LDDsimulation.LDDsolver method.
+ """
if self.isRichards:
for ind in self.has_interface:
interface[ind].read_pressure_dofs(from_function = self.pressure['wetting'], #
--
GitLab