How to save the results as a file which can be read by a CAD software

The following is the link of the code.

My question is how I can save the optimization results as a geometry. I hope I can open it using CAD software instead of paraview.

Thank you very much!


Taking advantage of this post, is it possible, for example, to convert a file in .xdmf format to be read by FreeCad or other CAD software? Even return to Gmsh!

I would like to be able to work on the result obtained for possible construction in a 3D printer.

thank you for your reply.


I am going to reply to your question first, as I can answer this (somewhat) directly.

I assume that you have the following problem: You have some initial geometry generated by Gmsh, read it into FEniCS, do some stuff with it (e.g. shape optimization), then you have your changed geometry, which you want to export to Gmsh again.

You can do this in fenics (not fenicsx, yet) with the help of my software cashocs.
The workflow would look somewhat like this (assuming that you have a mesh file named mesh.msh)

from fenics import *
import cashocs

# convert Gmsh to XDMF
cashocs.convert('mesh.msh', "mesh.xdmf")

# read the mesh into fenics
mesh, subdomains, boundaries, dx, ds, dS = cashocs.import_mesh('mesh.xmdf')

# do stuff

# Write out the modified mesh, "mesh.msh", "mesh_modified.msh")

The only important thing for this to work is that the number of cells, nodes, and their connectivity is not allowed to change. However, in such a case there might also be a solution - for shape optimization in cashocs, remeshing is implemented and you can use this to change the number of nodes, cells, etc. If you are interested, let me know.

You can find an extensive documentation of cashocs here

Now, regarding the original question: You can, e.g., use the approach I have described above to write out a (modified) mesh into a Gmsh format again.

If you want to use it in CAD Software, you can save the mesh / design as a .stl file in Gmsh, which will save the surface representation, which can in turn be used in most CAD Software. You might, however, have to do some pre-processing before you can really use it for your application.

Dear @

Thank you very much for your help. Well, here are some questions.
1- I do the mesh transformation from gmsh to fenics using the pattern msh to .xdmf using meshio as below:

import meshio

def create_mesh(mesh, cell_type, prune_z=False):
    cells = mesh.get_cells_type(cell_type)
    cell_data = mesh.get_cell_data("gmsh:physical", cell_type)
    out_mesh = meshio.Mesh(points=mesh.points, cells={
                           cell_type: cells}, cell_data={"name_to_read": [cell_data]})
    if prune_z:
    return out_mesh

msh ="meshtest.msh")

facet_mesh = create_mesh(msh, "triangle", prune_z=True)
meshio.write("meshtest_facet.xdmf", facet_mesh)

triangle_mesh = create_mesh(msh, "tetra", prune_z=True)
meshio.write("meshtest_mesh.xdmf", triangle_mesh)

In your program, wouldn’t that be necessary? It already does the conversion on the bass line, is that it?

# convert Gmsh to XDMF
cashocs.convert('mesh.msh', "mesh.xdmf")

2 - I work with topological optimization of several domains at the same time, so I have dx1, dx2,…,dxn. Where in gmsh I create the independent volumes and pass them to fenics in the style:

# Define 3D geometry
mesh = Mesh()
with XDMFFile("meshtest_mesh.xdmf") as infile:
mvc2 = MeshValueCollection("size_t", mesh, 2)
with XDMFFile("meshtest_facet.xdmf") as infile:, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc2)
mvc3 = MeshValueCollection("size_t", mesh, 3)
with XDMFFile("meshtest_mesh.xdmf") as infile:, "name_to_read")
cf = cpp.mesh.MeshFunctionSizet(mesh, mvc3)

dx1 = Measure("dx", domain=mesh, subdomain_data=cf, subdomain_id=100) # this number 100 is hypothetical, but equal to the one created within gmsh
dx2 = Measure("dx", domain=mesh, subdomain_data=cf, subdomain_id=200)
dx3 = Measure("dx", domain=mesh, subdomain_data=cf, subdomain_id=300)

Would this conversion or consideration be possible in your program?

I imagine that some change would be made in the line below:

# read the mesh into fenics
mesh, subdomains, boundaries, dx, ds, dS = cashocs.import_mesh('mesh.xdmf')

3 - Would it be possible for me to just install cashocs and just perform the transformation according to the .xdmf file generation pattern:

#ParaView Results:
    file_results = XDMFFile(MPI.comm_world, "solution.xdmf")
    file_results.parameters["flush_output"] = True
    file_results.parameters["functions_share_mesh"] = True
    file_results.write(rho_opt, 0.)
    file_results.write(ud, 0.)

In short, I can take, for example, the result of the code from the first post above (dolfin-adjoint/pyadjoint/blob/master/examples/stokes-topology/ 1) and transform the .xdmf
to .msh using cashocs?

Hi @Rafael_Ferro,

you’re welcome. Here are my answers

  1. Yes, cashocs does that conversion with the cashocs.convert command (can also be invoked from the command line as cashocs-convert)

  2. No, you don’t have to change anything. cashocs already takes care of this - you do not have to do anything yourself. If you have a Gmsh mesh file, where you have defined “physical groups” yourself (e.g. Physical Curves, Physical Surfaces, Physical Volumes), you can take that mesh file, put it into cashocs.convert, and load the converted one with cashocs.import_mesh. Then, you are able to call dx(i) to access the volume / surface (in 3D / 2D) measure corresponding to the Physical Volume / Physical Surface, same goes for the ds and dS measures. Take a look at the first demo for shape optimization and its documentation. There, you can find the mesh files in the /mesh folder. For a slightly more complicated problem, take a look at this demo, where the physical tags are used.
    Moreover, you can even name the surfaces and use the named measures in a mesh imported with cashocs. Consider the case that you have a 2D mesh and define the following surface in your Gmsh .geo file
    Physical Surface("region", 42) = {11}
    where the indices 42 and 11 are arbitrary. If you convert and import the mesh file with cashocs, you can then access the surface measure of this surface by either using dx(42) or by using its name dx("region"). Just try it out and have fun :wink:

  3. I am not sure what you are trying to do / achieve with this. In the mentioned demo, topology optimization is performed on a fixed mesh via a density approach. This means, if you write out the mesh, you will have the same one as before. Your solution is a density function \rho which can be interpreted as the indicator function for a domain. So what do you want to achieve?

Dear @plugged,

Thanks for the answers, I’ll try to use your program here and then I’ll get back to you.

About your last comment, some CAD/CAE programs, at the end of the optimization, you can export this solution as a fixed mesh of the solution contour, and over this mesh, you create a new mesh, “manually” making the internal contours and smoothing all geometry using the fixed mesh as a reference. See this video (Topology Optimization in Autodesk Fusion 360 - YouTube), from minute 4.36 that mentions what I said above. This one uses Fusion 360, but ansys and others also have something similar.

So that would be the question, how to manage to export the final result of fenics in .xdmf, even if in a fixed mesh, to be able to remodel the mesh in another software.

Paraview has a “Treshold” filter, if anyone knows how to export this filtered mesh it would also be a great help. I still haven’t found how to export the results in mesh or CAD file from Paraview.

Well, just to update, I just found out how to export from paraview. First you make the treshold filter, then selecting this filtered model, make a new filter “Extract Surface” in ascii and then you can export in File - Save Data - Files of type: .stl

And so, it is possible to open in any CAD software.

1 Like