diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cbbdbc3..7b5f16c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -97,7 +97,10 @@ Fixed - 3D ``mesh_max_volume`` and per-phase ``max_volume`` are now honored by TetGen. In 2D, a per-phase ``max_volume`` larger than the global value is no longer capped, and an infinite ``mesh_max_volume`` is no longer passed - to Triangle as the (mis-parsed) switch ``ainf``. + to Triangle as the (mis-parsed) switch ``ainf``. The ``max_volume`` of a + phase replaces the global value for that phase, an infinite one included, + and phases without one, such as the default phases when none are given, + use the global value. - ``Ellipsoid.approximate`` mapped the axes incorrectly for the ordering c >= a >= b, so those grains were tessellated with the wrong orientation. The b >= c >= a ordering is now sorted explicitly as well. diff --git a/docs/source/sphinx_gallery/plot_demos.py b/docs/source/sphinx_gallery/plot_demos.py index bf455ec..3692b42 100644 --- a/docs/source/sphinx_gallery/plot_demos.py +++ b/docs/source/sphinx_gallery/plot_demos.py @@ -24,7 +24,7 @@ # them is edited, and the build would serve stale figures. # # Managed by docs/example_digest.py. Do not edit by hand. -EXAMPLES_DIGEST = '2d39355b71ddd257' +EXAMPLES_DIGEST = '22bb4ed7ea2ddd9f' example_dir = '../../../src/microstructpy/examples' diff --git a/src/microstructpy/meshing/trimesh.py b/src/microstructpy/meshing/trimesh.py index b7b7f7c..c72350f 100644 --- a/src/microstructpy/meshing/trimesh.py +++ b/src/microstructpy/meshing/trimesh.py @@ -217,8 +217,8 @@ def from_polymesh(cls, polymesh, phases=None, mesher='Triangle/Tetgen', polymesh (PolyMesh): A polygon/polyhedron mesh. phases (list): *(optional)* A list of dictionaries containing options for each phase. - Default is - ``{'material_type': 'solid', 'max_volume': float('inf')}``. + Default is ``{'material_type': 'solid'}`` for each phase, + meshed with the ``max_volume`` argument. mesher (str): {'Triangle/TetGen' | 'Triangle' | 'TetGen' | 'gmsh'} specify the mesh generator. Default is 'Triangle/TetGen'. min_angle (float): The minimum interior angle, in degrees, of an @@ -844,8 +844,7 @@ def from_polymesh(cls, polymesh, mesh_size, phases=None): mesh_size (float): The side length of each pixel/voxel. phases (list): *(optional)* A list of dictionaries containing options for each phase. - Default is - ``{'material_type': 'solid', 'max_volume': float('inf')}``. + Default is ``{'material_type': 'solid'}`` for each phase. """ if phases is None: @@ -1965,10 +1964,13 @@ def _amorphous_seed_numbers(pmesh, phases): def _default_phases(polymesh): - """Default phases: one solid phase per phase number of the polymesh.""" + """Default phases: one solid phase per phase number of the polymesh. + + They have no ``max_volume``, so the ``max_volume`` argument of the + mesher applies to their regions. + """ n_phases = int(np.max(polymesh.phase_numbers)) + 1 - return [{'material_type': 'solid', 'max_volume': float('inf')} - for _ in range(n_phases)] + return [{'material_type': 'solid'} for _ in range(n_phases)] def _pt3d(pt): diff --git a/tests/meshing/test_trimesh_fixes.py b/tests/meshing/test_trimesh_fixes.py index dbe0623..4fb7d83 100644 --- a/tests/meshing/test_trimesh_fixes.py +++ b/tests/meshing/test_trimesh_fixes.py @@ -342,6 +342,19 @@ def test_triangle_per_phase_max_volume_exceeds_global(case_2d): assert np.all(areas[elem_phases != 0] <= 1e-3 + 1e-9) +@pytest.mark.parametrize('periodic', [False, True]) +def test_triangle_max_volume_without_phases(periodic): + # Without phases, the max_volume argument limits the area of the + # triangles. The default phases must not carry a limit of their own, + # which would replace it (an infinite one left it unapplied). + domain = msp.geometry.Square(side_length=4, corner=(0, 0)) + seeds = msp.seeding.SeedList([msp.seeding.Seed.factory( + 'circle', r=1.5, position=(2.2, 1.9))]) + pmesh = msp.meshing.PolyMesh.from_seeds(seeds, domain, periodic=periodic) + mesh = TriMesh.from_polymesh(pmesh, min_angle=20, max_volume=0.4) + assert np.max(simplex_volumes(mesh)) <= 0.4 + 1e-9 + + def test_triangle_infinite_max_volume_not_passed(case_2d, monkeypatch): pmesh, phases, _ = case_2d captured = {}