Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory block refactor #296

Merged
merged 19 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8d34e7b
refactor: modify implementation of make_block_memory_metadata functio…
sy-cui Sep 4, 2023
41ad249
feat: test_memory_block for straight rods. Modify BaseRodForTesting d…
sy-cui Sep 5, 2023
896a1da
refactor: remove custom marker from test_make_block_memory_metadata
sy-cui Sep 5, 2023
4cf74fb
refactor: rename test_memory_block to test_memory_block_cosserat_rod …
sy-cui Sep 5, 2023
2bccd08
refactor: prepend underscores '_' to initialization functions, and mo…
sy-cui Sep 5, 2023
47f5884
fix: fix rate collection indexing
sy-cui Sep 5, 2023
63866b7
test: add self check to test_memory_block_rod_straight_rods
sy-cui Sep 5, 2023
f0610c0
refactor: add mapping helper function in memory block to avoid code r…
sy-cui Sep 5, 2023
b8c7ba6
refactor: replace np.all(. == .) assertion with np.testing.assert_arr…
sy-cui Sep 6, 2023
503186f
test: test_make_block_memory_periodic_boundary_metadata
sy-cui Sep 7, 2023
9c32387
test: test_memory_block_rod_straight_rod now also test ring rods, and…
sy-cui Sep 7, 2023
4b76c3f
chore: restructure if statement in memory_block_rod.py to avoid code …
sy-cui Sep 7, 2023
d977a32
refactor: switch self-check and cross-check order
sy-cui Sep 7, 2023
bcf3aa9
refactor: change type hints and doc string
sy-cui Sep 7, 2023
4dfeb88
test: test cases for rigid body memory block
sy-cui Sep 7, 2023
f9d83d3
docs: add docstring to test_memory_block_rod
sy-cui Sep 7, 2023
854898d
test: add more parameterized number of rigid bodies into test
sy-cui Sep 7, 2023
c6aeb21
refactor: add mapping function to memory_block_rigid_body to avoid co…
sy-cui Sep 7, 2023
c4f7048
fix: add ring_rod_falg to construct_memory_block test
sy-cui Sep 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 83 additions & 57 deletions elastica/memory_block/memory_block_rigid_body.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
__doc__ = """Create block-structure class for collection of rigid body systems."""
import numpy as np
from typing import Sequence, List
from typing import Sequence, Literal

from elastica.rigidbody import RigidBodyBase
from elastica.rigidbody.data_structures import _RigidRodSymplecticStepperMixin


class MemoryBlockRigidBody(RigidBodyBase, _RigidRodSymplecticStepperMixin):
def __init__(self, systems: Sequence, system_idx_list: List[int]):
def __init__(self, systems: Sequence, system_idx_list: Sequence[np.int64]):

self.n_bodies = len(systems)
self.n_elems = self.n_bodies
self.n_nodes = self.n_elems
self.system_idx_list = np.array(system_idx_list, dtype=np.int64)

# Allocate block structure using system collection.
self.allocate_block_variables_scalars(systems)
self.allocate_block_variables_vectors(systems)
self.allocate_block_variables_matrix(systems)
self.allocate_block_variables_for_symplectic_stepper(systems)
self._allocate_block_variables_scalars(systems)
self._allocate_block_variables_vectors(systems)
self._allocate_block_variables_matrix(systems)
self._allocate_block_variables_for_symplectic_stepper(systems)

# Initialize the mixin class for symplectic time-stepper.
_RigidRodSymplecticStepperMixin.__init__(self)

def allocate_block_variables_scalars(self, systems: Sequence):
def _allocate_block_variables_scalars(self, systems: Sequence):
"""
This function takes system collection and allocates the variables for
block-structure and references allocated variables back to the systems.
Expand Down Expand Up @@ -55,19 +55,14 @@ def allocate_block_variables_scalars(self, systems: Sequence):
(len(map_scalar_dofs_in_rigid_bodies), self.n_elems)
)

for k, v in map_scalar_dofs_in_rigid_bodies.items():
self.__dict__[k] = np.lib.stride_tricks.as_strided(
self.scalar_dofs_in_rigid_bodies[v], (self.n_elems,)
)

for k, v in map_scalar_dofs_in_rigid_bodies.items():
for system_idx, system in enumerate(systems):
self.__dict__[k][..., system_idx : system_idx + 1] = system.__dict__[k]
system.__dict__[k] = np.ndarray.view(
self.__dict__[k][..., system_idx : system_idx + 1]
)
self._map_system_properties_to_block_memory(
mapping_dict=map_scalar_dofs_in_rigid_bodies,
systems=systems,
block_memory=self.scalar_dofs_in_rigid_bodies,
value_type="scalar",
)

def allocate_block_variables_vectors(self, systems: Sequence):
def _allocate_block_variables_vectors(self, systems: Sequence):
"""
This function takes system collection and allocates the vector variables for
block-structure and references allocated vector variables back to the systems.
Expand Down Expand Up @@ -96,28 +91,21 @@ def allocate_block_variables_vectors(self, systems: Sequence):
(len(map_vector_dofs_in_rigid_bodies), 3 * self.n_elems)
)

for k, v in map_vector_dofs_in_rigid_bodies.items():
self.__dict__[k] = np.lib.stride_tricks.as_strided(
self.vector_dofs_in_rigid_bodies[v], (3, self.n_elems)
)

for k, v in map_vector_dofs_in_rigid_bodies.items():
for system_idx, system in enumerate(systems):
self.__dict__[k][..., system_idx : system_idx + 1] = system.__dict__[
k
].copy()
system.__dict__[k] = np.ndarray.view(
self.__dict__[k][..., system_idx : system_idx + 1]
)
self._map_system_properties_to_block_memory(
mapping_dict=map_vector_dofs_in_rigid_bodies,
systems=systems,
block_memory=self.vector_dofs_in_rigid_bodies,
value_type="vector",
)

def allocate_block_variables_matrix(self, systems: Sequence):
def _allocate_block_variables_matrix(self, systems: Sequence):
"""
This function takes system collection and allocates the matrix variables for
block-structure and references allocated matrix variables back to the systems.

Parameters
----------
system
systems

Returns
-------
Expand All @@ -139,21 +127,14 @@ def allocate_block_variables_matrix(self, systems: Sequence):
(len(map_matrix_dofs_in_rigid_bodies), 9 * self.n_elems)
)

for k, v in map_matrix_dofs_in_rigid_bodies.items():
self.__dict__[k] = np.lib.stride_tricks.as_strided(
self.matrix_dofs_in_rigid_bodies[v], (3, 3, self.n_elems)
)

for k, v in map_matrix_dofs_in_rigid_bodies.items():
for system_idx, system in enumerate(systems):
self.__dict__[k][..., system_idx : system_idx + 1] = system.__dict__[
k
].copy()
system.__dict__[k] = np.ndarray.view(
self.__dict__[k][..., system_idx : system_idx + 1]
)
self._map_system_properties_to_block_memory(
mapping_dict=map_matrix_dofs_in_rigid_bodies,
systems=systems,
block_memory=self.matrix_dofs_in_rigid_bodies,
value_type="tensor",
)

def allocate_block_variables_for_symplectic_stepper(self, systems: Sequence):
def _allocate_block_variables_for_symplectic_stepper(self, systems: Sequence):
"""
This function takes system collection and allocates the variables used by symplectic
stepper for block-structure and references allocated variables back to the systems.
Expand Down Expand Up @@ -181,11 +162,12 @@ def allocate_block_variables_for_symplectic_stepper(self, systems: Sequence):
"alpha_collection": 3,
}
self.rate_collection = np.zeros((len(map_rate_collection), 3 * self.n_elems))
for k, v in map_rate_collection.items():
self.__dict__[k] = np.lib.stride_tricks.as_strided(
self.rate_collection[v], (3, self.n_elems)
)

self._map_system_properties_to_block_memory(
mapping_dict=map_rate_collection,
systems=systems,
block_memory=self.rate_collection,
value_type="vector",
)
# For Dynamic state update of position Verlet create references
self.v_w_collection = np.lib.stride_tricks.as_strided(
self.rate_collection[0:2], (2, 3 * self.n_elems)
Expand All @@ -195,11 +177,55 @@ def allocate_block_variables_for_symplectic_stepper(self, systems: Sequence):
self.rate_collection[2:-1], (2, 3 * self.n_elems)
)

for k, v in map_rate_collection.items():
def _map_system_properties_to_block_memory(
self,
mapping_dict: dict,
systems: Sequence,
block_memory: np.ndarray,
value_type: Literal["scalar", "vector", "tensor"],
) -> None:
"""Map system (rigid bodies) properties to memory blocks.

Parameters
----------
mapping_dict: dict
Dictionary with attribute names as keys and block row index as values.
systems: Sequence
A sequence containing Cosserat rod objects to map from.
block_memory: ndarray
Memory block that, at the end of the method execution, contains all designated
attributes of all systems.
value_type: str
A string that indicates the shape of the attribute.
Options among "scalar", "vector", and "tensor".

"""
if value_type == "scalar":
view_shape = (self.n_elems,)

elif value_type == "vector":
view_shape = (3, self.n_elems)

elif value_type == "tensor":
view_shape = (3, 3, self.n_elems)

else:
raise ValueError(
"Incorrect value type. Must be one of scalar, vector, and tensor."
)

for k, v in mapping_dict.items():
self.__dict__[k] = np.lib.stride_tricks.as_strided(
block_memory[v],
shape=view_shape,
)

for system_idx, system in enumerate(systems):
self.__dict__[k][..., system_idx : system_idx + 1] = system.__dict__[
k
].copy()
self.__dict__[k][..., system_idx : system_idx + 1] = (
system.__dict__[k]
if value_type == "scalar"
else system.__dict__[k].copy()
)
system.__dict__[k] = np.ndarray.view(
self.__dict__[k][..., system_idx : system_idx + 1]
)
Loading