@@ -156,83 +156,147 @@ def create_mesh(
156156 manifold_surface = manifold_surface ,
157157 correct_surface_orientation = True ,
158158 )
159- coords , connections = tetra .get_tracked_surfaces ()
160159
161160 tetra_mesh = meshio .Mesh (
162161 point_array , [("tetra" , cell_array )], cell_data = {"cell_tags" : [marker .ravel ()]}
163162 )
164- tetra_mesh_pv = pv .from_meshio (tetra_mesh ).clean ()
163+
164+ tetra_mesh_pv = pv .from_meshio (tetra_mesh )
165165 pv .save_meshio (outdir / "tetra_mesh.xdmf" , tetra_mesh_pv )
166166
167- for i , coord in enumerate (coords ):
168- np .save (outdir / f"coords_{ i } .npy" , coord )
167+ np .save (outdir / "point_array.npy" , point_array )
168+ np .save (outdir / "cell_array.npy" , cell_array )
169+ np .save (outdir / "marker.npy" , marker )
170+
171+ # coords, connections = tetra.get_tracked_surfaces()
172+ # for i, coord in enumerate(coords):
173+ # np.save(outdir / f"coords_{i}.npy", coord)
174+
175+ # for i, conn in enumerate(connections):
176+ # np.save(outdir / f"connections_{i}.npy", conn)
169177
170- for i , conn in enumerate (connections ):
171- np .save (outdir / f"connections_{ i } .npy" , conn )
178+ # cell_tags.find
179+ # Compute incident with facets
180+ # Intersection exterior facets
172181
173182
174- def convert_mesh_dolfinx (mesh_dir : Path ):
183+ def convert_mesh_dolfinx (
184+ mesh_dir : Path , extract_facet_tags : bool = False , extract_submesh : bool = False
185+ ):
175186 logger .info ("Converting mesh to dolfinx in %s" , mesh_dir )
176187 from mpi4py import MPI
177- from scipy .spatial .distance import cdist
178188 import dolfinx
189+ import basix
190+ import ufl
179191
180- threshold = 1.0
181- fdim = 2
182-
183- coords = []
184- for path in sorted (mesh_dir .glob ("coords_*.npy" ), key = lambda x : int (x .stem .split ("_" )[- 1 ])):
185- coords .append (np .load (path ))
186- logger .debug (f"Found { len (coords )} coordinates" )
192+ point_array = np .load (mesh_dir / "point_array.npy" )
193+ cell_array = np .load (mesh_dir / "cell_array.npy" )
194+ marker = np .load (mesh_dir / "marker.npy" )
187195
188- connections = []
189- for path in sorted (
190- mesh_dir .glob ("connections_*.npy" ), key = lambda x : int (x .stem .split ("_" )[- 1 ])
191- ):
192- connections .append (np .load (path ))
193- logger .debug (f"Found { len (connections )} connections" )
196+ comm = MPI .COMM_WORLD
197+ mesh = dolfinx .mesh .create_mesh (
198+ comm ,
199+ cell_array .astype (np .int64 ),
200+ point_array ,
201+ ufl .Mesh (basix .ufl .element ("Lagrange" , "tetrahedron" , 1 , shape = (3 ,))),
202+ )
203+ tdim = mesh .topology .dim
204+ fdim = tdim - 1
205+ local_entities , local_values = dolfinx .io .gmshio .distribute_entity_data (
206+ mesh ,
207+ tdim ,
208+ cell_array .astype (np .int64 ),
209+ marker .flatten ().astype (np .int32 ),
210+ )
211+ adj = dolfinx .graph .adjacencylist (local_entities )
212+ cell_tags = dolfinx .mesh .meshtags_from_entities (
213+ mesh ,
214+ tdim ,
215+ adj ,
216+ local_values .astype (np .int32 , copy = False ),
217+ )
218+ if not extract_facet_tags :
219+ logger .debug ("Save files" )
220+ with dolfinx .io .XDMFFile (comm , mesh_dir / "mesh_full.xdmf" , "w" ) as xdmf :
221+ xdmf .write_mesh (mesh )
222+ xdmf .write_meshtags (cell_tags , mesh .geometry )
194223
195- assert len ( connections ) == len ( coords )
224+ return
196225
197- logger .debug ("Loading mesh" )
198- comm = MPI .COMM_WORLD
199- with dolfinx .io .XDMFFile (comm , mesh_dir / "tetra_mesh.xdmf" , "r" ) as xdmf :
200- mesh = xdmf .read_mesh (name = "Grid" )
201- cell_tags = xdmf .read_meshtags (mesh , name = "Grid" )
226+ mesh .topology .create_connectivity (tdim - 1 , tdim )
202227
203- logger . debug ( "Mesh loaded" )
228+ # FIXME: Here we just add hard coded values for now. This should be fixed in the future
204229
205- facets = []
230+ entities = []
206231 values = []
207- for i , coord in enumerate ( coords , start = 1 ):
208- logger . debug ( f"Processing coord { i } " )
232+ # 1 = Parenchyma
233+ PARENCHYMA = 1
209234
210- def locator (x ):
211- # Find the distance to all coordinates
212- distances = cdist (x .T , coord )
213- # And return True is they are close
214- return np .any (distances < threshold , axis = 1 )
235+ cells = cell_tags .find (PARENCHYMA )
236+ exterior_facets = dolfinx .mesh .exterior_facet_indices (mesh .topology )
237+ incident_facets = dolfinx .mesh .compute_incident_entities (mesh .topology , cells , tdim , tdim - 1 )
238+ exterior_facets_marker = np .intersect1d (incident_facets , exterior_facets )
239+ values .append (np .full (exterior_facets_marker .shape [0 ], PARENCHYMA , dtype = np .int32 ))
240+ entities .append (exterior_facets_marker )
215241
216- f = dolfinx .mesh .locate_entities_boundary (mesh , dim = fdim , marker = locator )
217- v = np .full (f .shape [0 ], i , dtype = np .int32 )
218- facets .append (f )
219- values .append (v )
242+ VENTRICLES = 3
243+ all_cell_tags = np .unique (cell_tags .values )
244+ cell_not_ventricles = np .setdiff1d (all_cell_tags , [VENTRICLES ])
245+ import scifem
246+
247+ interface_entities = scifem .mesh .find_interface (cell_tags , [VENTRICLES ], cell_not_ventricles )
248+ entities .append (interface_entities )
249+ values .append (np .full (interface_entities .shape [0 ], VENTRICLES , dtype = np .int32 ))
220250
221- logger .debug ("Create meshtags" )
222251 facet_tags = dolfinx .mesh .meshtags (
223252 mesh ,
224253 fdim ,
225- np .hstack (facets ),
254+ np .hstack (entities ),
226255 np .hstack (values ),
227256 )
228257 facet_tags .name = "facet_tags"
229258 cell_tags .name = "cell_tags"
230259 mesh .name = "mesh"
231260
232261 logger .debug ("Save files" )
233- with dolfinx .io .XDMFFile (comm , mesh_dir / "mesh .xdmf" , "w" ) as xdmf :
262+ with dolfinx .io .XDMFFile (comm , mesh_dir / "mesh_full .xdmf" , "w" ) as xdmf :
234263 xdmf .write_mesh (mesh )
235264 xdmf .write_meshtags (facet_tags , mesh .geometry )
236265 xdmf .write_meshtags (cell_tags , mesh .geometry )
237266
238267 logger .info ("Mesh saved to %s" , mesh_dir / "mesh.xdmf" )
268+
269+ if not extract_submesh :
270+ return
271+ submesh_data = scifem .mesh .extract_submesh (mesh , cell_tags , cell_not_ventricles )
272+
273+ # Transfer the facet tags to the submesh
274+ submesh_data .domain .topology .create_connectivity (2 , 3 )
275+ facet_tags_submesh , sub_to_parent_entity_map = scifem .mesh .transfer_meshtags_to_submesh (
276+ facet_tags ,
277+ # geo.facet_tags, # If available
278+ submesh_data .domain ,
279+ vertex_to_parent = submesh_data .vertex_map ,
280+ cell_to_parent = submesh_data .cell_map ,
281+ )
282+
283+ np .save (mesh_dir / "sub_to_parent_entity_map.npy" , sub_to_parent_entity_map )
284+ np .save (mesh_dir / "vertex_map.npy" , submesh_data .vertex_map )
285+ np .save (mesh_dir / "cell_map.npy" , submesh_data .cell_map )
286+
287+ # Remove overflow values
288+ keep_indices = facet_tags_submesh .values > 0
289+ facet_tags_new = dolfinx .mesh .meshtags (
290+ submesh_data .domain ,
291+ fdim ,
292+ facet_tags_submesh .indices [keep_indices ],
293+ facet_tags_submesh .values [keep_indices ],
294+ )
295+
296+ facet_tags_new .name = "facet_tags"
297+ submesh_data .cell_tag .name = "cell_tags"
298+
299+ with dolfinx .io .XDMFFile (comm , mesh_dir / "mesh.xdmf" , "w" ) as xdmf :
300+ xdmf .write_mesh (submesh_data .domain )
301+ xdmf .write_meshtags (submesh_data .cell_tag , submesh_data .domain .geometry )
302+ xdmf .write_meshtags (facet_tags_new , submesh_data .domain .geometry )
0 commit comments