From f1184fb1c0cafead4188963191338f2460f6e96a Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 04:19:07 +0000 Subject: [PATCH 1/6] retrieve individual curves from curve loops --- meshwell/labeledentity.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/meshwell/labeledentity.py b/meshwell/labeledentity.py index 5de9dbe..3227875 100644 --- a/meshwell/labeledentity.py +++ b/meshwell/labeledentity.py @@ -66,7 +66,12 @@ def filter_by_target_and_tags(target_dimension, tags, min_mass, max_mass): case 1: tags = self.boundaries case 2 | 3: - tags = [self.model.occ.getCurveLoops(b)[1] for b in self.boundaries] + tags = [ + c + for b in self.boundaries + for cs in self.model.occ.getCurveLoops(b)[1] + for c in cs + ] case -1: warnings.warn("Applying volume ResolutionSpec to surface, skipping") return [] From 1733aa9c7b9f4ab6184f436cc8ce10013a3df37c Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 04:19:52 +0000 Subject: [PATCH 2/6] return refined fields --- meshwell/resolution.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meshwell/resolution.py b/meshwell/resolution.py index 5ec6509..5e5c1e9 100644 --- a/meshwell/resolution.py +++ b/meshwell/resolution.py @@ -150,6 +150,8 @@ def refine(self, resolution_factor: float): if result.sizemin is not None: result.sizemin *= resolution_factor + return result + class ExponentialField(SampledField): """Exponential growth of the characteristic length away from the entity""" @@ -196,3 +198,5 @@ def refine(self, resolution_factor: float): result = copy.copy(self) if result.sizemin is not None: result.sizemin *= resolution_factor + + return result From a4c19a4a0752558e9d96bed29905aff7ff5b7dd9 Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 05:29:58 +0000 Subject: [PATCH 3/6] add test for refine --- tests/test_resolution.py | 55 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/test_resolution.py b/tests/test_resolution.py index 5824c93..3d57f8f 100644 --- a/tests/test_resolution.py +++ b/tests/test_resolution.py @@ -7,6 +7,7 @@ from meshwell.resolution import ConstantInField, ThresholdField, ExponentialField from meshwell.utils import compare_meshes from pathlib import Path +import pytest def test_2D_resolution(): @@ -150,6 +151,58 @@ def test_exponential_field(): ) +@pytest.mark.parametrize( + "field", + [ + ConstantInField(apply_to="surfaces", resolution=1), + ExponentialField( + growth_factor=2, + sizemin=0.3, + max_samplings=200, + apply_to="curves", + lengthscale=2, + ), + ThresholdField( + sizemin=1, + sizemax=5, + distmin=0, + distmax=5, + apply_to="curves", + ), + ], +) +def test_refine(field): + large_rect = 10 + + polygon1 = shapely.Polygon( + [[0, 0], [large_rect, 0], [large_rect, large_rect], [0, large_rect], [0, 0]], + ) + + points = [] + for factor in [0.5, 1, 2]: + model = Model(n_threads=1) # 1 thread for deterministic mesh + poly_obj2 = PolySurface( + polygons=polygon1, + model=model, + mesh_order=1, + physical_name="inner", + resolutions=[field.refine(factor)], + ) + + entities_list = [poly_obj2] + + output = model.mesh( + entities_list=entities_list, + default_characteristic_length=5, + verbosity=0, + filename="mesh_test_2D_exponential.msh", + ) + + points.append(len(output.points)) + + assert points[0] > points[1] > points[2] + + if __name__ == "__main__": - test_exponential_field() + test_refine(ConstantInField(apply_to="surfaces", resolution=1)) # test_3D_resolution() From e949222bba5eddcb20924c5e769b175bbb092dd3 Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 06:08:06 +0000 Subject: [PATCH 4/6] fix filtering more --- meshwell/labeledentity.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/meshwell/labeledentity.py b/meshwell/labeledentity.py index 3227875..5c74f49 100644 --- a/meshwell/labeledentity.py +++ b/meshwell/labeledentity.py @@ -57,7 +57,11 @@ def filter_by_target_and_tags(target_dimension, tags, min_mass, max_mass): for tag in tags if min_mass < self.model.occ.getMass(target_dimension, tag) < max_mass ] - return {tag: self.model.occ.getMass(target_dimension, tag) for tag in tags} + return ( + {tag: self.model.occ.getMass(target_dimension, tag) for tag in tags} + if tags is not [] + else {} + ) # Filter the tags based on current dimension and target match self.dim - target_dimension: @@ -74,15 +78,17 @@ def filter_by_target_and_tags(target_dimension, tags, min_mass, max_mass): ] case -1: warnings.warn("Applying volume ResolutionSpec to surface, skipping") - return [] + return {} # If targeting points, need post-filtering filtering if target_dimension == 0: filtered_tags = filter_by_target_and_tags(1, tags, min_mass, max_mass) - return ( - self.model.getBoundary([(0, tag) for tag in filtered_tags]), - None, - ) # no mass in 0D + return { + p: None + for p in self.model.getBoundary( + [(1, tag) for tag in filtered_tags.keys()] + ) + } # no mass in 0D else: return filter_by_target_and_tags(target_dimension, tags, min_mass, max_mass) From db8dc402a828c27df7df42930e985dff2e102f3c Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 06:11:26 +0000 Subject: [PATCH 5/6] get point --- meshwell/labeledentity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshwell/labeledentity.py b/meshwell/labeledentity.py index 5c74f49..8562a14 100644 --- a/meshwell/labeledentity.py +++ b/meshwell/labeledentity.py @@ -84,7 +84,7 @@ def filter_by_target_and_tags(target_dimension, tags, min_mass, max_mass): if target_dimension == 0: filtered_tags = filter_by_target_and_tags(1, tags, min_mass, max_mass) return { - p: None + p[1]: None for p in self.model.getBoundary( [(1, tag) for tag in filtered_tags.keys()] ) From 6c7bf7b1da49ebb70520f84bf33eb663da352889 Mon Sep 17 00:00:00 2001 From: Simon Bilodeau Date: Mon, 4 Nov 2024 06:12:01 +0000 Subject: [PATCH 6/6] add incomplete test case --- tests/test_resolution.py | 79 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/tests/test_resolution.py b/tests/test_resolution.py index 3d57f8f..e32f7ba 100644 --- a/tests/test_resolution.py +++ b/tests/test_resolution.py @@ -8,6 +8,7 @@ from meshwell.utils import compare_meshes from pathlib import Path import pytest +import numpy as np def test_2D_resolution(): @@ -203,6 +204,82 @@ def test_refine(field): assert points[0] > points[1] > points[2] +# FIXME: add regression +@pytest.mark.parametrize( + ("apply_to", "min_mass", "max_mass"), + [ + ("volumes", 5**3, np.inf), + ("volumes", 0, 5**3), + ("surfaces", 5**2, np.inf), + ("surfaces", 0, 5**2), + ("curves", 5, np.inf), + ("curves", 0, 5), + ("points", 5, np.inf), + ("points", 0, 5), + ], +) +def test_filter(apply_to, min_mass, max_mass): + large_rect = 6 + small_rect = 4 + + buffers1 = {-6: 0, 6: 0} + buffers2 = {-4: 0, 4: 0} + + polygon1 = shapely.Polygon( + [ + [-large_rect / 2, -large_rect / 2], + [large_rect / 2, -large_rect / 2], + [large_rect / 2, large_rect / 2], + [-large_rect / 2, large_rect / 2], + [-large_rect / 2, -large_rect / 2], + ], + ) + polygon2 = shapely.Polygon( + [ + [-small_rect / 2, -small_rect / 2], + [small_rect / 2, -small_rect / 2], + [small_rect / 2, small_rect / 2], + [-small_rect / 2, small_rect / 2], + [-small_rect / 2, -small_rect / 2], + ], + ) + + model = Model(n_threads=1) # 1 thread for deterministic mesh + prism1 = Prism( + polygons=polygon1, + buffers=buffers1, + model=model, + mesh_order=2, + physical_name="outer", + resolutions=[ + ConstantInField( + apply_to=apply_to, resolution=0.5, min_mass=min_mass, max_mass=max_mass + ) + ], + ) + prism2 = Prism( + polygons=polygon2, + buffers=buffers2, + model=model, + mesh_order=1, + physical_name="inner", + resolutions=[ + ConstantInField( + apply_to=apply_to, resolution=0.5, min_mass=min_mass, max_mass=max_mass + ) + ], + ) + + entities_list = [prism1, prism2] + + model.mesh( + entities_list=entities_list, + default_characteristic_length=5, + verbosity=0, + filename="mesh_filter.msh", + ) + + if __name__ == "__main__": - test_refine(ConstantInField(apply_to="surfaces", resolution=1)) + test_filter("points", 5, np.inf) # test_3D_resolution()