phiFEM 0.7.0.dev1__py3-none-any.whl → 0.7.1.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
phifem/mesh_scripts.py CHANGED
@@ -118,35 +118,31 @@ def _compute_detection_vector(
118
118
  detection_denom_form = dfx.fem.form(detection_denom)
119
119
  detection_denom_vec = assemble_vector(detection_denom_form)
120
120
 
121
- imap = dg_0_space.dofmap.index_map
122
- detection_vector = dfx.la.vector(imap)
123
121
  # detection_denom_vec is not supposed to be zero, this would mean that the levelset is zero at all dofs in a cell.
124
122
  # However, in practice it can happen that for a very small cut triangle, detection_denom_vec is of the order of the machine precision.
125
123
  # In this case, we set the value of detection_vector to 0.5, meaning we consider the cell as cut.
124
+ mask = np.where(detection_denom_vec.array > 0.0)
125
+ detection_vector = np.full_like(detection_num_vec.array, 0.5)
126
+ detection_vector[mask] = (
127
+ detection_num_vec.array[mask] / detection_denom_vec.array[mask]
128
+ )
126
129
  if np.any(np.isclose(detection_denom_vec.array, 0.0)):
127
130
  warnings.warn(
128
- "The levelset function is zero everywhere on a cell. We mark it as 'cut' but this can be incorrect and should be carefully checked.",
131
+ "The detection function is zero everywhere on a cell. We mark it as 'cut' but this can be incorrect and should be carefully checked.",
129
132
  RuntimeWarning,
130
133
  )
131
- mask = np.where(detection_denom_vec.array > 0.0)
132
- detection_vector.array[:] = 0.5
133
- detection_vector.array[mask] = (
134
- detection_num_vec.array[mask] / detection_denom_vec.array[mask]
135
- )
136
- detection_vector.scatter_forward()
137
134
  return detection_vector
138
135
 
139
136
 
140
137
  def _compute_integration_entities(
141
- mesh: Mesh, integration_cells: list[int], integration_facets: list[int], ind: int
142
- ) -> ufl.Measure:
138
+ mesh: Mesh, integration_cells: list[int], integration_facets: list[int]
139
+ ) -> list[int]:
143
140
  """Compute the integration entities in order to build a one-sided integral over a set of given edges. This script is inspired from https://github.com/jorgensd/dolfinx-tutorial/issues/158.
144
141
 
145
142
  Args:
146
143
  mesh: the mesh on which we compute the measure.
147
144
  integration_cells: list of cells indices from which the integral is computed.
148
145
  integration_facets: list of facets indices on which the integral is computed.
149
- ind: index used in the measure.
150
146
  Returns: the integration entities.
151
147
  """
152
148
  cdim = mesh.topology.dim
@@ -192,7 +188,7 @@ def _compute_integration_entities(
192
188
  np.column_stack((right_side_cells_rep, local_indices))
193
189
  ).astype(np.int32)
194
190
 
195
- return [(ind, integration_entities)]
191
+ return integration_entities
196
192
 
197
193
 
198
194
  def _reshape_map(connect: AdjacencyList_int32) -> npt.NDArray[np.int32]:
@@ -217,31 +213,71 @@ def _reshape_map(connect: AdjacencyList_int32) -> npt.NDArray[np.int32]:
217
213
  return emap, max_offset
218
214
 
219
215
 
220
- def _transfer_markers(
221
- source_markers: dfx.la.Vector,
216
+ def _transfer_tags(
217
+ source_mesh_tags: MeshTags,
218
+ dest_mesh: Mesh,
222
219
  cmap: npt.NDArray[Any],
223
- edim: int,
224
- ) -> dfx.la.Vector:
220
+ source_mesh: Mesh = None,
221
+ ) -> MeshTags:
225
222
  """Given entities tags (cells or facets) from a source mesh, a destination mesh and the source mesh-destination mesh cells mapping, transfers the entities tags to the destination mesh.
226
223
 
227
224
  Args:
228
- source_markers: the markers on the source mesh.
225
+ source_mesh_tags: the tags on the source mesh.
229
226
  dest_mesh: the destination mesh.
230
227
  cmap: the source mesh-destination mesh cells mapping.
228
+ source_mesh: the source mesh mandatory to transfer facets tags.
231
229
 
232
230
  Returns:
233
231
  Cells tags on the destination mesh.
234
232
  """
235
- sub_index_map = cmap.sub_topology.index_map(edim)
236
- local_entities = np.arange(sub_index_map.size_local + sub_index_map.num_ghosts)
237
- emap = cmap.sub_topology_to_topology(
238
- local_entities,
239
- False,
233
+ cdim = dest_mesh.topology.dim
234
+ fdim = cdim - 1
235
+ edim = source_mesh_tags.dim
236
+
237
+ if edim == cdim:
238
+ emap = cmap
239
+ elif edim == fdim:
240
+ if source_mesh is None:
241
+ raise ValueError("You must pass a source_mesh to transfer facets tags.")
242
+
243
+ source_mesh.topology.create_connectivity(cdim, fdim)
244
+ c2f_connect = source_mesh.topology.connectivity(cdim, fdim)
245
+ num_facets_per_cell = len(c2f_connect.links(0))
246
+ source_c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
247
+ dest_mesh.topology.create_connectivity(cdim, fdim)
248
+ c2f_connect = dest_mesh.topology.connectivity(cdim, fdim)
249
+ num_facets_per_cell = len(c2f_connect.links(0))
250
+ dest_c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
251
+ source_c2f_dest_map = source_c2f_map[cmap]
252
+ source_c2f_dest_map = source_c2f_dest_map.reshape(
253
+ -1,
254
+ )
255
+ dest_c2f_map = dest_c2f_map.reshape(
256
+ -1,
257
+ )
258
+ unique_indices, sorted_indices = np.unique(dest_c2f_map, return_index=True)
259
+ emap = source_c2f_dest_map[sorted_indices]
260
+ else:
261
+ raise ValueError("The source_mesh_tags can only be cells tags or facets tags.")
262
+
263
+ # TODO: change this line to allow parallel computing
264
+ source_tags = source_mesh_tags.values
265
+
266
+ dest_entities = np.arange(len(emap))
267
+ dest_tags = source_tags[emap]
268
+
269
+ dest_entities_indices = np.hstack(dest_entities).astype(np.int32)
270
+ dest_entities_markers = np.hstack(dest_tags).astype(np.int32)
271
+ sorted_indices = np.argsort(dest_entities_indices)
272
+
273
+ dest_entities_tags = dfx.mesh.meshtags(
274
+ dest_mesh,
275
+ edim,
276
+ dest_entities_indices[sorted_indices],
277
+ dest_entities_markers[sorted_indices],
240
278
  )
241
- dest_markers = dfx.la.vector(sub_index_map)
242
- dest_markers.array[:] = source_markers.array[emap]
243
279
 
244
- return dest_markers
280
+ return dest_entities_tags
245
281
 
246
282
 
247
283
  def _tag_cells(
@@ -249,7 +285,7 @@ def _tag_cells(
249
285
  discrete_levelset: Function,
250
286
  detection_degree: int,
251
287
  single_layer_cut: bool = False,
252
- ) -> dfx.la.Vector:
288
+ ) -> MeshTags:
253
289
  """Tag the mesh cells by computing detection = Σ f(dof)/Σ|f(dof)| where 'dof' are coming from a custom quadrature rule with points on the boundary of the cell only.
254
290
  Strictly inside cell => tag 1
255
291
  Cut cell => tag 2
@@ -262,7 +298,7 @@ def _tag_cells(
262
298
  single_layer_cut: boolean, if True force a single layer of cut cells.
263
299
 
264
300
  Returns:
265
- The cells markers as a dfx.la.Vector object.
301
+ The cells tags as a MeshTags object.
266
302
  """
267
303
  if single_layer_cut:
268
304
  cdim = mesh.topology.dim
@@ -304,12 +340,10 @@ def _tag_cells(
304
340
  mesh, discrete_levelset, detection_measure
305
341
  )
306
342
  cut_indices = np.where(
307
- np.logical_and(
308
- detection_vector.array[:] > -1.0, detection_vector.array[:] < 1.0
309
- )
343
+ np.logical_and(detection_vector > -1.0, detection_vector < 1.0)
310
344
  )[0]
311
- exterior_indices = np.where(np.isclose(detection_vector.array[:], 1.0))[0]
312
- interior_indices = np.where(np.isclose(detection_vector.array[:], -1.0))[0]
345
+ exterior_indices = np.where(detection_vector == 1.0)[0]
346
+ interior_indices = np.where(detection_vector == -1.0)[0]
313
347
 
314
348
  if single_layer_cut:
315
349
  neighbor_cells = np.reshape(
@@ -337,21 +371,30 @@ def _tag_cells(
337
371
  assert np.logical_not(np.isin(exterior_indices, interior_indices).any()), (
338
372
  "The sets of outside cells and inside cells have a non-empty intersection"
339
373
  )
340
- cells_markers = dfx.la.vector(detection_vector.index_map)
341
- cells_markers.array[interior_indices] = 1
342
- cells_markers.array[cut_indices] = 2
343
- cells_markers.array[exterior_indices] = 3
344
- cells_markers.scatter_forward()
345
374
 
346
- return cells_markers
375
+ # Create the meshtags from the indices.
376
+ indices = np.hstack([exterior_indices, interior_indices, cut_indices]).astype(
377
+ np.int32
378
+ )
379
+ interior_marker = np.full_like(interior_indices, 1).astype(np.int32)
380
+ exterior_marker = np.full_like(exterior_indices, 3).astype(np.int32)
381
+ cut_marker = np.full_like(cut_indices, 2).astype(np.int32)
382
+ markers = np.hstack([exterior_marker, interior_marker, cut_marker]).astype(np.int32)
383
+ sorted_indices = np.argsort(indices)
384
+
385
+ cells_tags = dfx.mesh.meshtags(
386
+ mesh, mesh.topology.dim, indices[sorted_indices], markers[sorted_indices]
387
+ )
388
+
389
+ return cells_tags
347
390
 
348
391
 
349
392
  def _tag_facets(
350
393
  mesh: Mesh,
351
- cells_markers: dfx.la.Vector,
394
+ cells_tags: MeshTags,
352
395
  discrete_levelset: Function,
353
396
  detection_degree: int,
354
- ) -> dfx.la.Vector:
397
+ ) -> MeshTags:
355
398
  """Tag the mesh facets.
356
399
  Strictly interior facets => tag 1
357
400
  Cut facets => tag 2
@@ -362,13 +405,12 @@ def _tag_facets(
362
405
 
363
406
  Args:
364
407
  mesh: the background mesh.
365
- cells_markers: the vector storing the cells markers.
408
+ cells_tags: the MeshTags object containing cells tags.
366
409
  discrete_levelset: the discretization of the levelset.
367
410
  detection_degree: the degree of the custom quadrature rule used to detect cut entities.
368
411
 
369
412
  Returns:
370
- The facets markers as a dfx.la.Vector object.
371
- The wireframe mesh containing all facets.
413
+ The facets tags as a MeshTags object.
372
414
  """
373
415
  cdim = mesh.topology.dim
374
416
  fdim = cdim - 1
@@ -379,9 +421,9 @@ def _tag_facets(
379
421
  c2f_map = np.reshape(c2f_connect.array, (-1, num_facets_per_cell))
380
422
 
381
423
  # Get tagged cells
382
- interior_cells = np.where(cells_markers.array[:] == 1)
383
- cut_cells = np.where(cells_markers.array[:] == 2)
384
- exterior_cells = np.where(cells_markers.array[:] == 3)
424
+ interior_cells = cells_tags.find(1)
425
+ cut_cells = cells_tags.find(2)
426
+ exterior_cells = cells_tags.find(3)
385
427
 
386
428
  # Check which background mesh boundary facets are cut by the interface
387
429
  background_mesh_boundary_facets = dfx.mesh.locate_entities_boundary(
@@ -403,7 +445,7 @@ def _tag_facets(
403
445
  mesh, discrete_levelset, detection_measure
404
446
  )
405
447
  mask_cut_indices_cells = np.logical_and(
406
- detection_vector.array[:] > -1.0, detection_vector.array[:] < 1.0
448
+ detection_vector > -1.0, detection_vector < 1.0
407
449
  )
408
450
  cut_indices_cells = np.where(mask_cut_indices_cells)[0]
409
451
  comp_indices_cells = np.where(np.logical_not(mask_cut_indices_cells))[0]
@@ -477,26 +519,52 @@ def _tag_facets(
477
519
  + " have a non-empty intersection!"
478
520
  )
479
521
 
480
- # Allocate distributed vectors supporting facets markers.
481
- all_facets = dfx.mesh.locate_entities(
482
- mesh, 1, lambda x: np.ones_like(x[0]).astype(bool)
522
+ # Create the meshtags from the indices.
523
+ indices = np.hstack(
524
+ [
525
+ exterior_facets,
526
+ interior_facets,
527
+ interior_boundary_facets,
528
+ cut_facets,
529
+ boundary_facets,
530
+ direct_interface_facets,
531
+ ]
532
+ ).astype(np.int32)
533
+ interior_marker = np.full_like(interior_facets, 1).astype(np.int32)
534
+ cut_marker = np.full_like(cut_facets, 2).astype(np.int32)
535
+ interior_boundary_marker = np.full_like(interior_boundary_facets, 3).astype(
536
+ np.int32
537
+ )
538
+ boundary_marker = np.full_like(boundary_facets, 4).astype(np.int32)
539
+ exterior_marker = np.full_like(exterior_facets, 5).astype(np.int32)
540
+ direct_interface_marker = np.full_like(direct_interface_facets, 6).astype(np.int32)
541
+ markers = np.hstack(
542
+ [
543
+ exterior_marker,
544
+ interior_marker,
545
+ interior_boundary_marker,
546
+ cut_marker,
547
+ boundary_marker,
548
+ direct_interface_marker,
549
+ ]
550
+ ).astype(np.int32)
551
+ sorted_indices = np.argsort(indices)
552
+
553
+ facets_tags = dfx.mesh.meshtags(
554
+ mesh, fdim, indices[sorted_indices], markers[sorted_indices]
483
555
  )
484
- wireframe = dfx.mesh.create_submesh(mesh, 1, all_facets)[0]
485
- cell_name_wf = wireframe.topology.cell_name()
486
- dg0_element_wf = element("DG", cell_name_wf, 0)
487
- dg0_space_wf = dfx.fem.functionspace(wireframe, dg0_element_wf)
488
- imap = dg0_space_wf.dofmap.index_map
489
- facets_markers = dfx.la.vector(imap)
490
556
 
491
- facets_markers.array[interior_facets] = 1
492
- facets_markers.array[cut_facets] = 2
493
- facets_markers.array[interior_boundary_facets] = 3
494
- facets_markers.array[boundary_facets] = 4
495
- facets_markers.array[exterior_facets] = 5
496
- facets_markers.array[direct_interface_facets] = 6
497
- facets_markers.scatter_forward()
557
+ return facets_tags
498
558
 
499
- return facets_markers
559
+
560
+ def _overwrite_tags(mesh, tags_to_overwrite, new_tags):
561
+ stack_indices = np.hstack([new_tags.indices, tags_to_overwrite.indices])
562
+ stack_values = np.hstack([new_tags.values, tags_to_overwrite.values])
563
+ overwritten_indices, ind = np.unique(stack_indices, return_index=True)
564
+ overwritten_values = stack_values[ind]
565
+
566
+ overwritten_tags = dfx.mesh.meshtags(mesh, tags_to_overwrite.dim, overwritten_indices, overwritten_values)
567
+ return overwritten_tags
500
568
 
501
569
 
502
570
  def compute_tags_measures(
@@ -505,6 +573,7 @@ def compute_tags_measures(
505
573
  detection_degree: int,
506
574
  box_mode: bool = False,
507
575
  single_layer_cut: bool = False,
576
+ overwrite_tags: dict[str,MeshTags] | dict = {},
508
577
  ) -> Tuple[
509
578
  MeshTags,
510
579
  MeshTags,
@@ -528,98 +597,71 @@ def compute_tags_measures(
528
597
  The boundaries measure.
529
598
  Submesh c-map, v-map and n-map.
530
599
  """
531
- cells_markers = _tag_cells(
600
+ cells_tags = _tag_cells(
532
601
  mesh, discrete_levelset, detection_degree, single_layer_cut=single_layer_cut
533
602
  )
534
- facets_markers = _tag_facets(
535
- mesh, cells_markers, discrete_levelset, detection_degree
536
- )
603
+ facets_tags = _tag_facets(mesh, cells_tags, discrete_levelset, detection_degree)
604
+
605
+ if "cells" in overwrite_tags.keys():
606
+ ow_cells_tags = overwrite_tags["cells"]
607
+ if np.any(np.isin([1, 2, 3], ow_cells_tags.values)):
608
+ raise ValueError("Cannot overwrite cells tags with values 1, 2 or 3.")
609
+ cells_tags = _overwrite_tags(mesh, cells_tags, ow_cells_tags)
610
+ if "facets" in overwrite_tags.keys():
611
+ ow_facets_tags = overwrite_tags["facets"]
612
+ if np.any(np.isin([1, 2, 3, 4, 5, 6], ow_facets_tags.values)):
613
+ raise ValueError("Cannot overwrite facets tags with values 1, 2, 3, 4, 5, 6, 100 or 101.")
614
+ facets_tags = _overwrite_tags(mesh, facets_tags, ow_facets_tags)
537
615
 
538
616
  if box_mode:
539
617
  submesh = None
540
- integration_cells = np.union1d(
541
- np.where(np.isclose(cells_markers.array[:], 2)),
542
- np.where(np.isclose(cells_markers.array[:], 1)),
543
- )
618
+ integration_cells = np.union1d(cells_tags.find(2), cells_tags.find(1))
544
619
  integration_entities_outside = _compute_integration_entities(
545
- mesh,
546
- integration_cells,
547
- np.where(np.isclose(facets_markers.array[:], 4)),
548
- 100,
549
- )
550
- integration_cells = np.union1d(
551
- np.where(np.isclose(cells_markers.array[:], 2)),
552
- np.where(np.isclose(cells_markers.array[:], 3)),
553
- )
620
+ mesh, integration_cells, facets_tags.find(4))
621
+ integration_entities_outside = [(100, integration_entities_outside)]
622
+ integration_cells = np.union1d(cells_tags.find(2), cells_tags.find(3))
554
623
  integration_entities_inside = _compute_integration_entities(
555
- mesh,
556
- integration_cells,
557
- np.where(np.isclose(facets_markers.array[:], 3)),
558
- 101,
559
- )
560
- combined_integration_entities = (
561
- integration_entities_outside + integration_entities_inside
562
- )
624
+ mesh, integration_cells, facets_tags.find(3))
625
+ integration_entities_inside = [(101, integration_entities_inside)]
626
+ combined_integration_entities = integration_entities_outside + integration_entities_inside
627
+
628
+ non_phifem_mask = ~np.isin(facets_tags.values, [1, 2, 3, 4, 5, 6])
629
+ fdim = facets_tags.dim
630
+ boundary_facets = dfx.mesh.locate_entities_boundary(mesh, fdim, lambda x: np.ones_like(x[0]).astype(bool))
631
+ non_phifem_facets_bdy = np.isin(facets_tags.indices, boundary_facets)
632
+ non_phifem_mask *= non_phifem_facets_bdy
633
+ non_phifem_facets_ind = np.arange(len(facets_tags.indices))[non_phifem_mask]
634
+ non_phifem_facets = facets_tags.indices[non_phifem_facets_ind]
635
+ non_phifem_facets_tags = np.unique(facets_tags.values[non_phifem_facets_ind])
636
+
637
+ for tag in non_phifem_facets_tags:
638
+ cdim = mesh.topology.dim
639
+ fdim = cdim - 1
640
+ mesh.topology.create_connectivity(fdim, cdim)
641
+ f2c_connect = mesh.topology.connectivity(fdim, cdim)
642
+ f2c_map = _reshape_map(f2c_connect)[0]
643
+
644
+ non_phifem_facets_cells = f2c_map[non_phifem_facets]
645
+
646
+ assert len(non_phifem_facets_cells) == len(non_phifem_facets)
647
+
648
+ combined_integration_entities += [(tag, _compute_integration_entities(mesh, non_phifem_facets_cells, facets_tags.find(tag)))]
563
649
 
564
650
  boundaries_measure = ufl.Measure(
565
651
  "ds", domain=mesh, subdomain_data=combined_integration_entities
566
652
  )
567
653
  submesh_maps = None
568
- indices = np.arange(
569
- cells_markers.index_map.size_local + cells_markers.index_map.num_ghosts
570
- )
571
- cells_tags = dfx.mesh.meshtags(
572
- mesh, mesh.topology.dim, indices, cells_markers.array[:]
573
- )
574
- indices = np.arange(
575
- facets_markers.index_map.size_local + facets_markers.index_map.num_ghosts
576
- )
577
- facets_tags = dfx.mesh.meshtags(
578
- mesh, mesh.topology.dim - 1, indices, facets_markers.array[:]
579
- )
580
654
  else:
581
655
  # We create the submesh
582
- omega_h_cells = np.unique(
583
- np.hstack(
584
- [
585
- np.where(np.isclose(cells_markers.array[:], 1)),
586
- np.where(np.isclose(cells_markers.array[:], 2)),
587
- ]
588
- )
589
- )
656
+ omega_h_cells = np.unique(np.hstack([cells_tags.find(1), cells_tags.find(2)]))
590
657
  submesh, c_map, v_map, n_map = dfx.mesh.create_submesh(
591
658
  mesh, mesh.topology.dim, omega_h_cells
592
- )
593
- submesh_maps = [c_map, v_map, n_map]
659
+ ) # type: ignore
594
660
 
595
- cells_markers_submesh = _transfer_markers(
596
- cells_markers, c_map, submesh.topology.dim
597
- )
598
- submesh.topology.create_entities(submesh.topology.dim - 1)
599
- submesh_imap = submesh.topology.index_map(submesh.topology.dim - 1)
600
- submesh_facets = np.arange(submesh_imap.size_local + submesh_imap.num_ghosts)
601
- wf_submesh, wf_map = dfx.mesh.create_submesh(
602
- submesh, submesh.topology.dim - 1, submesh_facets
603
- )[:2]
604
- wf_submesh.topology.create_entities(wf_submesh.topology.dim)
605
- facets_markers_subwf = _transfer_markers(
606
- facets_markers, wf_map, submesh.topology.dim - 1
607
- )
661
+ cells_tags = _transfer_tags(cells_tags, submesh, c_map)
662
+ facets_tags = _transfer_tags(facets_tags, submesh, c_map, source_mesh=mesh)
608
663
  boundaries_measure = ufl.Measure("ds", domain=submesh)
609
-
610
- indices = np.arange(
611
- cells_markers_submesh.index_map.size_local
612
- + cells_markers_submesh.index_map.num_ghosts
613
- )
614
- cells_tags = dfx.mesh.meshtags(
615
- submesh, submesh.topology.dim, indices, cells_markers_submesh.array[:]
616
- )
617
- facets_tags = dfx.mesh.meshtags(
618
- submesh,
619
- submesh.topology.dim - 1,
620
- submesh_facets,
621
- facets_markers_subwf.array[submesh_facets],
622
- )
664
+ submesh_maps = [c_map, v_map, n_map]
623
665
 
624
666
  return (
625
667
  cells_tags,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phiFEM
3
- Version: 0.7.0.dev1
3
+ Version: 0.7.1.dev2
4
4
  Summary: phiFEM: convenience tools to use the phiFEM immersed boundary finite element method with dolfinx.
5
5
  Project-URL: Homepage, https://github.com/PhiFEM/phiFEM
6
6
  Project-URL: Issues, https://github.com/PhiFEM/phiFEM/issues
@@ -113,6 +113,16 @@ To run the demos first clone the repository.
113
113
  pytest
114
114
  ```
115
115
 
116
+ ## Disclaimer
117
+
118
+ The author Raphaël Bulle guarantees that his contributions to this project are generative-ai-free.
119
+
120
+ <p align="center" width="50%">
121
+ <img width="30%" src="https://github.com/PhiFEM/phiFEM/raw/main/logo/sw_wbg.png">
122
+ </p>
123
+
124
+ For more information, see [here (in french)](https://doi.org/10.58079/1591s).
125
+
116
126
  ## License
117
127
 
118
128
  `phiFEM` is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -0,0 +1,7 @@
1
+ phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ phifem/mesh_scripts.py,sha256=NSciUpSeABNaZAHdihEI4yUqYZGSFk-NvjuRkSUqrhk,26963
3
+ phifem-0.7.1.dev2.dist-info/METADATA,sha256=JxTs9hdtq3hgmaVLZM4F8iCUkuSOb4SNkBfmawf01wo,5603
4
+ phifem-0.7.1.dev2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
5
+ phifem-0.7.1.dev2.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
6
+ phifem-0.7.1.dev2.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
7
+ phifem-0.7.1.dev2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.30.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,7 +0,0 @@
1
- phifem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- phifem/mesh_scripts.py,sha256=jVRTsIQRmEffTfhWHyJrqiImqtWZoiCBnSpuhW4W-Ho,24614
3
- phifem-0.7.0.dev1.dist-info/METADATA,sha256=R0NitwqmCfRUTMiH-p907mLfKPWTX1RTEXJaKO-f0YY,5285
4
- phifem-0.7.0.dev1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
5
- phifem-0.7.0.dev1.dist-info/licenses/COPYING,sha256=xTplwv1WHIfqq_EHLvXcq4ZTBCvBUwhGX1JBNYXrYnE,35146
6
- phifem-0.7.0.dev1.dist-info/licenses/COPYING.lesser,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
7
- phifem-0.7.0.dev1.dist-info/RECORD,,