From d7b70a4ed06b359cc1bae47571a731c582a42492 Mon Sep 17 00:00:00 2001 From: David Seus <david.seus@ians.uni-stuttgart.de> Date: Fri, 19 Apr 2019 16:50:17 +0200 Subject: [PATCH] write output for L2 errornorm with exact solution --- LDDsimulation/LDDsimulation.py | 185 +++++++-- LDDsimulation/domainPatch.py | 16 +- RR-2-patch-test-case/RR-2-patch-test.py | 381 ++---------------- .../plots/exact_solution_error_norms.tex | 47 +++ .../plots/subsequent_errors.tex | 114 +++++- TP-TP-patch-test-case/TP-TP-2-patch-test.py | 45 ++- 6 files changed, 386 insertions(+), 402 deletions(-) create mode 100644 RR-2-patch-test-case/plots/exact_solution_error_norms.tex diff --git a/LDDsimulation/LDDsimulation.py b/LDDsimulation/LDDsimulation.py index 7e38bcd..74d5827 100644 --- a/LDDsimulation/LDDsimulation.py +++ b/LDDsimulation/LDDsimulation.py @@ -121,9 +121,12 @@ class LDDsimulation(object): # dictionary to store the df.dirichletBC objects in. These are used by the # solver to set the boundary conditions self.outerBC = dict() - # Flag to toggle between a case with exact solution and a purely numerical - # simulation. This changes the behaviour of self.update_DirichletBC_dictionary() - self.exact_solution_case = False + # Dictionary that holdes the exact solution. Gets set by self.set_parameters() + # but can remain None if we don't consider a case with an exact solution. + self.exact_solution = None + # Dictionary of df. Expressions holding for each subdomain and phase the + # dolfin expressions generated of self.exact_solution by self._init_initial_values() + self.exact_solution_expr = dict() # dictionary holding the source expressions for each subdomain. These are # saved to the respective subdomains by the self._init_subdomains() method. self.sources = None# @@ -178,7 +181,7 @@ class LDDsimulation(object): initial_conditions: tp.Dict[int, tp.Dict[str, str]],# dirichletBC_Expressions: tp.Dict[int, tp.Dict[str, str]],# write2file: tp.Dict[str, bool],# - exact_solution_case: bool = False, # + exact_solution: tp.Dict[int, tp.Dict[str, str]] = None, # )-> None: """ set parameters of an instance of class LDDsimulation""" @@ -196,6 +199,7 @@ class LDDsimulation(object): self.relative_permeability = relative_permeability self.saturation = saturation # simulation start time and time variable + self.t_initial = time_interval[0] self.t = time_interval[0] # end_time self.T = time_interval[1] @@ -203,7 +207,7 @@ class LDDsimulation(object): self.sources = sources self.initial_conditions = initial_conditions self.dirichletBC_Expressions = dirichletBC_Expressions - self.exact_solution_case = exact_solution_case + self.exact_solution = exact_solution self.write2file = write2file self._parameters_set = True @@ -214,6 +218,7 @@ class LDDsimulation(object): """ if not self._parameters_set: raise RuntimeError('Parameters note set!\nYou forgott to run self.set_parameters(**kwds)') + self._add_parameters_to_output_dirname() print("initialise meshes and marker functions ...\n") self._init_meshes_and_markers() print("initialise interfaces ...\n") @@ -225,9 +230,12 @@ class LDDsimulation(object): # initial values get initialised here to be able to call the solver at different # timesteps without having to call self.run(). self._init_initial_values() + # initialise exact solution expression dictionary if we have an exact + # solution case. + self._init_exact_solution_expression() self._initialised = True - def run(self, analyse_solver_at_times: tp.List[float] = None): + def run(self, analyse_solver_at_timesteps: tp.List[float] = None): """ run the simulation This method implements the time stepping, calls the acutal solvers and writes @@ -235,7 +243,7 @@ class LDDsimulation(object): want to understand this code, start reading here. PARAMETERS - analyse_solver_at_times #type tp.List[float] List of timesteps at which + analyse_solver_at_timesteps #type tp.List[float] List of timesteps at which to produce output to analyse the solver at given timestep. This @@ -256,15 +264,19 @@ class LDDsimulation(object): df.info(colored("Start time stepping","green")) # write initial values to file. + self.timestep_num = 0 while self.t < self.T: - print(f"entering timestep t = self.t") + print(f"entering timestep ", + "{number:.{digits}f}".format(number = self.timestep_num, digits = 4), + f"t = {self.t}") # check if the solver should beanalised or not. - if analyse_solver_at_times is not None and np.isin(self.t, analyse_solver_at_times): + if analyse_solver_at_timesteps is not None and np.isin(self.timestep_num, analyse_solver_at_timesteps): self.LDDsolver(debug = False, analyse_timestep = True) else: self.LDDsolver(debug = False, analyse_timestep = False) self.t += self.timestep_size + self.timestep_num += 1 # write solutions to files. for subdom_ind, subdomain in self.subdomain.items(): subdomain.write_solution_to_xdmf(# @@ -272,6 +284,28 @@ class LDDsimulation(object): time = self.t,# write_iter_for_fixed_time = False, ) + # if we have an exact solution, write out the |u -uh|_L2 to see the + # absolute error. + if self.exact_solution is not None: + L2errornorm = dict() + for phase in subdomain.has_phases: + #error = df.Function(subdomain.function_space[phase]) + # error.assign(subdomain.pressure[phase] - subdomain.pressure_prev_iter[phase]) + pa_exact = self.exact_solution_expr[subdom_ind][phase] + pa_exact.t = self.t + error_calculated = df.errornorm(pa_exact, subdomain.pressure[phase], 'L2', degree_rise=6) + L2errornorm.update( + {phase: error_calculated} + ) + errornorm_filename = self.output_dir+self.output_filename_parameter_part[subdom_ind]+\ + "_L2_errornorms_over_time" +".csv" + self.write_errornorms_to_csv( + filename = errornorm_filename, # + subdomain_index = subdom_ind, + errors = L2errornorm, + ) + + df.info("Finished") df.info("Elapsed time:"+str(timer.elapsed()[0])) @@ -311,7 +345,9 @@ class LDDsimulation(object): # create xdmf files for writing out iterations if analyse_timestep is # given. if analyse_timestep: - filename = self.output_dir+"subdomain"+"{}_".format(ind)+ "iterations_at_time"+ "{}".format(time) +".xdmf" + filename = self.output_dir+self.output_filename_parameter_part[ind]\ + + "solution_iterations_at_t"\ + + "{number:.{digits}f}".format(number=time, digits=2) +".xdmf" solution_over_iteration_within_timestep.update( # {ind: SolutionFile(self._mpi_communicator, filename)} ) @@ -376,26 +412,34 @@ class LDDsimulation(object): subsequent_iter_error.update( {phase: error_calculated} ) - print(f"the subsequent error in iteration {iteration} is {subsequent_iter_error[phase]}") + if debug: + print(f"the subsequent error in iteration {iteration} is {subsequent_iter_error[phase]}") if analyse_timestep: - # - subsequent_errors_over_iteration[sd_index].update( - { phase: error }) - subsequent_error_filename = self.output_dir+"subdomain"+"{}_".format(sd_index)+\ - "subsequent_iteration_error_for_phase_"+"{}".format(phase)+"_at_time"+ "{}".format(time) +".csv" - self.write_subsequent_errors( + # save the calculated L2 errors to csv file for plotting + # with pgfplots. + print(f"t = {self.t} the subsequent error in iteration {iteration} is {subsequent_iter_error[phase]}") + subsequent_error_filename = self.output_dir\ + +self.output_filename_parameter_part[sd_index]\ + +"subsequent_iteration_errors" +"_at_time"+\ + "{number:.{digits}f}".format(number=time, digits=2) +".csv" + self.write_subsequent_errors_to_csv( filename = subsequent_error_filename, # subdomain_index = sd_index, - subsequent_errors = subsequent_iter_error, + errors = subsequent_iter_error, time = time) + # this saves the actual difference function between subsequent + # iterations to analyse then in paraview later. + subsequent_errors_over_iteration[sd_index].update( + { phase: error }) + # both phases should be done before we mark the subdomain as # finished. total_subsequent_iter_error = max(subsequent_iter_error.values()) # check if error criterion has been met - error_criterion = subdomain.mesh.hmin()**2*subdomain.timestep_size + error_criterion = min(1E-9, subdomain.mesh.hmin()**2*subdomain.timestep_size) if debug: print(f" total_subsequent_error in iter {iteration} = {total_subsequent_iter_error }\n") print(f"the grid size on subdomain{sd_index} is h={subdomain.mesh.hmin()}") @@ -440,6 +484,7 @@ class LDDsimulation(object): iteration += 1 # end iteration while loop. + def Lsolver_step(self, subdomain_index: int,# debug: bool = False) -> None: """ L-scheme solver iteration step for an object of class subdomain @@ -518,6 +563,7 @@ class LDDsimulation(object): each subdomain. """ # set up solution file names for each subdomain. + self.output_filename_parameter_part = dict() self.solution_file = dict() for subdom_ind, subdomain in self.subdomain.items(): tau = subdomain.timestep_size @@ -525,32 +571,36 @@ class LDDsimulation(object): h = subdomain.mesh.hmin() if subdomain.isRichards: Lam = subdomain.lambda_param['wetting'] - name1 ="solution_subdomain" + "{}_".format(subdom_ind) + name1 ="subdomain" + "{}".format(subdom_ind) # only show three digits of the mesh size. - name2 = "dt" + "{}".format(tau)+"_hmin" + "{number:.{digits}f}".format(number=h, digits=3) + name2 = "_dt" + "{}".format(tau)+"_hmin" + "{number:.{digits}f}".format(number=h, digits=3) name3 = "_lambda" + "{}".format(Lam) + "_Lw" + "{}".format(L["wetting"]) - filename = self.output_dir + name1 + name2 + name3 +".xdmf" + filename_param_part = name1 + name2 + name3 + filename = self.output_dir + filename_param_part + "_solution" +".xdmf" else: Lam_w = subdomain.lambda_param['wetting'] Lam_nw = subdomain.lambda_param['nonwetting'] - filename = self.output_dir+"solution_subdomain" + "{}_".format(subdom_ind)\ - +"dt" + "{}".format(tau)\ + filename_param_part = "subdomain" + "{}".format(subdom_ind)\ + +"_dt" + "{}".format(tau)\ +"_hmin" + "{number:.{digits}f}".format(number=h, digits=3)\ +"_lambda_w" + "{}".format(Lam_w)\ +"_lambda_nw" + "{}".format(Lam_nw)\ +"_Lw" + "{}".format(L["wetting"])\ - +"_Lnw" + "{}".format(L["nonwetting"])\ - +".xdmf" + +"_Lnw" + "{}".format(L["nonwetting"]) + filename = self.output_dir+"_solution" +".xdmf" # create solution files and populate dictionary. + self.output_filename_parameter_part.update( + {subdom_ind: filename_param_part} + ) self.solution_file.update( # {subdom_ind: SolutionFile(self._mpi_communicator, filename)} ) - def write_subsequent_errors(self,# + def write_subsequent_errors_to_csv(self,# filename: str, # subdomain_index: int,# - subsequent_errors,#: tp.Dict[str: float],# + errors: tp.Dict[str, float],# time: float = None) -> None: """ write subsequent errors to csv file for plotting with pgfplots""" # in case no time is given, use the time of the class. @@ -565,14 +615,48 @@ class LDDsimulation(object): self.errors = pd.DataFrame({ "iteration": iteration, #"th. initial mass": df.assemble(rho*df.dx), \ #"energy": self.total_energy(), \ - "wetting": subsequent_errors["wetting"]}, index=[iteration]) + "wetting": errors["wetting"]}, index=[iteration]) else: self.errors = pd.DataFrame({"iteration":iteration, #\ #"th. initial mass": df.assemble(rho*df.dx), \ #"energy": self.total_energy(), \ - "wetting": subsequent_errors["wetting"], - "nonwetting": subsequent_errors["nonwetting"]}, index=[iteration]) + "wetting": errors["wetting"], + "nonwetting": errors["nonwetting"]}, index=[iteration]) + # if self._rank == 0: + # check if file exists + if os.path.isfile(filename) == True: + with open(filename, 'a') as f: + self.errors.to_csv(f, header=False, sep='\t', encoding='utf-8', index=False) + else: + self.errors.to_csv(filename, sep='\t', encoding='utf-8', index=False) + + def write_errornorms_to_csv(self,# + filename: str, # + subdomain_index: int,# + errors: tp.Dict[str, float],# + ) -> None: + """ write subsequent errors to csv file for plotting with pgfplots""" + # in case no time is given, use the time of the class. + subdomain = self.subdomain[subdomain_index] + time = self.t + timestep = self.timestep_num + + subdomain = self.subdomain[subdomain_index] + # iteration = subdomain.iteration_number + + if subdomain.isRichards: + self.errors = pd.DataFrame({ "time": self.t, + "timestep": self.timestep_num, + #"th. initial mass": df.assemble(rho*df.dx), \ + #"energy": self.total_energy(), \ + "wetting": errors["wetting"]}, index=[timestep]) + + else: + self.errors = pd.DataFrame({ "time": self.t, + "timestep": self.timestep_num, + "wetting": errors["wetting"], + "nonwetting": errors["nonwetting"]}, index=[timestep]) # if self._rank == 0: # check if file exists if os.path.isfile(filename) == True: @@ -866,7 +950,7 @@ class LDDsimulation(object): # subdomain.outer_boundary[j]['nonwetting'] return # the actual expression needed for the dirichlet condition for both phases if present. for index, boundary in enumerate(subdomain.outer_boundary): - if np.abs(time) < self.tol: + if np.abs(time-self.t_initial) < self.tol: # Here the dictionary has to be created first because t = 0. # create a dictionary of dictionaries for each subdomain self.outerBC.update({num: dict()}) @@ -885,7 +969,7 @@ class LDDsimulation(object): boundary_marker_value = index+1 for phase in subdomain.has_phases: # note that the default interpolation degree is 2 - if np.abs(time) < self.tol : + if np.abs(time - self.t_initial) < self.tol : # time = 0 so the Dolfin Expression has to be created first. pDCa = df.Expression(pDC[phase], domain = mesh, degree = interpolation_degree, t=time) self.dirichletBC_dfExpression[num][index].update({phase: pDCa}) @@ -900,6 +984,27 @@ class LDDsimulation(object): print("subdomain is an inner subdomain and has no outer boundary.\n", "no Dirichlet boundary has been set.") + def _init_exact_solution_expression(self): + """ initialise dolfin expressions for exact solution and populate + self.exact_solution_expr dictionary. This is used to calculate errornorms + in the case of an exact solution. + """ + if self.exact_solution is not None: + for sd_ind, subdomain in self.subdomain.items(): + for phase in subdomain.has_phases: + if np.abs(self.t-self.t_initial) < self.calc_tol: + # here t = 0 and we have to initialise the sources. + mesh = subdomain.mesh + # p0 contains both pw_0 and pnw_0 for subdomain[subdomain_index] + pa_exact = self.exact_solution[sd_ind][phase] + self.exact_solution_expr.update({sd_ind: dict()}) + # note that the default interpolation degree is 2 + self.exact_solution_expr[sd_ind].update( + { phase: df.Expression(pa_exact, domain = mesh, degree=self.interpolation_degree, t=self.t) } + ) + else: + pass + def _eval_sources(self, subdomain_index: int, # interpolation_degree: int = None, # time: float = 0,# @@ -911,7 +1016,7 @@ class LDDsimulation(object): subdomain = self.subdomain[subdomain_index] for phase in subdomain.has_phases: - if np.abs(time) < self.calc_tol: + if np.abs(time-self.t_initial) < self.calc_tol: # here t = 0 and we have to initialise the sources. mesh = subdomain.mesh # p0 contains both pw_0 and pnw_0 for subdomain[subdomain_index] @@ -928,6 +1033,18 @@ class LDDsimulation(object): # note that the default interpolation degree is 2 subdomain.source[phase].t = time + def _add_parameters_to_output_dirname(self): + """ function to create a new output directory for given set of input + parameters and adjust self.output_dir accordingly + """ + dirname = "mesh_res" + "{}_".format(self.mesh_resolution)\ + + "dt" + "{}".format(self.timestep_size) + "/" + self.output_dir += dirname + + if not os.path.exists(self.output_dir): + os.mkdir(self.output_dir) + print(f"\nwill save output of this simulation to path {self.output_dir}") + # https://github.com/geo-fluid-dynamics/phaseflow-fenics # adapted from Lucas Ostrowski diff --git a/LDDsimulation/domainPatch.py b/LDDsimulation/domainPatch.py index deae328..8b3ce51 100644 --- a/LDDsimulation/domainPatch.py +++ b/LDDsimulation/domainPatch.py @@ -288,7 +288,7 @@ class DomainPatch(df.SubDomain): interface_forms = [] # the marker values of the interfacese are global interfaces index + 1 for interface in self.has_interface: - print(f"subdomain{self.subdomain_index} has interfaces: {interface}\n") + # print(f"subdomain{self.subdomain_index} has interfaces: {interface}\n") marker_value = self.interface[interface].marker_value # interface_forms += (dt*Lambda_a*pa*phi_a)*ds(interface) interface_forms.append((dt*Lambda_a*pa*phi_a)*ds(marker_value)) @@ -665,18 +665,18 @@ class DomainPatch(df.SubDomain): mesh_data = self.mesh.data() # local to parent vertex index map self.parent_mesh_index = mesh_data.array('parent_vertex_indices',0) - print(f"on subdomain{self.subdomain_index} parent_vertex_indices: {self.parent_mesh_index}") + # print(f"on subdomain{self.subdomain_index} parent_vertex_indices: {self.parent_mesh_index}") self.dof2vertex = dict() self.vertex2dof = dict() for phase in self.has_phases: self.dof2vertex.update(# {phase :df.dof_to_vertex_map(self.function_space[phase])}# ) - print(f"on subdomain{self.subdomain_index} dof2vertex: {self.dof2vertex[phase]}") + # print(f"on subdomain{self.subdomain_index} dof2vertex: {self.dof2vertex[phase]}") self.vertex2dof.update(# {phase :df.vertex_to_dof_map(self.function_space[phase])}# ) - print(f"on subdomain{self.subdomain_index} vertex2dof: {self.vertex2dof[phase]}") + # print(f"on subdomain{self.subdomain_index} vertex2dof: {self.vertex2dof[phase]}") def _init_markers(self) -> None: """ define boundary markers @@ -1124,13 +1124,13 @@ class Interface(BoundaryPart): """ interface_vertex_indices = self._vertex_indices(interface_marker, interface_marker_value, print_vertex_indices = False) - print(f"local interface vertices: {interface_vertex_indices}") + # print(f"local interface vertices: {interface_vertex_indices}") dof2vertex = df.dof_to_vertex_map(function_space) - print(f"dof2vertex map: {dof2vertex}\n") + # print(f"dof2vertex map: {dof2vertex}\n") # check which dofs actually lie on the interface using the dof2vertex map. is_a_dof_on_interface = np.isin(dof2vertex, interface_vertex_indices, assume_unique=True) - print(f"is_a_dof_on_interface: {is_a_dof_on_interface}") - print(f"this means the following dofs are interface dofs:", np.nonzero(is_a_dof_on_interface)[0]) + # print(f"is_a_dof_on_interface: {is_a_dof_on_interface}") + # print(f"this means the following dofs are interface dofs:", np.nonzero(is_a_dof_on_interface)[0]) return np.nonzero(is_a_dof_on_interface)[0] def init_interface_values(self,# diff --git a/RR-2-patch-test-case/RR-2-patch-test.py b/RR-2-patch-test-case/RR-2-patch-test.py index c61dff9..5857fe0 100755 --- a/RR-2-patch-test-case/RR-2-patch-test.py +++ b/RR-2-patch-test-case/RR-2-patch-test.py @@ -84,10 +84,40 @@ isRichards = { 2: True } -Tmax = 1 -timestep_size = 0.005 +##################### MESH ##################################################### +mesh_resolution = 40 +##################### TIME ##################################################### +timestep_size = 2*0.0001 +number_of_timesteps = 300 +# decide how many timesteps you want analysed. Analysed means, that we write out +# subsequent errors of the L-iteration within the timestep. +number_of_timesteps_to_analise = 7 +starttime = 0 + +# We want to write out csv files containing subsequent L2 errors of iterations for +# number_of_timesteps_to_analise many timesteps. We want to do this with +# analyse_timesteps = np.linspace(starttime, number_of_timesteps, number_of_timesteps_to_analise) +# see below. Therefor, we need to check if (number_of_timesteps_to_analise-1) is +# a divisor of number_of_timesteps, +if number_of_timesteps_to_analise == 0: + analyse_timesteps = None +elif number_of_timesteps_to_analise == 1: + analyse_timesteps = [0] +else: + if not number_of_timesteps%(number_of_timesteps_to_analise-1) == 0: + # if number_of_timesteps%(number_of_timesteps_to_analise-1) is not 0, we + # round the division error to the nearest integer and redefine number_of_timesteps + print(f"since number_of_timesteps/number_of_timesteps_to_analise = {number_of_timesteps/number_of_timesteps_to_analise}", + "is not an integer,\n") + new_analysing_interval = int(round(number_of_timesteps/(number_of_timesteps_to_analise-1))) + number_of_timesteps = new_analysing_interval*(number_of_timesteps_to_analise-1) + print(f"I'm resetting number_of_timesteps = {number_of_timesteps}\n") + analyse_timesteps = np.linspace(0, number_of_timesteps, number_of_timesteps_to_analise) + +Tmax = number_of_timesteps*timestep_size +time_interval = [starttime, Tmax] +print(f"The simulation interval is [{starttime}, {Tmax}]") -time_interval = [0, Tmax] viscosity = {# # subdom_num : viscosity @@ -109,8 +139,8 @@ L = {# lambda_param = {# # subdom_num : lambda parameter for the L-scheme - 1 : {'wetting' :100},# - 2 : {'wetting' :100} + 1 : {'wetting' :160},# + 2 : {'wetting' :160} } ## relative permeabilty functions on subdomain 1 @@ -190,8 +220,6 @@ write_to_file = { 'L_iterations': True } -mesh_resolution = 30 - # initialise LDD simulation class simulation = ldd.LDDsimulation(tol = 1E-12) simulation.set_parameters(output_dir = "./output/",# @@ -212,348 +240,11 @@ simulation.set_parameters(output_dir = "./output/",# sources = source_expression,# initial_conditions = initial_condition,# dirichletBC_Expressions = dirichletBC,# - exact_solution_case = True,# + exact_solution = exact_solution,# write2file = write_to_file,# ) simulation.initialise() -# simulation._init_meshes_and_markers(subdomain_def_points, mesh_resolution=2) -# subdomain marker functions -# output_dir = simulation.output_dir -# domain_marker = simulation.domain_marker -# mesh_subdomain = simulation.mesh_subdomain - - -# mesh = mesh_subdomain[0] -# interface_marker = df.MeshFunction('int', mesh, mesh.topology().dim()-1) -# interface_marker.set_all(0) -# interface = dp.Interface(vertices=interface_def_points[0], # -# tol=mesh.hmin()/100,# -# internal=True,# -# adjacent_subdomains = adjacent_subdomains[0]) -# print("interface vertices are: \n", interface.vertices) -# interface.mark(interface_marker, 1) -# simulation._init_interfaces(interface_def_points, adjacent_subdomains) - -# interface = simulation.interface -# interface_marker = simulation.interface_marker -# -# subdoms = simulation.subdomain - -# df.File('./subdomain1_interface_marker.pvd') << simulation.subdomain[1].interface_marker -# df.File('./subdomain2_interface_marker.pvd') << simulation.subdomain[2].interface_marker -# df.File('./test_subdomain1_boundary_marker.pvd') << boundary_marker1 -# df.File('./test_subdomain2_boundary_marker.pvd') << boundary_marker2 -analyse_timesteps = [0, 100*timestep_size, 1, 2, 3] simulation.run(analyse_timesteps) # simulation.LDDsolver(time = 0, debug = True, analyse_timestep = True) # df.info(parameters, True) - -# for iterations in range(1): -# # -# -# a1 = (L1*u1*v1)*dx1 + (df.inner(relative_permeability(saturation(p1_i, 1), 1)*df.grad(u1), df.grad(v1)))*dx_1 + (timestep*lambda1*u1*v1)*ds1(1) #timestep* -# rhs1 = (L1*p1_i*v1)*dx1 - ((saturation(p1_i, 1) - saturation(p1_0, 1))*v1)*dx1 + (timestep*(source1 - g1_i)*v1)*ds1(1) -# rhssplit1 = (L1*p1_i*v1)*dx1 - ((saturation(p1_i, 1) - saturation(p1_0, 1))*v1)*dx1 -# extratrem = (timestep*(source1 - g1_i)*v1)*ds1(1) -# splitrhs = df.assemble(rhssplit1) -# print("splitrhs: \n", splitrhs.get_local()) -# extrat_assembled = df.assemble(extratrem) -# print("extratrem: \n", extrat_assembled.get_local()) -# added = splitrhs + extrat_assembled -# print("both added together:\n", added.get_local()) -# -# A1 = df.assemble(a1) -# dsform = (timestep*lambda1*u1*v1)*ds1(1) -# dsform_vec = df.assemble(dsform) -# b1 = df.assemble(rhs1) -# #p_gamma1.apply(A1,b1) -# # outerBC1.apply(A1,b1) -# u = df.Function(V1) -# U1 = u.vector() -# df.solve(A1,U1,b1) -# # print("Form:\n", A1.array()) -# print("RHS:\n", b1.get_local()) -# #print("ds term:\n", dsform_vec.array()) -# # print('solution:\n', U1.get_local()) -# p1_i.vector()[:] = U1 -# interface[0].read_pressure_dofs(from_function = p1_i, # -# interface_dofs = dofs_on_interface1,# -# dof_to_vert_map = dom1_d2v,# -# local_to_parent_vertex_map = dom1_parent_vertex_indices,# -# phase = 'wetting',# -# subdomain_ind = 1) -# # -# # Save mesh to file -# df.File('./test_domain_layered_soil.xml.gz') << mesh_subdomain[0] -# df.File('./test_domain_mesh.pvd') << mesh_subdomain[0] -# df.File('./test_global_interface_marker.pvd') << interface_marker -# df.File('./test_subdomain1.xml.gz') << mesh_subdomain[1] -# df.File('./test_subdomain2.xml.gz') << mesh_subdomain[2] -# df.File('./test_domain_marker.pvd') << domain_marker -# df.File('./test_domain_layered_soil_solution.pvd') << u -# df.File('./test_subdomain1_interface_marker.pvd') << interface_marker1 -# df.File('./test_subdomain2_interface_marker.pvd') << interface_marker2 -# df.File('./test_subdomain1_boundary_marker.pvd') << boundary_marker1 -# df.File('./test_subdomain2_boundary_marker.pvd') << boundary_marker2 - -# boundary_marker1 = simulation.subdomain[1].outer_boundary_marker -# boundary_marker2 = simulation.subdomain[2].outer_boundary_marker -# dx_1 = simulation.subdomain[1].dx -# dx_2 = simulation.subdomain[2].dx -# ds_1 = simulation.subdomain[1].ds -# ds_2 = simulation.subdomain[2].ds -# -# interface_marker1 = simulation.subdomain[1].interface_marker#df.MeshFunction('int', mesh_subdomain[1], mesh_subdomain[1].topology().dim()-1) -# interface_marker2 = simulation.subdomain[2].interface_marker#df.MeshFunction('int', mesh_subdomain[2], mesh_subdomain[2].topology().dim()-1) -# # interface_marker1.set_all(0) -# # interface_marker2.set_all(0) -# # print(dir(interface_marker1)) -# -# interface[0].mark(interface_marker1, 1) -# interface[0].mark(interface_marker2, 1) -# # interface_marker1 = simulation.subdomain[1].boundary_marker -# -# # domain measures -# -# # dx1 = simulation.subdomain[1].dx -# dx1 = df.Measure('dx', domain = mesh_subdomain[1]) -# dx2 = df.Measure('dx', domain = mesh_subdomain[2]) -# -# # boundary measures -# ds1 = df.Measure('ds', domain = mesh_subdomain[1], subdomain_data = interface_marker1) -# ds2 = df.Measure('ds', domain = mesh_subdomain[2], subdomain_data = interface_marker2) -# -# V1 = df.FunctionSpace(mesh_subdomain[1], 'P', 1) -# p1_exact = df.Expression('1.0 - (1.0 + t*t)*(1.0 + x[0]*x[0] + x[1]*x[1])', domain = mesh_subdomain[1], degree = 2, t = 0) -# -# coordinates = mesh_subdomain[0].coordinates() -# print("global mesh coordinates of domain: \n", coordinates) -# coordinates1 = mesh_subdomain[1].coordinates() -# -# coordinates2 = mesh_subdomain[2].coordinates() -# submesh1_data = mesh_subdomain[1].data() -# dom1_parent_vertex_indices = submesh1_data.array('parent_vertex_indices',0) -# # print("map of dom1 vertices to parent vertices on global domain:\n", dom1_parent_vertex_indices) -# # -# # coordinates2 = mesh_subdomain[2].coordinates() -# # print("\nvertices of subdomain2: \n", coordinates2) -# submesh2_data = mesh_subdomain[2].data() -# dom2_parent_vertex_indices = submesh2_data.array('parent_vertex_indices',0) -# # print("'parent_vertex_indices',1 \n") -# # -# # -# # print("on domain: \n") -# # interface_coordinates = interface[0].coordinates(interface_marker, 1, print_coordinates = True) -# # interface_coordinates = interface[0]._vertex_indices(interface_marker, 1, print_vertex_indices = True) -# # print("\non subdomain2: \n") -# # dom2_interface_coordinates = interface[0].coordinates(interface_marker2, 1, print_coordinates = True) -# dom2_interface_def_points = interface[0]._vertex_indices(interface_marker2, 1, print_vertex_indices = True) -# -# -# -# dofs_on_interface1 = interface[0].dofs_on_interface(V1, interface_marker1, 1) -# print("Dofs on Interface dom1", dofs_on_interface1) -# -# V2 = df.FunctionSpace(mesh_subdomain[2], 'P', 1) -# dofs_on_interface2 = interface[0].dofs_on_interface(V2, interface_marker2, 1) -# # print("Dofs on Interface dom1", dofs_on_interface2) -# -# # markermesh = interface_marker2.mesh() -# # functionSpaceMesh = V2.mesh() -# # print("Domain 2 mesh extracted from markerfunction:\n", markermesh.coordinates()) -# # print("Domain 2 mesh extracted from Function Space V2:\n", functionSpaceMesh.coordinates()) -# -# dom1_d2v = df.dof_to_vertex_map(V1) -# dom1_v2d = df.vertex_to_dof_map(V1) -# # print("dof to vertex map for V1:\n", dom1_d2v) -# # print("vertex to dof map for V1:\n", dom1_v2d) -# dom2_d2v = df.dof_to_vertex_map(V2) -# dom2_v2d = df.vertex_to_dof_map(V2) -# # print("dof to vertex map for V2:\n", dom2_d2v) -# # print("vertex to dof map for V2:\n", dom2_v2d) -# -# testf1 = df.Constant(41) -# f1test = df.interpolate(testf1, V1) -# testf2 = df.Constant(42) -# f2test = df.interpolate(testf2, V2) -# -# # f1vec = f1test.compute_vertex_values() -# # for i in range(len(f1vec)): -# # f1vec[i] = i -# -# # f1test.vector()[:] = f1vec -# # f1nodal = f1test.vector().get_local() -# # for i in range(len(f1nodal)): -# # f1nodal[i] = i -# -# # print("nodal values of f1nodal\n", f1nodal) -# -# # -# # print('dofs on interface \n', f1vec[dofs_on_interface]) -# # f1test.vector()[:] = f1vec -# # print("f1test.vector()[:]\n", f1test.vector()[:]) -# # print("f1test.vector()[dofs_on_interface]\n", f1test.vector()[dofs_on_interface]) -# -# # print("constant function on dom1\n", f1vec) -# # -# # for i in dofs_on_interface1: -# # print("local dof ind %i, parent = %i", i,dom1_parent_vertex_indices[dom1_d2v[i]]) -# # # f1test.vector() is enumerated by dof not by vertex -# # f1test.vector()[i] = i -# # # this enumerates according to the dof numbering -# # print("testfunction f1test with set interface values\n", f1test.vector()[:]) -# # print("testfunction f1test with get_local\n", f1test.vector().get_local()) -# # f1test.vector()[dom1_v2d[dom1_d2v[dofs_on_interface]]] = f1vec[dofs_on_interface] -# # .vector()[:] and .vector().get_local() order values according to the vertex numbering -# # print("testfunction f1test with compute_vertex_values\n", f1test.compute_vertex_values()) -# # print("testfunction f1test with compute_vertex_values mit d2vmap\n", f1test.compute_vertex_values()[dom1_d2v[:]]) -# # i=0 -# # for x in coordinates1: -# # print(f"vertex {i}: f1test[{dom1_v2d[i]}] = {f1test.vector()[dom1_v2d[i]]}\tu({x}) = {f1test(x)}") -# # i += 1 -# # print("\non subdomain1: \n") -# print("vertices of subdomain1: \n", coordinates1) -# # dom1_interface_coordinates = interface[0].coordinates(interface_marker1, 1, print_coordinates = True) -# dom1_interface_def_points = interface[0]._vertex_indices(interface_marker1, 1, print_vertex_indices = True) -# -# interface[0].read_pressure_dofs(from_function = f1test, # -# interface_dofs = dofs_on_interface1,# -# dof_to_vert_map = dom1_d2v,# -# local_to_parent_vertex_map = dom1_parent_vertex_indices,# -# phase = 'wetting', -# subdomain_ind = 1) -# -# interface[0].write_pressure_dofs(to_function = f2test, # -# interface_dofs = dofs_on_interface2,# -# dof_to_vert_map = dom2_d2v,# -# local_to_parent_vertex_map = dom2_parent_vertex_indices,# -# phase = 'wetting', -# subdomain_ind = 2) -# -# i=0 -# for x in coordinates2: -# print(f"vertex {i}: f2test[{dom2_v2d[i]}] = {f2test.vector()[dom2_v2d[i]]}\tu({x}) = {f2test(x)}") -# i += 1 -# print("\non subdomain2: \n") -# print("vertices of subdomain2: \n", coordinates2) -# -# # dom2_interface_coordinates = interface[0].coordinates(interface_marker2, 1, print_coordinates = True) -# dom2_interface_def_points = interface[0]._vertex_indices(interface_marker2, 1, print_vertex_indices = True) -# print("Parent indices", dom2_parent_vertex_indices) -# -# -# u1 = df.TrialFunction(V1) -# v1 = df.TestFunction(V1) -# -# u2 = df.TrialFunction(V2) -# v2 = df.TestFunction(V2) -# -# def relative_permeability(s, subdomain_index): -# if subdomain_index == 1: -# # relative permeabilty on subdomain1 -# return s**2 -# else: -# # relative permeabilty on subdomain2 -# return s**3 -# -# def saturation(pressure, subdomain_index): -# # inverse capillary pressure-saturation-relationship -# return df.conditional(pressure < 0, 1/((1 - pressure)**(1/(subdomain_index + 1))), 1) -# -# -# # exact solution -# # cell = df.Cell("triangle", 2) -# # x1 = df.SpatialCoordinate(mesh_subdomain[1]) -# # x2 = df.SpatialCoordinate(mesh_subdomain[2]) -# -# p2_exact = df.Expression('1.0 - (1.0 + t*t)*(1.0 + x[1]*x[1])', domain = mesh_subdomain[2], degree = 2, t = 0) -# p1_e = df.interpolate(p1_exact, V1) -# p2_e = df.interpolate(p2_exact, V2) -# # -# # initial conditions -# p1_initial = df.Expression('-(x[0]*x[0] + x[1]*x[1])', domain = mesh_subdomain[1], degree = 2) -# p2_initial = df.Expression('-x[1]*x[1]', domain = mesh_subdomain[2], degree = 2) -# p1_0 = df.interpolate(p1_initial, V1) -# p2_0 = df.interpolate(p2_initial, V2) -# -# # Initial boundary value for the pressure on interface -# p_gamma1 = df.DirichletBC(V1, p1_exact, interface_marker1, 1) -# p_gamma2 = df.DirichletBC(V2, p2_exact, interface_marker2, 1) -# -# outerBC1 = df.DirichletBC(V1, p1_exact, boundary_marker1, 1) -# outerBC2 = df.DirichletBC(V2, p2_exact, boundary_marker2, 1) -# -# -# ### source terms -# # source1 = df.Expression('4.0/pow(1 + x[0]*x[0] + x[1]*x[1], 2) - t/sqrt( pow(1 + t*t, 3)*(1 + x[0]*x[0] + x[1]*x[1]) )', domain = mesh_subdomain[1], degree = 2, t = 0) -# # source2 = df.Expression('2.0*(1-x[1]*x[1])/pow(1 + x[1]*x[1], 2) - 2*t/(3*pow( pow(1 + t*t, 4)*(1 + x[1]*x[1]), 1/3))', domain = mesh_subdomain[2], degree = 2, t = 0) -# source1 = df.Expression(source_expression[1]['wetting'], domain = mesh_subdomain[1], degree = 2, t = 0) -# source2 = df.Expression('2.0*(1-x[1]*x[1])/pow(1 + x[1]*x[1], 2) - 2*t/(3*pow( pow(1 + t*t, 4)*(1 + x[1]*x[1]), 1/3))', domain = mesh_subdomain[2], degree = 2, t = 0) -# -# source1h = df.interpolate(source1, V1) -# source2h = df.interpolate(source2, V2) -# -# L1 = 0.25 -# L2 = L1 -# timestep = 0.1 -# lambda1 = 4 -# lambda2 = lambda1 -# # initial iteartion -# p1_i = p1_0 -# p2_i = p2_0 -# # initial g_i -# n1 = df.FacetNormal(mesh_subdomain[1]) -# flux = -df.grad(p1_0) -# gl0 = (df.dot(flux, n1) - lambda1*p1_0)*v1*ds1(1) -# print('gl0 term assembliert', df.assemble(gl0).get_local()) -# g1_i = -lambda1*p1_i -# g2_i = -lambda1*p2_i - -# for iterations in range(1): -# # -# -# a1 = (L1*u1*v1)*dx1 + (df.inner(relative_permeability(saturation(p1_i, 1), 1)*df.grad(u1), df.grad(v1)))*dx_1 + (timestep*lambda1*u1*v1)*ds1(1) #timestep* -# rhs1 = (L1*p1_i*v1)*dx1 - ((saturation(p1_i, 1) - saturation(p1_0, 1))*v1)*dx1 + (timestep*(source1 - g1_i)*v1)*ds1(1) -# rhssplit1 = (L1*p1_i*v1)*dx1 - ((saturation(p1_i, 1) - saturation(p1_0, 1))*v1)*dx1 -# extratrem = (timestep*(source1 - g1_i)*v1)*ds1(1) -# splitrhs = df.assemble(rhssplit1) -# print("splitrhs: \n", splitrhs.get_local()) -# extrat_assembled = df.assemble(extratrem) -# print("extratrem: \n", extrat_assembled.get_local()) -# added = splitrhs + extrat_assembled -# print("both added together:\n", added.get_local()) -# -# A1 = df.assemble(a1) -# dsform = (timestep*lambda1*u1*v1)*ds1(1) -# dsform_vec = df.assemble(dsform) -# b1 = df.assemble(rhs1) -# #p_gamma1.apply(A1,b1) -# # outerBC1.apply(A1,b1) -# u = df.Function(V1) -# U1 = u.vector() -# df.solve(A1,U1,b1) -# # print("Form:\n", A1.array()) -# print("RHS:\n", b1.get_local()) -# #print("ds term:\n", dsform_vec.array()) -# # print('solution:\n', U1.get_local()) -# p1_i.vector()[:] = U1 -# interface[0].read_pressure_dofs(from_function = p1_i, # -# interface_dofs = dofs_on_interface1,# -# dof_to_vert_map = dom1_d2v,# -# local_to_parent_vertex_map = dom1_parent_vertex_indices,# -# phase = 'wetting',# -# subdomain_ind = 1) -# # -# # Save mesh to file -# df.File('./test_domain_layered_soil.xml.gz') << mesh_subdomain[0] -# df.File('./test_domain_mesh.pvd') << mesh_subdomain[0] -# df.File('./test_global_interface_marker.pvd') << interface_marker -# df.File('./test_subdomain1.xml.gz') << mesh_subdomain[1] -# df.File('./test_subdomain2.xml.gz') << mesh_subdomain[2] -# df.File('./test_domain_marker.pvd') << domain_marker -# df.File('./test_domain_layered_soil_solution.pvd') << u -# df.File('./test_subdomain1_interface_marker.pvd') << interface_marker1 -# df.File('./test_subdomain2_interface_marker.pvd') << interface_marker2 -# df.File('./test_subdomain1_boundary_marker.pvd') << boundary_marker1 -# df.File('./test_subdomain2_boundary_marker.pvd') << boundary_marker2 diff --git a/RR-2-patch-test-case/plots/exact_solution_error_norms.tex b/RR-2-patch-test-case/plots/exact_solution_error_norms.tex new file mode 100644 index 0000000..8d7d343 --- /dev/null +++ b/RR-2-patch-test-case/plots/exact_solution_error_norms.tex @@ -0,0 +1,47 @@ +\documentclass[a4paper]{scrartcl}%scrartcl +\input{praeambels_and_definitions/artikelpraeambel.tex} +\input{praeambels_and_definitions/artikel_theoreme_und_farbe.tex} +%\input{praeambels_and_definitions/special_symbols.tex} +%%%% MAKROS %%%%%%%%%%%%% restriction +\input{./praeambels_and_definitions/L-Schema_Paper_makros.tex} +% set graphicspath +\graphicspath{ {./} } + +\usepackage{pgfplotstable} + +\begin{document} + % Generation of Profile_Error_new.png + \tikzsetnextfilename{Errornorm-exact-solution-over-time} + \tikzset{external/force remake} + \begin{tikzpicture} +% % \path[draw,dashed,thick] (3.13,0) -- (3.13,5.2); + \begin{axis}[% + width=\textwidth, + title={ $\bigl\|p_{w,l} - p_{w,l}^n\bigr\|_{L^2}$ over time $t$, $ h \approx 0.02$, $\tau = 2\cdot 10^{-4}$ }, + % axis lines=left, + % legend style = {draw=none}, + legend cell align = left, + xlabel= {timesteps}, + ylabel= {$\bigl\|p_{w,l} - p_{w,l}^n\bigr\|_{L^2}$}, +% xmin= 0, +% xmax= 53, +% ymin= 0, +% ymax= 0.0003, + grid= both, %major or minor + axis line style={-Latex[round]}, + legend style={ +% anchor=north east, +% at={(1,1)}, + font=\tiny + }, + legend entries={$\bigl\|p_{w,1} - p_{w,1}^{n}\bigr\|_{L^2(\dom_1)}$, + $\bigl\|p_{w,2} - p_{w,2}^{n}\bigr\|_{L^2(\dom_2)}$}, + ] % end of axis options %col sep=comma, + \addplot table [x=timestep, y=wetting] {../output/mesh_res30_dt0.004/subdomain1_dt0.004_hmin0.019_lambda70_Lw0.25_L2_errornorms_over_time.csv};% + \addplot table [x=timestep, y=wetting] {../output/mesh_res30_dt0.004/subdomain2_dt0.004_hmin0.019_lambda70_Lw0.25_L2_errornorms_over_time.csv};% +% % \addplot table [col sep=comma] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% +% % % \addplot table [col sep=comma] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% + \end{axis} + \end{tikzpicture} + +\end{document} diff --git a/RR-2-patch-test-case/plots/subsequent_errors.tex b/RR-2-patch-test-case/plots/subsequent_errors.tex index 2d98427..7df36b5 100644 --- a/RR-2-patch-test-case/plots/subsequent_errors.tex +++ b/RR-2-patch-test-case/plots/subsequent_errors.tex @@ -10,21 +10,21 @@ \usepackage{pgfplotstable} \begin{document} - % Generation of Profile_Error_new.png - \tikzsetnextfilename{Subsequent_errors_t0} + % Generation of Subsequent_errors_t0.00 + \tikzsetnextfilename{Subsequent_errors_t0.00} \tikzset{external/force remake} \begin{tikzpicture} % % \path[draw,dashed,thick] (3.13,0) -- (3.13,5.2); \begin{semilogyaxis}[% width=\textwidth, - title={ Subsequent errors for $t = 0$, $ h \approx 0.02$, $\tau = 2\cdot 10^{-4}$ }, + title={ Subsequent errors for $t = 0$, $ h \approx 0.02$, $\tau = 4\cdot 10^{-4}$ }, % axis lines=left, % legend style = {draw=none}, legend cell align = left, xlabel= {iterations}, ylabel= {subsequent errors}, xmin= 0, - xmax= 53, +% xmax= 53, % ymin= 0, % ymax= 0.0003, grid= both, %major or minor @@ -37,8 +37,110 @@ legend entries={$\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_1)}$, $\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_2)}$}, ] % end of axis options %col sep=comma, - \addplot table [x=iteration, y=wetting] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% - \addplot table [x=iteration, y=wetting] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain1_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.00.csv};% + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain2_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.00.csv};% +% \addplot table [col sep=comma] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% +% % \addplot table [col sep=comma] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% + \end{semilogyaxis} + \end{tikzpicture} + + % Generation of Subsequent_errors_t0.00 + \tikzsetnextfilename{Subsequent_errors_t0.05} + \tikzset{external/force remake} + \begin{tikzpicture} +% % \path[draw,dashed,thick] (3.13,0) -- (3.13,5.2); + \begin{semilogyaxis}[% + width=\textwidth, + title={ Subsequent errors for $t = 0.05$, $ h \approx 0.02$, $\tau = 4\cdot 10^{-4}$ }, + % axis lines=left, + % legend style = {draw=none}, + legend cell align = left, + xlabel= {iterations}, + ylabel= {subsequent errors}, +% xmin= 0, +% xmax= 53, +% ymin= 0, +% ymax= 0.0003, + grid= both, %major or minor + axis line style={-Latex[round]}, + legend style={ +% anchor=north east, +% at={(1,1)}, + font=\tiny + }, + legend entries={$\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_1)}$, + $\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_2)}$}, + ] % end of axis options %col sep=comma, + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain1_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.05.csv};% + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain2_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.05.csv};% +% \addplot table [col sep=comma] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% +% % \addplot table [col sep=comma] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% + \end{semilogyaxis} + \end{tikzpicture} + + % Generation of Subsequent_errors_t0.00 + \tikzsetnextfilename{Subsequent_errors_t0.1} + \tikzset{external/force remake} + \begin{tikzpicture} +% % \path[draw,dashed,thick] (3.13,0) -- (3.13,5.2); + \begin{semilogyaxis}[% + width=\textwidth, + title={ Subsequent errors for $t = 0.1$, $ h \approx 0.02$, $\tau = 4\cdot 10^{-4}$ }, + % axis lines=left, + % legend style = {draw=none}, + legend cell align = left, + xlabel= {iterations}, + ylabel= {subsequent errors}, +% xmin= 0, +% xmax= 53, +% ymin= 0, +% ymax= 0.0003, + grid= both, %major or minor + axis line style={-Latex[round]}, + legend style={ +% anchor=north east, +% at={(1,1)}, + font=\tiny + }, + legend entries={$\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_1)}$, + $\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_2)}$}, + ] % end of axis options %col sep=comma, + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain1_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.10.csv};% + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain2_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.10.csv};% +% \addplot table [col sep=comma] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% +% % \addplot table [col sep=comma] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% + \end{semilogyaxis} + \end{tikzpicture} + + % Generation of Subsequent_errors_t0.00 + \tikzsetnextfilename{Subsequent_errors_t0.14} + \tikzset{external/force remake} + \begin{tikzpicture} +% % \path[draw,dashed,thick] (3.13,0) -- (3.13,5.2); + \begin{semilogyaxis}[% + width=\textwidth, + title={ Subsequent errors for $t = 0.14$, $ h \approx 0.02$, $\tau = 4\cdot 10^{-4}$ }, + % axis lines=left, + % legend style = {draw=none}, + legend cell align = left, + xlabel= {iterations}, + ylabel= {subsequent errors}, +% xmin= 0, +% xmax= 53, +% ymin= 0, +% ymax= 0.0003, + grid= both, %major or minor + axis line style={-Latex[round]}, + legend style={ +% anchor=north east, +% at={(1,1)}, + font=\tiny + }, + legend entries={$\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_1)}$, + $\bigl\|p_l^i - p_l^{i-1}\bigr\|_{L^2(\dom_2)}$}, + ] % end of axis options %col sep=comma, + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain1_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.14.csv};% + \addplot table [x=iteration, y=wetting] {../output/mesh_res30_dt0.004/subdomain2_dt0.004_hmin0.019_lambda70_Lw0.25subsequent_iteration_errors_at_time0.14.csv};% % \addplot table [col sep=comma] {../output/subdomain1_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% % % \addplot table [col sep=comma] {../output/subdomain2_subsequent_iteration_error_for_phase_wetting_at_time0.csv};% \end{semilogyaxis} diff --git a/TP-TP-patch-test-case/TP-TP-2-patch-test.py b/TP-TP-patch-test-case/TP-TP-2-patch-test.py index 1e9a7d5..6f120ff 100755 --- a/TP-TP-patch-test-case/TP-TP-2-patch-test.py +++ b/TP-TP-patch-test-case/TP-TP-2-patch-test.py @@ -87,10 +87,37 @@ isRichards = { 2: False } -Tmax = 1 -timestep_size = 4*0.001 -time_interval = [0, Tmax] +timestep_size = 4*0.001 +number_of_timesteps = 100 +# decide how many timesteps you want analysed. Analysed means, that we write out +# subsequent errors of the L-iteration within the timestep. +number_of_timesteps_to_analise = 5 +starttime = 0 + +# We want to write out csv files containing subsequent L2 errors of iterations for +# number_of_timesteps_to_analise many timesteps. We want to do this with +# analyse_timesteps = np.linspace(starttime, number_of_timesteps, number_of_timesteps_to_analise) +# see below. Therefor, we need to check if (number_of_timesteps_to_analise-1) is +# a divisor of number_of_timesteps, +if number_of_timesteps_to_analise == 0: + analyse_timesteps = None +elif number_of_timesteps_to_analise == 1: + analyse_timesteps = [0] +else: + if not number_of_timesteps%(number_of_timesteps_to_analise-1) == 0: + # if number_of_timesteps%(number_of_timesteps_to_analise-1) is not 0, we + # round the division error to the nearest integer and redefine number_of_timesteps + print(f"since number_of_timesteps/number_of_timesteps_to_analise = {number_of_timesteps/number_of_timesteps_to_analise}", + "is not an integer,\n") + new_analysing_interval = int(round(number_of_timesteps/(number_of_timesteps_to_analise-1))) + number_of_timesteps = new_analysing_interval*(number_of_timesteps_to_analise-1) + print(f"I'm resetting number_of_timesteps = {number_of_timesteps}\n") + analyse_timesteps = np.linspace(0, number_of_timesteps, number_of_timesteps_to_analise) + +Tmax = number_of_timesteps*timestep_size +time_interval = [starttime, Tmax] +print(f"The simulation interval is [{starttime}, {Tmax}]") viscosity = {# # subdom_num : viscosity @@ -116,10 +143,10 @@ L = {# lambda_param = {# # subdom_num : lambda parameter for the L-scheme - 1 : {'wetting' :100, - 'nonwetting': 100},# - 2 : {'wetting' :100, - 'nonwetting': 100} + 1 : {'wetting' :140, + 'nonwetting': 140},# + 2 : {'wetting' :140, + 'nonwetting': 140} } ## relative permeabilty functions on subdomain 1 @@ -333,7 +360,7 @@ simulation.set_parameters(output_dir = "./output/",# sources = source_expression,# initial_conditions = initial_condition,# dirichletBC_Expressions = dirichletBC,# - exact_solution_case = True,# + exact_solution = exact_solution,# write2file = write_to_file,# ) @@ -365,7 +392,7 @@ simulation.initialise() # df.File('./subdomain2_interface_marker.pvd') << simulation.subdomain[2].interface_marker # df.File('./test_subdomain1_boundary_marker.pvd') << boundary_marker1 # df.File('./test_subdomain2_boundary_marker.pvd') << boundary_marker2 -analyse_timesteps = [0, 100*timestep_size, 1, 2, 3] + simulation.run(analyse_timesteps) # simulation.LDDsolver(time = 0, debug = True, analyse_timestep = True) # df.info(parameters, True) -- GitLab