diff --git a/docs/environment.yml b/docs/environment.yml index 42892d354..d0fd19929 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -15,3 +15,4 @@ dependencies: - sphinxcontrib-bibtex - sphinx-copybutton - pillow + - sphinxcontrib-images diff --git a/docs/source/conf.py b/docs/source/conf.py index e5a285d7b..d99eba436 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -59,6 +59,7 @@ "sphinx_design", "sphinxcontrib.bibtex", "matplotlib.sphinxext.plot_directive", + "sphinxcontrib.images", ] napoleon_use_ivar = True # needed to correctly format class attributes diff --git a/docs/source/files/Mesh_1.med b/docs/source/files/Mesh_1.med new file mode 100644 index 000000000..dfab49c9c Binary files /dev/null and b/docs/source/files/Mesh_1.med differ diff --git a/docs/source/images/salome_guide_1.png b/docs/source/images/salome_guide_1.png new file mode 100644 index 000000000..4085cec99 Binary files /dev/null and b/docs/source/images/salome_guide_1.png differ diff --git a/docs/source/images/salome_guide_10.png b/docs/source/images/salome_guide_10.png new file mode 100644 index 000000000..8dcf61c19 Binary files /dev/null and b/docs/source/images/salome_guide_10.png differ diff --git a/docs/source/images/salome_guide_11.png b/docs/source/images/salome_guide_11.png new file mode 100644 index 000000000..0ec9ef87a Binary files /dev/null and b/docs/source/images/salome_guide_11.png differ diff --git a/docs/source/images/salome_guide_12.png b/docs/source/images/salome_guide_12.png new file mode 100644 index 000000000..9f45f4293 Binary files /dev/null and b/docs/source/images/salome_guide_12.png differ diff --git a/docs/source/images/salome_guide_13.png b/docs/source/images/salome_guide_13.png new file mode 100644 index 000000000..6e9372dbb Binary files /dev/null and b/docs/source/images/salome_guide_13.png differ diff --git a/docs/source/images/salome_guide_14.png b/docs/source/images/salome_guide_14.png new file mode 100644 index 000000000..478dea365 Binary files /dev/null and b/docs/source/images/salome_guide_14.png differ diff --git a/docs/source/images/salome_guide_2.png b/docs/source/images/salome_guide_2.png new file mode 100644 index 000000000..278798623 Binary files /dev/null and b/docs/source/images/salome_guide_2.png differ diff --git a/docs/source/images/salome_guide_3.png b/docs/source/images/salome_guide_3.png new file mode 100644 index 000000000..a1dfad426 Binary files /dev/null and b/docs/source/images/salome_guide_3.png differ diff --git a/docs/source/images/salome_guide_4.png b/docs/source/images/salome_guide_4.png new file mode 100644 index 000000000..13aeb52c5 Binary files /dev/null and b/docs/source/images/salome_guide_4.png differ diff --git a/docs/source/images/salome_guide_5.png b/docs/source/images/salome_guide_5.png new file mode 100644 index 000000000..43bb25303 Binary files /dev/null and b/docs/source/images/salome_guide_5.png differ diff --git a/docs/source/images/salome_guide_6.png b/docs/source/images/salome_guide_6.png new file mode 100644 index 000000000..557f6b3bd Binary files /dev/null and b/docs/source/images/salome_guide_6.png differ diff --git a/docs/source/images/salome_guide_7.png b/docs/source/images/salome_guide_7.png new file mode 100644 index 000000000..922d8bb1c Binary files /dev/null and b/docs/source/images/salome_guide_7.png differ diff --git a/docs/source/images/salome_guide_8.png b/docs/source/images/salome_guide_8.png new file mode 100644 index 000000000..8b1afffc4 Binary files /dev/null and b/docs/source/images/salome_guide_8.png differ diff --git a/docs/source/images/salome_guide_9.png b/docs/source/images/salome_guide_9.png new file mode 100644 index 000000000..26e951981 Binary files /dev/null and b/docs/source/images/salome_guide_9.png differ diff --git a/docs/source/images/salome_guide_cad_1.png b/docs/source/images/salome_guide_cad_1.png new file mode 100644 index 000000000..ec5d153ed Binary files /dev/null and b/docs/source/images/salome_guide_cad_1.png differ diff --git a/docs/source/images/salome_guide_cad_2.png b/docs/source/images/salome_guide_cad_2.png new file mode 100644 index 000000000..80bea5ad4 Binary files /dev/null and b/docs/source/images/salome_guide_cad_2.png differ diff --git a/docs/source/images/salome_guide_cad_3.png b/docs/source/images/salome_guide_cad_3.png new file mode 100644 index 000000000..70bd36533 Binary files /dev/null and b/docs/source/images/salome_guide_cad_3.png differ diff --git a/docs/source/userguide/mesh.rst b/docs/source/userguide/mesh.rst index c2b7a2a4c..3142ad0fd 100644 --- a/docs/source/userguide/mesh.rst +++ b/docs/source/userguide/mesh.rst @@ -55,6 +55,238 @@ GMSH example The DOLFINx tutorial gives an `example `_ of mesh generation with gmsh. +SALOME example +-------------- + +This is a step-by-step guide to meshing with `SALOME 9.12.0 `_. + +Building the geometry in SALOME +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Open SALOME and create a new study. +2. Activate the Geometry module + +.. thumbnail:: ../images/salome_guide_1.png + :width: 400 + :align: center + +3. Create a first square by clicking "Create rectangular face". Keep the default parameters. Click "Apply and Close" + +.. thumbnail:: ../images/salome_guide_2.png + :width: 400 + :align: center + +4. Repeat the operation to create a second square + +5. Translate the second square by clicking "Operations/Transformation/Translation" + +.. thumbnail:: ../images/salome_guide_3.png + :width: 400 + :align: center + +6. Make sure Face 2 is selected. Enter 100 for the Dx value. Click "Apply and Close" + +.. thumbnail:: ../images/salome_guide_4.png + :width: 400 + :align: center + +7. Create a compound by clicking "New Entity/Build/Compound" make sure Face_1 and Translation_1 are selected then click "Apply and Close". + +.. thumbnail:: ../images/salome_guide_5.png + :width: 400 + :align: center + +8. Create a group "New Entity/Group/Create group". In Shape Type, select the 2D surface. Name the group "left_volume". Make sure Compound_1 is selected. +Click on the left square and click "Add" (2 should appear in the white window). Click "Apply and Close". + +.. thumbnail:: ../images/salome_guide_6.png + :width: 400 + :align: center + +9. Repeat the operation to create a group "right_volume" with the right square (12 should appear in the white window). + +10. Create another group "left_boundary" but this time in Shape Type select the 1D curve. Click on the left edge of the left square and click "Add". Click "Apply and Close". + +.. thumbnail:: ../images/salome_guide_7.png + :width: 400 + :align: center + +11. Repeat the operation to create a group "right_boundary" with the right edge of the right square. Your study should look like: + +.. thumbnail:: ../images/salome_guide_8.png + :width: 400 + :align: center + +12. Click on "Mesh" to activate the mesh module. + +.. thumbnail:: ../images/salome_guide_9.png + :width: 400 + :align: center + +13. Create a mesh by clicking "Mesh/Create Mesh". + +14. Make sure Compound_1 is selected in "Geometry". Under the 2D tab, select "NETGEN 1D-2D" as algorithm. + +.. thumbnail:: ../images/salome_guide_10.png + :width: 400 + :align: center + +15. Next to "Hypothesis" click on the gear symbol. Select "NETGEN 2D Simple Parameters". Click Ok. Click "Apply and Close". + +.. thumbnail:: ../images/salome_guide_11.png + :width: 400 + :align: center + + In the Objet Browser, under Mesh_1 you should see Groups of Edges and Groups of Faces, containing left_boundary, right_boundary, left_volume and right_volume. + +16. Export the mesh to MED by right clicking on Mesh_1 in the Object Browser, then Export/MED file. Choose a location where you want to write your MED file and click Save. + +.. thumbnail:: ../images/salome_guide_12.png + :width: 400 + :align: center + +17. Convert mesh with meshio (at the time or writing we are using meshio 5.3) + +.. code-block:: bash + + python convert_mesh.py + +The script `convert_mesh.py` is: + +.. code-block:: python + + import meshio + + def convert_med_to_xdmf( + med_file, + cell_file="mesh_domains.xdmf", + facet_file="mesh_boundaries.xdmf", + cell_type="tetra", + facet_type="triangle", + ): + """Converts a MED mesh to XDMF + Args: + med_file (str): the name of the MED file + cell_file (str, optional): the name of the file containing the + volume markers. Defaults to "mesh_domains.xdmf". + facet_file (str, optional): the name of the file containing the + surface markers.. Defaults to "mesh_boundaries.xdmf". + cell_type (str, optional): The topology of the cells. Defaults to "tetra". + facet_type (str, optional): The topology of the facets. Defaults to "triangle". + Returns: + dict, dict: the correspondance dict, the cell types + """ + msh = meshio.read(med_file) + + correspondance_dict = msh.cell_tags + + cell_data_types = msh.cell_data_dict["cell_tags"].keys() + + for mesh_block in msh.cells: + if mesh_block.type == cell_type: + + meshio.write_points_cells( + cell_file, + msh.points, + [mesh_block], + cell_data={"f": [-1 * msh.cell_data_dict["cell_tags"][cell_type]]}, + ) + elif mesh_block.type == facet_type: + meshio.write_points_cells( + facet_file, + msh.points, + [mesh_block], + cell_data={"f": [-1 * msh.cell_data_dict["cell_tags"][facet_type]]}, + ) + + return correspondance_dict, cell_data_types + + + if __name__ == "__main__": + filename = "Mesh_1.med" + correspondance_dict, cell_data_types = convert_med_to_xdmf( + filename, cell_type="triangle", facet_type="line") + print(correspondance_dict) + +Running this script produces mesh_domains.xdmf, mesh_boundaries.xdmf, mesh_domains.h5, mesh_boundaries.h5 and a dictionary of correspondance between the markers and the mesh entities: + +.. code-block:: bash + + {-6: ['left_volume'], -7: ['right_volume'], -8: ['left_boundary'], -9: ['right_boundary']} + +The correspondance dictionary can be used to assign the correct markers to the mesh. +Here, the left volume is tagged with ID 6, the right boundary is tagged with ID 9. + +18. Inspect the produced XDMF files with Paraview using the XDMF3 S reader. The file mesh_domains.xdmf should look like: + +.. thumbnail:: ../images/salome_guide_13.png + :width: 400 + :align: center + + +19. Test the mesh in FESTIM by running: + +.. code-block:: python + + import festim as F + + model = F.Simulation() + + model.mesh = F.MeshFromXDMF( + volume_file="mesh_domains.xdmf", boundary_file="mesh_boundaries.xdmf" + ) + + model.materials = [F.Material(D_0=1, E_D=0, id=6), F.Material(D_0=5, E_D=0, id=7)] + + model.boundary_conditions = [ + F.DirichletBC(field="solute", value=1, surfaces=[8]), + F.DirichletBC(field="solute", value=0, surfaces=[9]), + ] + + model.T = F.Temperature(823) + + model.exports = [F.XDMFExport("solute")] + + model.settings = F.Settings( + absolute_tolerance=1e-10, + relative_tolerance=1e-10, + transient=False, + ) + + model.initialise() + model.run() + +20. The simulation should run without errors. The solute field can be visualised with Paraview. + +.. thumbnail:: ../images/salome_guide_14.png + :width: 400 + :align: center + +Meshing CAD files in SALOME +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you have a CAD model, you can export it to a mesh with SALOME. + +1. Create a new study +2. Activate the Geometry module +3. Import STEP file by clicking "File/Import/STEP" + +.. thumbnail:: ../images/salome_guide_cad_1.png + :width: 400 + :align: center + +4. By clicking "Fit to selection" you can see the imported geometry: + +.. thumbnail:: ../images/salome_guide_cad_2.png + :width: 400 + :align: center + +5. Create a partition just like in the previous example +6. Create groups of volumes and faces +7. Mesh the geometry +8. Export the mesh to MED +9. Convert the mesh to XDMF (don't forget to change the cell and facet types in the script) + ------------------ Meshes from FEniCS ------------------