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