Skip to content

Conversation

@ylgrst
Copy link
Collaborator

@ylgrst ylgrst commented Mar 29, 2025

Description

This branch adds strut-based lattice to Microgen. 12 pre-set lattice have been implemented:

  • BodyCenteredCubic
  • FaceCenteredCubic
  • Cubic
  • Octahedron
  • Cuboctahedron
  • Diamond
  • OctetTruss
  • RhombicCuboctahedron
  • RhombicDodecahedron
  • TruncatedCube
  • TruncatedCuboctahedron (aka Kelvin lattice)
  • TruncatedOctahedron

An AbstractLattice class has also been implemented to let the user define their own strut-based lattice, by providing the coordinates of the lattice's vertices, and the pairs of vertex indices forming the struts

Examples

Examples have been added: examples/Lattices/preset_lattice.py plots the 12 preset lattice listed before. examples/Lattices/custom_lattice.py illustrates how a user can define their own strut-based lattice, here an auxetic lattice based on this paper.

Tests

Tests are written in test_lattice.py using data from test_lattice_utils.py. This data basically corresponds to the expected vertices, strut centers and cartesian orientation coordinates. This ensures _compute_vertices, _compute_strut_centers, _compute_strut_directions work as expected.

ylgrst added 30 commits March 8, 2025 00:28
* Use scipy Rotation object instead of euler angles array
* boolean operations with vtk are too poorly managed,
and could not make cadquery's toVtkPolyData method work

* also update __init__
* setup strut_number and strut_heights for fixed implemented
lattice and for custom lattice created by user

* implement input checks
for predefined lattice classes
due to an unknown issue when meshing struts that intersect
two opposing faces of the boundary cube

computed_radius = root_scalar(
lambda radius: float(calc_density(radius)) - self.density,
bracket=[10e-4, 1.0 * self.cell_size],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a comment explaining what are you trying to do here may be helpful for maintenance and readability, also putting the magic number 10e-4 in a variable with a self explanatory name

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments have been added to explain the computed_radius

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10e-4 the magic number may indicate a tolerance ? If it does it would be worthy to store it un a variable with that name. Same applies for 1.0 * self.cell_size


computed_radius = root_scalar(
lambda radius: float(calc_density(radius)) - self.density,
bracket=[10e-4, 1.0 * self.cell_size],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments have been added to explain the computed_radius

def _generate_strut_vertex_pairs(self) -> npt.NDArray[np.int64]:
tree = KDTree(self.base_vertices)
pairs = set()
tolerance = 1e-5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tolerance could be a named constant ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tolerance value could be passed as parameter ? Or be added as a member of the abstract class AbstractLattice ? If it is required for each of the derived classes ? @ylgrst

Copy link
Collaborator Author

@ylgrst ylgrst May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have passed it to UPPER_CASE but as for extracting the constant, I am not sure whether to make it a class constant for AbstractLattice (because not all daughter classes use the constant) or general constant in the abstract_lattice.py file that I can then import when needed in the right daughter classes.
For now i have chosen this second option, what do you think would be the best practice?

def _generate_strut_vertex_pairs(self) -> npt.NDArray[np.int64]:
tree = KDTree(self.base_vertices)
pairs = set()
tolerance = 1e-5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tolerance = 1e-5 could be a named constant?


def _generate_strut_vertex_pairs(self) -> npt.NDArray[np.int64]:
tree = KDTree(self.base_vertices)
tolerance = 1e-5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tolerance = 1e-5 could be a named constant?

def _generate_strut_vertex_pairs(self) -> npt.NDArray[np.int64]:
"""Generate index pairs representing the struts in the truncated octahedron."""
tree = KDTree(self.base_vertices)
tolerance = 1e-5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tolerance = 1e-5 could be a named constant?

Copy link
Collaborator

@ricardo0115 ricardo0115 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ! , this PR includes a flexible API to generate Strut Lattice structures.


computed_radius = root_scalar(
lambda radius: float(calc_density(radius)) - self.density,
bracket=[10e-4, 1.0 * self.cell_size],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10e-4 the magic number may indicate a tolerance ? If it does it would be worthy to store it un a variable with that name. Same applies for 1.0 * self.cell_size

def _generate_strut_vertex_pairs(self) -> npt.NDArray[np.int64]:
tree = KDTree(self.base_vertices)
pairs = set()
tolerance = 1e-5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tolerance value could be passed as parameter ? Or be added as a member of the abstract class AbstractLattice ? If it is required for each of the derived classes ? @ylgrst

@ylgrst ylgrst merged commit 3452c40 into main Jun 12, 2025
26 checks passed
@ylgrst ylgrst deleted the feature_strut_lattice branch June 12, 2025 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants