diff --git a/LDDsimulation/LDDsimulation.py b/LDDsimulation/LDDsimulation.py index 9c34840afc9f7c0e16cc3b92e686f3bdfe3229cb..032e7a1697ae60ce405d64134d7a62206520a172 100644 --- a/LDDsimulation/LDDsimulation.py +++ b/LDDsimulation/LDDsimulation.py @@ -464,14 +464,16 @@ class LDDsimulation(object): # step on each subdomain. # Here it should be possible to parallelise in # the future. - for sd_index in self.subdomain.keys(): + for sd_index, subdomain in self.subdomain.items(): # set subdomain iteration to current iteration + # mp.set_start_method('fork') + processQueue = mp.Queue() Lsolver_step = mp.Process( target=self.run_Lsolver_step, args=( iteration, sd_index, - max_subsequent_error, + processQueue, solution_over_iteration_within_timestep, debug, analyse_timestep, @@ -479,16 +481,23 @@ class LDDsimulation(object): ) ) Lsolver_step.start() + max_subsequent_error[sd_index-1] = processQueue.get() + print(Lsolver_step.exitcode) Lsolver_step.join() - # self.encapsulated_Lsolver_step( - # analyse_timestep=analyse_timestep, - # analyse_condition=analyse_condition, - # debug=debug, + print(Lsolver_step.exitcode) + # update interface iteration numbers + # for index in subdomain.has_interface: + # interface = self.interface[index] + # interface.current_iteration[sd_index] = iteration + # Lsolver_step.terminate() + # self.run_Lsolver_step( # iteration=iteration, # subdomain_index=sd_index, - # subdomain=subdomain, # max_subsequent_error=max_subsequent_error, # sol_over_iter_file=solution_over_iteration_within_timestep, + # analyse_timestep=analyse_timestep, + # analyse_condition=analyse_condition, + # debug=debug # ) # end loop over subdomains # stopping criterion for the solver. @@ -513,7 +522,7 @@ class LDDsimulation(object): self, iteration: int, subdomain_index: int, - max_subsequent_error: np.ndarray, + processQueue, sol_over_iter_file: tp.Dict[int, tp.Type[SolutionFile]], debug: bool = False, analyse_timestep: bool = False, @@ -557,10 +566,6 @@ class LDDsimulation(object): "iteration {} = ".format(iteration) print(debugstring, subsequent_iter_error[phase]) - # calculate the maximum over phase of subsequent errors for the - # stopping criterion. - max_subsequent_error[sd_index-1] = max(subsequent_iter_error.values()) - if analyse_timestep: # save the calculated L2 errors to csv file for plotting # with pgfplots @@ -608,6 +613,12 @@ class LDDsimulation(object): subdomain.pressure[phase] ) + # calculate the maximum over phase of subsequent errors for the + # stopping criterion. + # max_subsequent_error[sd_index-1] = max(subsequent_iter_error.values()) + processQueue.put(max(subsequent_iter_error.values())) + + def prepare_LDDsolver( self, time: float = None, @@ -651,23 +662,23 @@ class LDDsimulation(object): # before the iteration gets started all iteration numbers must be # nulled for subdomain_index in self.subdomain.keys(): - prepare_subdomain = mp.Process( - target=self.prepare_subdomain, - args=( - subdomain_index, - solution_over_iteration_within_timestep, - debug, - analyse_timestep, - ) - ) - prepare_subdomain.start() - prepare_subdomain.join() - # self.prepare_subdomain( - # subdomain_index=ind, - # sol_over_iter_file=solution_over_iteration_within_timestep, - # debug=debug, - # analyse_timestep=analyse_timestep, - # ) + # prepare_subdomain = mp.Process( + # target=self.prepare_subdomain, + # args=( + # subdomain_index, + # solution_over_iteration_within_timestep, + # debug, + # analyse_timestep, + # ) + # ) + # prepare_subdomain.start() + # prepare_subdomain.join() + self.prepare_subdomain( + subdomain_index=subdomain_index, + sol_over_iter_file=solution_over_iteration_within_timestep, + debug=debug, + analyse_timestep=analyse_timestep, + ) return solution_over_iteration_within_timestep @@ -772,7 +783,6 @@ class LDDsimulation(object): f"pressure_prev_timestep[{phase}].vector()[:]" + " =\n" + \ f"{subdomain.pressure_prev_timestep[phase].vector()[:]}" print(debugstr5) - # we need to update the previous pressure dictionaries of all # interfaces of the subdomain with the current solution, so that the # subdomain.calc_gli_term method works properly. @@ -802,7 +812,6 @@ class LDDsimulation(object): to write out each iteration. """ subdomain = self.subdomain[subdomain_index] - # iteration = subdomain.iteration_number condition_number = None if analyse_condition: condition_number = dict() diff --git a/Two-phase-Richards/multi-patch/layered_soil_with_inner_patch/TP-R-layered_soil_with_inner_patch-realistic.py b/Two-phase-Richards/multi-patch/layered_soil_with_inner_patch/TP-R-layered_soil_with_inner_patch-realistic.py index 5dd7b983bd292ded3b33fab1d014bea264770977..f9aaec372c6005a0fbe29bd29e617ebe096dcb83 100755 --- a/Two-phase-Richards/multi-patch/layered_soil_with_inner_patch/TP-R-layered_soil_with_inner_patch-realistic.py +++ b/Two-phase-Richards/multi-patch/layered_soil_with_inner_patch/TP-R-layered_soil_with_inner_patch-realistic.py @@ -60,7 +60,7 @@ resolutions = { # for each element t_0 in starttimes. starttimes = [0.0] timestep_size = 0.001 -number_of_timesteps = 500 +number_of_timesteps = 10 # LDD scheme parameters ###################################################### diff --git a/Two-phase-Richards/two-patch/TP-R-two-patch-test-case/TP-R-2-patch-realistic.py b/Two-phase-Richards/two-patch/TP-R-two-patch-test-case/TP-R-2-patch-realistic.py index b807a25c4c6aebf3e0b21051e74af6f545ae06ed..9360a1fd371fc7fc2f0f9dd0001bfcc17f2bfb41 100755 --- a/Two-phase-Richards/two-patch/TP-R-two-patch-test-case/TP-R-2-patch-realistic.py +++ b/Two-phase-Richards/two-patch/TP-R-two-patch-test-case/TP-R-2-patch-realistic.py @@ -12,6 +12,8 @@ import helpers as hlp import datetime import os import pandas as pd +import multiprocessing as mp +import domainSubstructuring as dss # init sympy session sym.init_printing() @@ -36,20 +38,20 @@ thisfile = "TP-R-2-patch-realistic.py" # GENERAL SOLVER CONFIG ###################################################### # maximal iteration per timestep -max_iter_num = 500 +max_iter_num = 50 FEM_Lagrange_degree = 1 # GRID AND MESH STUDY SPECIFICATIONS ######################################### -mesh_study = True +mesh_study = False resolutions = { - 1: 1e-5, - 2: 1e-5, - 4: 1e-5, - 8: 1e-5, + # 1: 1e-5, + # 2: 1e-5, + # 4: 1e-5, + # 8: 1e-5, 16: 5e-6, - 32: 5e-6, - 64: 2e-6, - 128: 2e-6, + # 32: 5e-6, + # 64: 2e-6, + # 128: 2e-6, # 256: 1e-6, } @@ -58,19 +60,19 @@ resolutions = { # for each element t_0 in starttimes. starttimes = [0.0] timestep_size = 0.001 -number_of_timesteps = 800 +number_of_timesteps = 5 # LDD scheme parameters ###################################################### -Lw1 = 0.25 #/timestep_size -Lnw1= 0.25 +Lw1 = 0.025 #/timestep_size +Lnw1= 0.025 -Lw2 = 0.5 #/timestep_size -Lnw2= 0.25 +Lw2 = 0.025 #/timestep_size +Lnw2= 0.025 -lambda_w = 40 -lambda_nw = 40 +lambda_w = 44 +lambda_nw = 4 -include_gravity = True +include_gravity = False debugflag = True analyse_condition = False @@ -431,14 +433,10 @@ p_e_sym = { } #-y*y*(sym.sin(-2*t+2*x)*sym.sin(1/2*y-1.2*t)) - t*t*x*(0.5-y)*y*(1-x) -pc_e_sym = dict() -for subdomain, isR in isRichards.items(): - if isR: - pc_e_sym.update({subdomain: -p_e_sym[subdomain]['wetting'].copy()}) - else: - pc_e_sym.update({subdomain: p_e_sym[subdomain]['nonwetting'].copy() - - p_e_sym[subdomain]['wetting'].copy()}) - +pc_e_sym = hlp.generate_exact_symbolic_pc( + isRichards=isRichards, + symbolic_pressure=p_e_sym + ) symbols = {"x": x, "y": y, @@ -464,35 +462,18 @@ source_expression = exact_solution_example['source'] exact_solution = exact_solution_example['exact_solution'] initial_condition = exact_solution_example['initial_condition'] -# Dictionary of dirichlet boundary conditions. -dirichletBC = dict() -# similarly to the outer boundary dictionary, if a patch has no outer boundary -# None should be written instead of an expression. -# This is a bit of a brainfuck: -# dirichletBC[ind] gives a dictionary of the outer boundaries of subdomain ind. -# Since a domain patch can have several disjoint outer boundary parts, the -# expressions need to get an enumaration index which starts at 0. -# So dirichletBC[ind][j] is the dictionary of outer dirichlet conditions of -# subdomain ind and boundary part j. -# Finally, dirichletBC[ind][j]['wetting'] and dirichletBC[ind][j]['nonwetting'] -# return the actual expression needed for the dirichlet condition for both -# phases if present. - # BOUNDARY CONDITIONS ######################################################### -# subdomain index: {outer boudary part index: {phase: expression}} -for subdomain in isRichards.keys(): - # subdomain can have no outer boundary - if outer_boundary_def_points[subdomain] is None: - dirichletBC.update({subdomain: None}) - else: - dirichletBC.update({subdomain: dict()}) - # set the dirichlet conditions to be the same code as exact solution on - # the subdomain. - for outer_boundary_ind in outer_boundary_def_points[subdomain].keys(): - dirichletBC[subdomain].update( - {outer_boundary_ind: exact_solution[subdomain]} - ) - +# Dictionary of dirichlet boundary conditions. If an exact solution case is +# used, use the hlp.generate_exact_DirichletBC() method to generate the +# Dirichlet Boundary conditions from the exact solution. +dirichletBC = hlp.generate_exact_DirichletBC( + isRichards=isRichards, + outer_boundary_def_points=outer_boundary_def_points, + exact_solution=exact_solution + ) +# If no exact solution is provided you need to provide a dictionary of boundary +# conditions. See the definiton of hlp.generate_exact_DirichletBC() to see +# the structure. # LOG FILE OUTPUT ############################################################# # read this file and print it to std out. This way the simulation can produce a @@ -502,88 +483,63 @@ print(f.read()) f.close() -# RUN ######################################################################### -for starttime in starttimes: - for mesh_resolution, solver_tol in resolutions.items(): - # initialise LDD simulation class - simulation = ldd.LDDsimulation( - tol=1E-14, - LDDsolver_tol=solver_tol, - debug=debugflag, - max_iter_num=max_iter_num, - FEM_Lagrange_degree=FEM_Lagrange_degree, - mesh_study=mesh_study - ) - - simulation.set_parameters( - use_case=use_case, - output_dir=output_string, - subdomain_def_points=subdomain_def_points, - isRichards=isRichards, - interface_def_points=interface_def_points, - outer_boundary_def_points=outer_boundary_def_points, - adjacent_subdomains=adjacent_subdomains, - mesh_resolution=mesh_resolution, - viscosity=viscosity, - porosity=porosity, - L=L, - lambda_param=lambda_param, - relative_permeability=relative_permeability, - saturation=sat_pressure_relationship, - starttime=starttime, - number_of_timesteps=number_of_timesteps, - number_of_timesteps_to_analyse=number_of_timesteps_to_analyse, - plot_timestep_every=plot_timestep_every, - timestep_size=timestep_size, - sources=source_expression, - initial_conditions=initial_condition, - dirichletBC_expression_strings=dirichletBC, - exact_solution=exact_solution, - densities=densities, - include_gravity=include_gravity, - gravity_acceleration=gravity_acceleration, - write2file=write_to_file, - ) - - simulation.initialise() - output_dir = simulation.output_dir - # simulation.write_exact_solution_to_xdmf() - output = simulation.run(analyse_condition=analyse_condition) - for subdomain_index, subdomain_output in output.items(): - mesh_h = subdomain_output['mesh_size'] - for phase, error_dict in subdomain_output['errornorm'].items(): - filename = output_dir \ - + "subdomain{}".format(subdomain_index)\ - + "-space-time-errornorm-{}-phase.csv".format(phase) - # for errortype, errornorm in error_dict.items(): - - # eocfile = open("eoc_filename", "a") - # eocfile.write( str(mesh_h) + " " + str(errornorm) + "\n" ) - # eocfile.close() - # if subdomain.isRichards:mesh_h - data_dict = { - 'mesh_parameter': mesh_resolution, - 'mesh_h': mesh_h, - } - for norm_type, errornorm in error_dict.items(): - data_dict.update( - {norm_type: errornorm} - ) - errors = pd.DataFrame(data_dict, index=[mesh_resolution]) - # check if file exists - if os.path.isfile(filename) is True: - with open(filename, 'a') as f: - errors.to_csv( - f, - header=False, - sep='\t', - encoding='utf-8', - index=False - ) - else: - errors.to_csv( - filename, - sep='\t', - encoding='utf-8', - index=False - ) +# MAIN ######################################################################## +if __name__ == '__main__': + # dictionary of simualation parameters to pass to the run function. + # mesh_resolution and starttime are excluded, as they get passed explicitly + # to achieve parallelisation in these parameters in these parameters for + # mesh studies etc. + simulation_parameter = { + "tol": 1E-14, + "debugflag": debugflag, + "max_iter_num": max_iter_num, + "FEM_Lagrange_degree": FEM_Lagrange_degree, + "mesh_study": mesh_study, + "use_case": use_case, + "output_string": output_string, + "subdomain_def_points": subdomain_def_points, + "isRichards": isRichards, + "interface_def_points": interface_def_points, + "outer_boundary_def_points": outer_boundary_def_points, + "adjacent_subdomains": adjacent_subdomains, + # "mesh_resolution": mesh_resolution, + "viscosity": viscosity, + "porosity": porosity, + "L": L, + "lambda_param": lambda_param, + "relative_permeability": relative_permeability, + "sat_pressure_relationship": sat_pressure_relationship, + # "starttime": starttime, + "number_of_timesteps": number_of_timesteps, + "number_of_timesteps_to_analyse": number_of_timesteps_to_analyse, + "plot_timestep_every": plot_timestep_every, + "timestep_size": timestep_size, + "source_expression": source_expression, + "initial_condition": initial_condition, + "dirichletBC": dirichletBC, + "exact_solution": exact_solution, + "densities": densities, + "include_gravity": include_gravity, + "gravity_acceleration": gravity_acceleration, + "write_to_file": write_to_file, + "analyse_condition": analyse_condition + } + for starttime in starttimes: + for mesh_resolution, solver_tol in resolutions.items(): + simulation_parameter.update({"solver_tol": solver_tol}) + hlp.info(simulation_parameter["use_case"]) + # LDDsim = mp.Process( + # target=hlp.run_simulation, + # args=( + # simulation_parameter, + # starttime, + # mesh_resolution + # ) + # ) + # LDDsim.start() + # LDDsim.join() + hlp.run_simulation( + mesh_resolution=mesh_resolution, + starttime=starttime, + parameter=simulation_parameter + )