Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.6.0 - 2026-10-18¶
Added¶
Periodic microstructures, in 2D and 3D. The
<periodic>field of the domain selects the periodic axes:True(or1) for all of them, or their names, such asxz. The same option is an argument ofcli.run,SeedList.positionandPolyMesh.from_seeds.Periodic seed placement: seeds crossing a periodic face are placed without overlapping the seeds on the opposite side.
Periodic tessellation: the Laguerre tessellation is periodic across the faces. Cells crossing a face are cut, and their pieces tile the domain.
Periodic meshes: the triangular, tetrahedral and raster meshes have matching nodes on opposite faces. The quality and size settings (
min_angle,max_volume, themax_volumeof each phase,max_edge_length) act as on non-periodic meshes. In 2D, the cells next to the periodic faces are copied outside the faces while meshing, so that Triangle refines both faces the same way. In 3D, the facets are triangulated with the points that TetGen adds on them in a first pass, identically on opposite faces, and the mesh is built again with the facets fixed.gmsh is not supported for periodic meshes, which need the default mesher, Triangle/TetGen.
Output of periodic meshes: the pairs of periodic points, nodes and facets are stored in the meshes and in their text files. The Abaqus output has a node set per periodic face, in matching order. The verification unwraps grains that are split by the faces.
Cells of the same amorphous phase that touch across a periodic face are merged into one region, like cells that share a facet. Every mesher and writer labels the merged region with the smallest seed number among its cells.
The element attributes and the facets of periodic meshes are computed from the geometry of the polymesh. TetGen can leave sub-faces of a facet unmarked when it may not modify the boundary, and its region attributes then leak between cells.
Examples:
periodic_2D.xml,periodic_3D.xmlandperiodic_tiling.pydemonstrate periodic microstructures,pbx_2D.xmlandpbx_3D.xmla periodic particulate composite (crystalline inclusions in a binder), andpbx_interface_2D.xmlandpbx_interface_3D.xmlmeshes refined at the grain boundaries.periodic_margin(a setting, and an argument ofSeedList.positionandcli.run): the minimum distance between the surface of a seed and a periodic face. A seed that ends within the margin of a face, or crosses it by less, is placed elsewhere, since it would leave a thin piece of its grain on the opposite face and elements much smaller than the target size of the mesh there.autouses half the target edge length of the mesh, or an eighth of the size of the smallest seed if that is smaller (the smallest seed needs about four elements across it, and cannot satisfy a margin larger than itself).PolyMesh.from_seeds(edge_opt=True, periodic_margin=...): the edge optimization of periodic meshes treats the thickness of each piece of a cell at a periodic face as a feature, like an edge. It moves the seeds of the pieces thinner than the margin, and of their neighbors, normal to the face, until the piece reaches the margin or the cell no longer crosses the face. The CLI passes itsperiodic_marginsetting on.PolyMesh.from_seeds(edge_opt=True, min_angle=...): the corners of the cells at the periodic faces narrower than the minimum angle of the mesh are features too, since the mesher cannot reach the minimum angle there and fills them with shells of very small elements. The seeds on both sides of the facet are moved along it to open the corner. The CLI passesmesh_min_angle.Edge optimization: a trial is now kept when the shortest feature that it changes gets longer (for the shortest edge of the mesh, the criterion is unchanged). A target that does not improve in
n_itertrials is left alone and the next one is taken, and the seeds moved across a periodic face are wrapped back into the domain. The CLI writes and plots the seeds again after the optimization, so that the seed files match the polygonal mesh. The periodic examples useperiodic_marginautoandedge_opt.When the nodes on the periodic faces of a 2D mesh do not match after the first pass, the next pass starts from all the points of the mesh (those on a periodic face and on its image merged and put on both faces), so that Triangle only refines it around the merged points, instead of meshing the cells again with the points on the faces only, which split the narrow corners of the cells again at every pass, down to very small elements. The copies of the cells at the corners of the domain, used while meshing, were open on one side and partly discarded by Triangle.
Fixed¶
Seed generation is reproducible: the RNG seed chain no longer depends on the (hash-randomized) iteration order of the phase keywords, and
SeedList.from_infoandcli.runno longer modify therng_seedsandfiletypesarguments (or their mutable defaults).<dist_type> cdf </dist_type>inputs are no longer distorted when the x-values in the CSV file are not evenly spaced (density=Falseis now passed toscipy.stats.rv_histogram).pdfis accepted as an alias ofhistogram.3D
mesh_max_volumeand per-phasemax_volumeare now honored by TetGen. In 2D, a per-phasemax_volumelarger than the global value is no longer capped, and an infinitemesh_max_volumeis no longer passed to Triangle as the (mis-parsed) switchainf. Themax_volumeof 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.approximatemapped 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.Seeds read back from
seeds.txtcan be repositioned. Ellipsoid seeds with a rotation sequence are written in a form that can be read back.Cells that intersect a circular or elliptical domain without having a vertex inside it are no longer dropped, cells cut twice by the boundary are clipped correctly, and the stored areas of clipped cells are correct (
PolyMesh.volumes,verification.volume_fractions)._segment_crossno longer hangs for large coordinate values, andsample_pos_withinraises instead of looping forever when the position distribution does not cover the domain.cli.plot_trino longer hangs in 3D when a void grain touches the boundary of the domain.Relative
<filename>and<directory>paths inside repeated tags (e.g. several<material>blocks) are resolved relative to the input file. A top-level<include>no longer discards materials, values such astrue_cdf.csvno longer cause infinite recursion, andinfis parsed as a float.Verification:
angle_radinputs are no longer replaced by a uniform distribution,<orientation> random </orientation>and vector-valued parameters (side_lengths,axes) no longer crash, unknown phase fields are ignored, the caller’s phases are not modified. The statistics of 2D orientations compare the angles modulo the symmetry of the shape, a half turn for ellipses and rectangles and a quarter turn for squares.RasterMesh: elements are counter-clockwise / right-handed (valid for Abaqus CPS4/C3D8), facets and their attributes are correct,vtkandabaqusoutput work (including with voids), 3D plotting works.TriMesh.write: valid.ele/.edge/.facefiles, Abaqus exterior surface unions reference only defined surfaces, full-precision points in text files, no dangling headers for meshes without attributes.PolyMesh.from_seeds(edge_opt=True)leaves the seed list in the accepted state (positions and breakdowns consistent) and is quiet unlessverbose.PolyMesh.write(format='poly')writes the file, andPolyMesh.__eq__is silent and no longer cubic.CircleandSphereare hashable, by identity, like the other geometries, so they can be put in sets and used as dictionary keys.Ellipse(axes=...),Ellipse(matrix=...),Ellipsoid(c=.., ratio_bc=..),Square.area_expectation(side_lengths=...), the*_expectationmethods with numpy scalars,Sphere.plotand 3DPolyMesh.plot/SeedList.plot_breakdownon a fresh figure,Rectangle.withinfor rotated rectangles,reflectfor ellipses and ellipsoids, single-materialcolor_bysettings, numpy arrays as per-item plot keywords.
Changed¶
pyvoro is installed from the
pyvoro-rimolipackage instead ofpyvoro-mmalahe. Both provide the samepyvoromodule. pyvoro-mmalahe bundles Voro++ 0.4.6, whose radical (Laguerre) tessellation can return a cell uncut when the compiler fuses multiply-adds. On macOS, pip compiles pyvoro-mmalahe from source, and Apple clang fuses them by default on Apple silicon. The cells then overlap, and Triangle and TetGen can crash on the resulting polygonal mesh. pyvoro-rimoli bundles the current Voro++, which gives the same cells either way, and has wheels for Linux, macOS and Windows. Uninstall pyvoro-mmalahe before upgrading (pip uninstall pyvoro-mmalahe), since the two packages install the same files.The continuous integration installs the current pytest and no longer installs tox from the requirements. The pinned tox 3.14 forced an old pluggy, with which pytest itself fails to import, so no test could run. The jobs of the test matrix no longer cancel each other on a failure.
Read the Docs builds the documentation with Python 3.10 instead of 3.8, which pyvoro-rimoli and the current versions of other dependencies do not support. It installs
requirements.txtlike the documentation check of the continuous integration, anddocs/requirements.txtalso keeps numpy below 2, so that numpy is installed once.The facets of the triangular and tetrahedral meshes created from a polygonal mesh are sorted (nodes in ascending order within a facet, facets in lexicographic order), whatever the mesher. Triangle and TetGen list the edges/faces of a mesh in an order, and with an orientation, that vary from one run to the next, so the mesh files of otherwise identical runs differed in the order of their facets.
max_edge_length(mesh_max_edge_length) acts in 3D on the triangles of the grain boundaries: when it is set, the facets of the polyhedral mesh are triangulated to that edge length (with Triangle, minimum angle 20 degrees) before TetGen meshes the cells, for periodic and non-periodic meshes alike, so that the elements can be smaller at the interfaces than inside the grains (see thepbx_interface_3D.xmlexample). The geometric tests of a mesh against its polymesh use the non-planarity of the facets (from the snapping of the points to the periodic faces) as their tolerance, and each element is assigned to the cell in which its centroid is deepest.Ellipsoid.limitsis exact for rotated ellipsoids (it was sampled).A
Seedcreated with aposition(or a geometry with a center) has its breakdown at that position. The geometry center is no longer reset to the origin.Ellipse,EllipsoidandNBoxgeometries compare equal when their parameters are equal, and keep their identity-based hash.Unused sampling helpers were removed from
seeding.seedlist.
1.5.9 - 2023-10-05¶
Added¶
Support for Python 3.12
Changed¶
Updated version numbers of dependencies per security report.
1.5.8 - 2023-08-25¶
Added¶
Support for Python 3.11
Fixed¶
Errors associated with using keyword arguments in
plt.gca()deprecated in matplotlib 3.4.
1.5.7 - 2023-08-06¶
Fixed¶
Errors associated with using keyword arguments in
plt.gca()deprecated in matplotlib 3.4.3D plots now use matplotlib standard for setting equal aspect ratios.
1.5.6 - 2022-09-01¶
Fixed¶
Bug in RasterMesh VTK writer.
1.5.5 - 2022-08-31¶
Changed¶
VTK writer for RasterMesh uses
RECTILINEAR_GRIDdata type.
1.5.4 - 2022-04-16¶
Added¶
Support for Python 3.9 and 3.10.
Changed¶
Dependent versions of NumPy, SciPy, and matplotlib.
Removed¶
Support for Python 3.7 and below.
Security¶
Upgraded to NumPy v1.22.0 to address overflow vulnerability.
1.5.3 - 2022-03-30¶
Fixed¶
String types in generating Abaqus inp files.
1.5.2 - 2021-09-09¶
Fixed¶
Plotting 3D raster meshes.
1.5.1 - 2021-09-09¶
Fixed¶
Plaid issue in 2D raster mesh array output.
Initialization and plotting of 3D raster meshes.
1.5.0 - 2021-09-08¶
Added¶
RasterMesh class, to create pixel/voxel meshes. (addresses #44)
1.4.10 - 2021-06-08¶
Fixed¶
Bug in gmsh for multi-circle seeds.
1.4.9 - 2021-05-14¶
Fixed¶
Bug in gmsh for amorphous and void phases.
1.4.8 - 2021-05-13¶
Fixed¶
Default behavior of
cli.plot_*functions whenplot_filesis not specified.
1.4.7 - 2021-02-07¶
Changed¶
Updated numpy and matplotlib versions.
Fixed¶
String parsing errors.
1.4.6 - 2021-02-07¶
Fixed¶
String parsing errors.
Logo example failing on ReadTheDocs.
3D gmsh with variable mesh sizes.
1.4.5 - 2020-12-24¶
Added¶
Meshing with gmsh can now use different mesh sizes in the interior and on the boundary of grains. The
<mesh_max_edge_length>tag specifies edge lengths on the boundary and<mesh_size>on the interior. If<mesh_max_edge_length>is not used,<mesh_size>is used throughout.
1.4.4 - 2020-12-22¶
Fixed¶
Reading absolute paths from
<include>tags.
1.4.3 - 2020-11-11¶
Fixed¶
PLY file format in 2D.
1.4.2 - 2020-11-3¶
Fixed¶
XML parsing text with parentheses.
1.4.1 - 2020-10-13¶
Changed¶
Upgraded to pygmsh v7.0.2.
1.4.0 - 2020-10-06¶
Added¶
References within XML input files using the
<include>tag.Support for gmsh. (addresses #16)
Citation to SoftwareX publication.
Fixed¶
Color-by seed number in CLI TriMesh plot function.
Expansion of “~” in input filepaths.
1.3.5 - 2020-09-20¶
Fixed¶
Tetrahedral mesh maximum volume setting no longer ignored.
1.3.4 - 2020-08-31¶
Removed¶
Debug print statements from SeedList population fractions method.
1.3.3 - 2020-08-31¶
Added¶
Helper functions for SeedList class.
Fixed¶
Dictionary conversion issue with lists of SciPy distributions.
XML tags in documentation on position distributions.
1.3.2 - 2020-07-11¶
Added¶
VTK output for 2D triangular meshes.
Changed¶
Updated reference to CMAME publication.
1.3.1 - 2020-07-09¶
Added¶
VTK output for seed lists and polyhedral meshes.
Option to compute expected area of ellipse from area distribution.
Option to compute expected volume of ellipsoid from volume distribution.
Fixed¶
Error in verification module for 2D uniform random orientations.
1.3.0 - 2020-06-25¶
Added¶
Option to reduce the presence of short edges in polygonal meshes.
Changed¶
Optimized seed positioning algorithm by using breadth-first search in the AABB tree.
Facets in polygonal meshes are now always defined with a positive outward normal vector.
Fixed¶
Plotting of 3D meshes.
Documentation for empirical PDFs.
Minor errors in examples.
1.2.2 - 2020-05-14¶
Fixed¶
Matplotlib error with undefined axes.
1.2.1 - 2020-05-14¶
Changed¶
Plot methods automatically update figure axes.
Fixed¶
CLI plotting function for triangular/tetrahedral meshes.
1.2.0 - 2020-05-13¶
Added¶
Options to shorten input keyword argument lists for plot methods (addresses #14)
Changed¶
Ellipse of best fit method calls the lsq-ellipse package.
Removed¶
Removed support for Python 2.7.
1.1.2 - 2019-11-07¶
Fixed¶
Paths to demo files in CLI, moved into source directory.
1.1.1 - 2019-11-05¶
Added¶
DOI links to readme and documentation.
Changed¶
Added logos, icons, social meta data for HTML documentation.
Fixed¶
Paths to demo files in CLI.
1.1.0 - 2019-09-27¶
Added¶
An
__add__method to the SeedList class.
Changed¶
Project documentation.
1.0.1 - 2019-09-07¶
Changed¶
Project documentation.
Made project name lowercase in PyPI.
1.0.0 - 2019-09-07¶
Added¶
Project added to GitHub.