From d5a10957a6746cc786d963d7815f7dca74e79e86 Mon Sep 17 00:00:00 2001 From: Julian Heinze <julian.heinze@ufz.de> Date: Tue, 21 Jan 2025 14:28:29 +0100 Subject: [PATCH 1/4] introduce subdomain --- ogstools/feflowlib/feflow_model.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/ogstools/feflowlib/feflow_model.py b/ogstools/feflowlib/feflow_model.py index 68a450efb..8ea57b284 100644 --- a/ogstools/feflowlib/feflow_model.py +++ b/ogstools/feflowlib/feflow_model.py @@ -56,7 +56,7 @@ class FeflowModel: self.mesh = convert_properties_mesh(self._doc) self.dimension = self._doc.getNumberOfDimensions() self.setup_prj() # _project object with default values is initialized here - self._init_boundary_conditions() + self._init_subdomains() self._mesh_saving_needed = True @property @@ -72,7 +72,7 @@ class FeflowModel: bulk_mesh["MaterialIDs"] = self.mesh["MaterialIDs"] return bulk_mesh - def _init_boundary_conditions(self) -> None: + def _init_subdomains(self) -> None: """ The boundary meshes for a ogs model. @@ -80,9 +80,7 @@ class FeflowModel: """ # ToDo: Introduce this behaviour to feflowlib.tools with a type. # And return type of name for cell and pt BC should be the same not possix Path... - _boundary_conditions = _tools.extract_point_boundary_conditions( - self.mesh - ) + _subdomains = _tools.extract_point_boundary_conditions(self.mesh) if self.dimension == 3 and ( ( @@ -98,11 +96,9 @@ class FeflowModel: cell_bc_path, cell_bc_mesh, ) = _tools.extract_cell_boundary_conditions(self.mesh) - _boundary_conditions[cell_bc_path] = cell_bc_mesh + _subdomains[cell_bc_path] = cell_bc_mesh - self.boundary_conditions: dict[ - str, pv.UnstructuredGrid - ] = _boundary_conditions + self.subdomains: dict[str, pv.UnstructuredGrid] = _subdomains @property def process(self) -> str: @@ -250,19 +246,19 @@ class FeflowModel: Save the converted FEFLOW model. Saves the meshes only if they have not been saved previously. or 'force_saving' is true. - :param output_path: The path where the mesh, boundary meshes and project file will be written. + :param output_path: The path where the mesh, subdomains and project file will be written. """ if output_path is None: output_path = self.mesh_path self.project.write_input(prjfile_path=output_path.with_suffix(".prj")) if self._mesh_saving_needed or force_saving: self.mesh.save(output_path.with_suffix(".vtu")) - for name, boundary_mesh in self.boundary_conditions.items(): - boundary_mesh.save(output_path.parent / (name + ".vtu")) + for name, subdomain in self.subdomains.items(): + subdomain.save(output_path.parent / (name + ".vtu")) self._mesh_saving_needed = False else: logger.info( - "The mesh and boundary meshes have already been saved. As no changes have been detected, saving of the mesh is skipped. The project file is saved (again)." + "The mesh and subdomains have already been saved. As no changes have been detected, saving of the mesh is skipped. The project file is saved (again)." ) def run( @@ -271,7 +267,7 @@ class FeflowModel: """ Run the converted FEFLOW model. - :param output_path: The path where the mesh, boundary meshes and project file will be written. + :param output_path: The path where the mesh, subdomains and project file will be written. """ self.save(output_path, overwrite) self.project.run_model() -- GitLab From 47f3c289931e5bbd6cadfebd30dbf472808902dc Mon Sep 17 00:00:00 2001 From: Julian Heinze <julian.heinze@ufz.de> Date: Tue, 21 Jan 2025 15:02:06 +0100 Subject: [PATCH 2/4] update cli, examples, tests --- .../howto_conversions/plot_B_feflowlib_BC_mesh.py | 14 +++++++------- .../howto_conversions/plot_C_feflowlib_prj.py | 10 +++++----- .../plot_D_feflowlib_CT_simulation.py | 2 +- .../plot_E_feflowlib_H_simulation.py | 12 ++++++------ .../plot_F_feflowlib_HT_simulation.py | 10 +++++----- ogstools/feflowlib/_cli.py | 2 +- tests/test_feflowlib.py | 6 +++--- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py b/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py index f4c209799..3f7395f94 100644 --- a/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py +++ b/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py @@ -48,12 +48,12 @@ ogs_sim_res = ms.mesh(ms.timesteps[-1]) ot.plot.contourf(ogs_sim_res, ot.variables.temperature) # %% # 6. The boundary meshes are manipulated to alter the model. -# 6.1 The Dirichlet boundary conditions for the hydraulic head are set to 0. -bc_flow = feflow_model.boundary_conditions["P_BC_FLOW"]["P_BC_FLOW"] -feflow_model.boundary_conditions["P_BC_FLOW"]["P_BC_FLOW"][bc_flow == 10] = 0 +# The original boundary conditions are shown in this example: :ref:`sphx_glr_auto_examples_howto_conversions_plot_F_HT_simulation.py` +# 6.1 The Dirichlet boundary conditions for the hydraulic head are set to 0. Therefore, no water flows from the left to the right edge. +bc_flow = feflow_model.subdomains["P_BC_FLOW"]["P_BC_FLOW"] +feflow_model.subdomains["P_BC_FLOW"]["P_BC_FLOW"][bc_flow == 10] = 0 # %% -# 6.2 Save the new boundary conditions and run the model. -# Overwrite is needed to save the changed boundary meshes. +# 6.2 Overwrite the new boundary conditions and run the model. feflow_model.run(overwrite=True) # %% # 6.3 The corresponding simulation results look like. @@ -62,7 +62,7 @@ ms = ot.MeshSeries(temp_dir / "HT_model.pvd") ogs_sim_res = ms.mesh(ms.timesteps[-1]) ot.plot.contourf(ogs_sim_res, ot.variables.temperature) # %% -# 6.3 Create new boundary mesh. +# 6.4 Create a new boundary mesh and overwrite the existing subdomains with this boundary mesh. assign_bulk_ids(mesh) # Get the points of the bulk mesh to build a new boundary mesh. wanted_pts = [1492, 1482, 1481, 1491, 1479, 1480, 1839, 1840] @@ -74,7 +74,7 @@ new_bc = mesh.extract_points( new_bc["bulk_node_ids"] = np.array(wanted_pts, dtype=np.uint64) # Define the temperature values of these points. new_bc["P_BC_HEAT"] = np.array([300] * len(wanted_pts), dtype=np.float64) -feflow_model.boundary_conditions["P_BC_HEAT"] = new_bc +feflow_model.subdomains["P_BC_HEAT"] = new_bc # %% # 7. Run the new model and plot the simulation results. feflow_model.run(overwrite=True) diff --git a/docs/examples/howto_conversions/plot_C_feflowlib_prj.py b/docs/examples/howto_conversions/plot_C_feflowlib_prj.py index c881768a1..c11af8ec2 100644 --- a/docs/examples/howto_conversions/plot_C_feflowlib_prj.py +++ b/docs/examples/howto_conversions/plot_C_feflowlib_prj.py @@ -46,12 +46,12 @@ feflow_model.save() model_prjfile = ET.parse(temp_dir / "CT_model.prj") ET.dump(model_prjfile) # %% -# 5. Remove some points of the boundary mesh. +# 5. Remove some points of the boundary mesh, which is part of the subdomains. bounds = [0.037, 0.039, 0.003, 0.006, 0, 0] -new_bc_mesh = feflow_model.boundary_conditions[ - "single_species_P_BC_MASS" -].clip_box(bounds, invert=False) -feflow_model.boundary_conditions["single_species_P_BC_MASS"] = new_bc_mesh +new_bc_mesh = feflow_model.subdomains["single_species_P_BC_MASS"].clip_box( + bounds, invert=False +) +feflow_model.subdomains["single_species_P_BC_MASS"] = new_bc_mesh # %% # 6. Run the model. feflow_model.run(overwrite=True) diff --git a/docs/examples/howto_conversions/plot_D_feflowlib_CT_simulation.py b/docs/examples/howto_conversions/plot_D_feflowlib_CT_simulation.py index 99fa60fd0..230bc129e 100644 --- a/docs/examples/howto_conversions/plot_D_feflowlib_CT_simulation.py +++ b/docs/examples/howto_conversions/plot_D_feflowlib_CT_simulation.py @@ -47,7 +47,7 @@ time_steps = list( zip([10] * 8, [8.64 * 10**i for i in range(8)], strict=False) ) feflow_model.setup_prj(end_time=int(4.8384e07), time_stepping=time_steps) -# Save the model (mesh, boundary meshes and project file). +# Save the model (mesh, subdomains and project file). feflow_model.save() # Print the prj-file as an example. ET.dump(ET.parse(feflow_model.mesh_path.with_suffix(".prj"))) diff --git a/docs/examples/howto_conversions/plot_E_feflowlib_H_simulation.py b/docs/examples/howto_conversions/plot_E_feflowlib_H_simulation.py index f7cbace22..e0ea59446 100644 --- a/docs/examples/howto_conversions/plot_E_feflowlib_H_simulation.py +++ b/docs/examples/howto_conversions/plot_E_feflowlib_H_simulation.py @@ -37,12 +37,12 @@ feflow_model.mesh.plot( ) print(feflow_model.mesh) # %% -# 2. Extract the boundary conditions. -BC_dict = feflow_model.boundary_conditions -# Since there can be multiple point based boundary conditions on the bulk mesh, -# they are saved and plotted iteratively. -plotter = pv.Plotter(shape=(len(BC_dict), 1)) -for i, (name, boundary_condition) in enumerate(BC_dict.items()): +# 2. Extract the subdomains conditions. +subdomains = feflow_model.subdomains +# Since there can be multiple boundary conditions in the subdomains, +# they are plotted iteratively. +plotter = pv.Plotter(shape=(len(subdomains), 1)) +for i, (name, boundary_condition) in enumerate(subdomains.items()): # topsurface refers to a cell based boundary condition. if name != "topsurface": plotter.subplot(i, 0) diff --git a/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py b/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py index 222470823..7928cf0eb 100644 --- a/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py +++ b/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py @@ -28,11 +28,11 @@ feflow_temperature = ot.variables.temperature.replace(data_name="P_TEMP") ot.plot.contourf(feflow_model.mesh, feflow_temperature) print(feflow_model.mesh) # %% -# 3. Extract the boundary conditions. -BC_dict = feflow_model.boundary_conditions -# Since there can be multiple point based boundary conditions on the bulk mesh, they are plotted iteratively. -plotter = pv.Plotter(shape=(len(BC_dict), 1)) -for i, (name, boundary_condition) in enumerate(BC_dict.items()): +# 3. Extract the subdomains. +subdomains = feflow_model.subdomains +# Since there can be multiple boundary conditions in the subdomains, they are plotted iteratively. +plotter = pv.Plotter(shape=(len(subdomains), 1)) +for i, (name, boundary_condition) in enumerate(subdomains.items()): # topsurface refers to a cell based boundary condition. if name != "topsurface": plotter.subplot(i, 0) diff --git a/ogstools/feflowlib/_cli.py b/ogstools/feflowlib/_cli.py index 0de9271e7..9b2dbf629 100644 --- a/ogstools/feflowlib/_cli.py +++ b/ogstools/feflowlib/_cli.py @@ -96,7 +96,7 @@ def feflow_converter(input: str, output: str, case: str, BC: str) -> int: "The conversion of the bulk mesh was successful.", ) return 0 - for path, boundary_mesh in feflow_model.boundary_conditions.items(): + for path, boundary_mesh in feflow_model.subdomains.items(): boundary_mesh.save(path) logger.info( diff --git a/tests/test_feflowlib.py b/tests/test_feflowlib.py index 65dd68e59..81af0ed12 100644 --- a/tests/test_feflowlib.py +++ b/tests/test_feflowlib.py @@ -729,15 +729,15 @@ class TestFeflowModel: def test_boundary_conditions(self): "Test for one model (HT) if boundary condition are returned correctly from FeflowModel." - boundary_conditions = self.feflow_model_HT.boundary_conditions + boundary_conditions = self.feflow_model_HT.subdomains first_bc = boundary_conditions[next(iter(boundary_conditions))] assert first_bc.n_cells == 44 assert first_bc.n_points == 44 assert first_bc.n_arrays == 2 - boundary_conditions = self.feflow_model_HT_hetero.boundary_conditions + boundary_conditions = self.feflow_model_HT_hetero.subdomains neumann_BC = boundary_conditions["P_BCFLOW_2ND"] assert neumann_BC.celltypes[0] == 3 # 3 is a Line element - assert "topsurface" in self.feflow_H_box_IOFLOW.boundary_conditions + assert "topsurface" in self.feflow_H_box_IOFLOW.subdomains def test_processes(self): "Test if processes are detected correctly." -- GitLab From 5348fd9cc9146d16f1611fb61f85efa3659f9ae9 Mon Sep 17 00:00:00 2001 From: Julian Heinze <julian.heinze@ufz.de> Date: Tue, 21 Jan 2025 15:28:16 +0100 Subject: [PATCH 3/4] remove unnecessary comments --- ogstools/feflowlib/feflow_model.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ogstools/feflowlib/feflow_model.py b/ogstools/feflowlib/feflow_model.py index 8ea57b284..7f0a8a397 100644 --- a/ogstools/feflowlib/feflow_model.py +++ b/ogstools/feflowlib/feflow_model.py @@ -78,8 +78,6 @@ class FeflowModel: :return: Dictionary (dict) of boundary meshes, with name as key and mesh as value. """ - # ToDo: Introduce this behaviour to feflowlib.tools with a type. - # And return type of name for cell and pt BC should be the same not possix Path... _subdomains = _tools.extract_point_boundary_conditions(self.mesh) if self.dimension == 3 and ( @@ -148,7 +146,7 @@ class FeflowModel: # For later functions of the converter, material properties are needed. # For this reason, a defaultdict is returned with no material properties in # this case. - # ToDo: return a dict of all properties with a warning! + # ToDo: return a dict of all possible material properties with a warning! material_properties = defaultdict(str) material_properties["undefined"] = ( f"Material properties are only saved on the mesh for this process: '{process}'", -- GitLab From 33f74ea0b0675dbdcc1a87bf3c16c381cf565099 Mon Sep 17 00:00:00 2001 From: Julian Heinze <julian.heinze@ufz.de> Date: Tue, 21 Jan 2025 15:47:01 +0100 Subject: [PATCH 4/4] tiny fixes --- docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py | 2 +- .../howto_conversions/plot_F_feflowlib_HT_simulation.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py b/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py index 3f7395f94..37178fc06 100644 --- a/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py +++ b/docs/examples/howto_conversions/plot_B_feflowlib_BC_mesh.py @@ -48,7 +48,7 @@ ogs_sim_res = ms.mesh(ms.timesteps[-1]) ot.plot.contourf(ogs_sim_res, ot.variables.temperature) # %% # 6. The boundary meshes are manipulated to alter the model. -# The original boundary conditions are shown in this example: :ref:`sphx_glr_auto_examples_howto_conversions_plot_F_HT_simulation.py` +# The original boundary conditions are shown in this example: :ref:`sphx_glr_auto_examples_howto_conversions_plot_F_feflowlib_HT_simulation.py` # 6.1 The Dirichlet boundary conditions for the hydraulic head are set to 0. Therefore, no water flows from the left to the right edge. bc_flow = feflow_model.subdomains["P_BC_FLOW"]["P_BC_FLOW"] feflow_model.subdomains["P_BC_FLOW"]["P_BC_FLOW"][bc_flow == 10] = 0 diff --git a/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py b/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py index 7928cf0eb..836fb8ef5 100644 --- a/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py +++ b/docs/examples/howto_conversions/plot_F_feflowlib_HT_simulation.py @@ -75,6 +75,7 @@ hydraulic_head_diff = ot.variables.Scalar( data_name="HEAD_difference", data_unit="m", output_unit="m" ) ot.plot.contourf(diff_mesh, hydraulic_head_diff, vmin=-1.5e-9, vmax=1.5e-9) +# %% # Plot differences in temperature. feflow_model.mesh["temperature"] = feflow_model.mesh["P_TEMP"] # Plot differences in temperature. -- GitLab