Source code for layout
import itertools
import jax.numpy as jnp
import numpy as np
import pandas as pd
from numpy.typing import NDArray
from moveable_morphable_components import components
[docs]
def grid_of_uniform_beams(
n_x: int, n_y: int, dimensions: tuple[float, float], thickness: float
) -> jnp.ndarray:
"""Initialises a grid of crossed Uniform Beams in the domain
Parameters:
n_x: int - The number of component pairs (crosses) in the x direction
n_y: int - The number of component pairs (crosses) in the y direction
dimensions: tuple[float, float] - The dimensions to fill with the grid
thickness: float - The thickness of the beam components
Returns:
list[Component] - The list of components
"""
# Work out the size of the regions each crossed pair will occupy
region_size: NDArray = dimensions / (n_x, n_y)
# Generate the center coordinates of regions
x_coords: NDArray = np.linspace(
region_size[0] / 2, dimensions[0] - region_size[0] / 2, n_x
)
y_coords: NDArray = np.linspace(
region_size[1] / 2, dimensions[1] - region_size[1] / 2, n_y
)
# Angle and length to put the components across the region diagonals
angle: float = np.arctan2(region_size[1], region_size[0])
length: float = np.linalg.norm(region_size)
design_variables: list[list[float]] = []
for y, x in itertools.product(y_coords, x_coords):
for sign in [-1, 1]:
design_variables.append([x, y, sign * angle, length, thickness])
return jnp.array(design_variables)
[docs]
def grid_of_uniform_beams_of_fixed_thickness(
n_x: int, n_y: int, dimensions: tuple[float, float], thickness: list[float] | float
) -> jnp.ndarray:
"""Initialises a grid of crossed Uniform Beams in the domain
Parameters:
n_x: int - The number of component pairs (crosses) in the x direction
n_y: int - The number of component pairs (crosses) in the y direction
dimensions: tuple[float, float] - The dimensions to fill with the grid
thickness: float - The thickness of the beam components
Returns:
list[Component] - The list of components
"""
if isinstance(thickness, float):
thickness = [thickness] * n_x * n_y * 2
assert (
len(thickness) == n_x * n_y * 2
), "thickness must be the correct length (nx * ny * 2)"
# Work out the size of the regions each crossed pair will occupy
region_size: NDArray = dimensions / (n_x, n_y)
# Generate the center coordinates of regions
x_coords: NDArray = np.linspace(
region_size[0] / 2, dimensions[0] - region_size[0] / 2, n_x
)
y_coords: NDArray = np.linspace(
region_size[1] / 2, dimensions[1] - region_size[1] / 2, n_y
)
# Angle and length to put the components across the region diagonals
angle: float = np.arctan2(region_size[1], region_size[0])
length: float = np.linalg.norm(region_size)
component_list: list[components.Component] = []
i = 0
for y, x in itertools.product(y_coords, x_coords):
for sign in [-1, 1]:
component_list.append(
components.UniformBeamFixedThickness(
center=components.Point2D(x, y),
angle=sign * angle,
length=length,
thickness=thickness[i],
)
)
i += 1
return component_list
[docs]
def random_beams(
min: NDArray,
max: NDArray,
n: int,
np_random: np.random.Generator | None,
) -> jnp.ndarray:
component_list = []
if np_random is None:
np_random = np.random.default_rng()
design_vars = np.random.uniform(low=min, high=max, size=(n, 5))
for i in range(n):
x, y, angle, length, thickness = design_vars[i]
component_list.append(
components.UniformBeam(
center=components.Point2D(x, y),
angle=angle,
length=length,
thickness=thickness,
)
)
return component_list
[docs]
def fixed_thickness_beam_from_df(df: pd.DataFrame) -> jnp.ndarray:
component_list = []
for i, row in df.iterrows():
component_list.append(
components.UniformBeamFixedThickness(
center=components.Point2D(row.x, row.y),
angle=row.angle,
length=row.length,
thickness=row.width,
)
)
return component_list