def square_lattice(): """a simple square with one diagonal""" nodes_positions = np.array([ [1, 1], [-1, 1], [-1, -1], [1, -1] ]).astype(float) edges_indices = np.array([ [0, 1], [1, 2], [0, 2], [2, 3], [3, 0] ]).astype(int) # create lattice lattice = Lattice( nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=1, angular_stiffness=1 ) # activate all edges for edge in lattice._possible_edges: lattice.flip_edge(edge) return lattice
def test_lattice_remove_edge(lattice: Lattice): """test that we can remove edges""" for edge in lattice._possible_edges: lattice._add_edge(edge) for edge in lattice._possible_edges: lattice._remove_edge(edge) assert edge not in lattice.edges
def render(self, save_path="image.png"): dir_name = os.path.dirname(save_path) if not os.path.exists(dir_name): os.makedirs(dir_name) nodes_pos, edges_indices, edges_thickness, _ = self.extract_node_edge_info() lattice = Lattice( nodes_positions=nodes_pos, edges_indices=edges_indices, edges_thickness=edges_thickness, linear_stiffness=LINEAR_STIFFNESS, angular_stiffness=ANGULAR_STIFFNESS ) for edge in lattice._possible_edges: lattice.flip_edge(edge) actuator = Actuator( lattice=lattice, input_nodes=self.input_nodes, input_vectors=self.input_vectors, output_nodes=self.output_nodes, output_vectors=self.output_vectors, frozen_nodes=self.frozen_nodes ) show_actuator(actuator, save_path=save_path)
def _load_crane_displacement(solver_tol=1e-5) -> Actuator: input_lammps_file = Path(__file__).parent / \ "data/crane/crane_initial_config.lammps" params = read_lammps(input_lammps_file) nodes_postions = params["nodes_positions"] edges_indices = params["edges_indices"] input_nodes = params["input_nodes"] output_nodes = params["output_nodes"] frozen_nodes = params["frozen_nodes"] lattice = Lattice( nodes_positions=nodes_postions, edges_indices=edges_indices, linear_stiffness=10, angular_stiffness=0.2, ) for edge in lattice._possible_edges: lattice.flip_edge(edge) # input and output vectors input_vectors = np.array([[0, -np.sqrt(3) / 4] for _ in input_nodes]) output_vectors = np.array([[-1, 0] for _ in output_nodes]) actuator = Actuator(lattice=lattice, input_nodes=input_nodes, output_nodes=output_nodes, frozen_nodes=frozen_nodes, input_vectors=input_vectors, output_vectors=output_vectors, max_force=solver_tol, method="displacement") return actuator
def test_lattice_flip_edge(lattice: Lattice): """test that we can flip edges Flipping an edge means adding it if it is not present and removing it if it is present """ for edge in lattice.edges: lattice.flip_edge(edge) assert edge in lattice.edges for edge in lattice.edges: lattice.flip_edge(edge) assert edge not in lattice.edges
def lattice() -> Lattice: """fixture to create a simple dummy square""" nodes_positions = np.array([ [1, 1], [-1, 1], [-1, -1], [1, -1], ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1) return lattice
def test_lattice_fails_wrong_z(): """make sure we raise an error when passing wrong z coordinates""" nodes_positions = np.array([ [1, 1, 0], [-1, 1, 0], [-1, -1, 0], [1, -1, .2], # z is not constant ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) with pytest.raises(NotImplementedError): lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1)
def test_lattice_fails_wrong_dimension_nodes(): """make sure we raise an error when passing nodes with wrong number of dimensions""" nodes_positions = np.array([ [0, 0, 0, 1, 1], [0, 0, 0, -1, 1], [0, 0, 0, -1, -1], [0, 0, 0, 1, -1], ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) with pytest.raises(RuntimeError): lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1)
def test_lattice_fails_nonunique_nodes(): """make sure we raise an error when passing nonunique nodes""" nodes_positions = np.array([ [1, 1], [1, 1], # repeated node here [-1, -1], [1, -1], ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) with pytest.raises(RuntimeError): lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1)
def calculate_simulation(self): nodes_pos, edges_indices, edges_thickness, _ = self.extract_node_edge_info() lattice = Lattice( nodes_positions=nodes_pos, edges_indices=edges_indices, edges_thickness=MAX_EDGE_THICKNESS * edges_thickness, linear_stiffness=LINEAR_STIFFNESS, angular_stiffness=ANGULAR_STIFFNESS ) for edge in lattice._possible_edges: lattice.flip_edge(edge) actuator = Actuator( lattice=lattice, input_nodes=self.input_nodes, input_vectors=self.input_vectors, output_nodes=self.output_nodes, output_vectors=self.output_vectors, frozen_nodes=self.frozen_nodes ) return actuator.efficiency
def _load_crane_force(solver_tol=1e-5) -> Actuator: path_to_initial_config = Path(__file__).parent / \ "data/crane/crane_initial_config.lammps" params = read_lammps(path_to_initial_config) nodes_postions = params["nodes_positions"] edges_indices = params["edges_indices"] input_nodes = params["input_nodes"] output_nodes = params["output_nodes"] frozen_nodes = params["frozen_nodes"] lattice = Lattice( nodes_positions=nodes_postions, edges_indices=edges_indices, linear_stiffness=10, angular_stiffness=0.2, ) for edge in lattice._possible_edges: lattice.flip_edge(edge) # input and output vectors input_vectors = np.array([[0, -0.0015] for _ in input_nodes]) output_vectors = np.array([[2, 0] for _ in output_nodes]) actuator = Actuator(lattice=lattice, input_nodes=input_nodes, output_nodes=output_nodes, frozen_nodes=frozen_nodes, input_vectors=input_vectors, output_vectors=output_vectors, max_force=solver_tol, method="force", output_spring_stiffness=0.001, efficiency_agg_fun=np.sum) return actuator
def test_lattice__generate_possible_edges(lattice: Lattice): """test that edges are added correctly at init""" nodes_positions = np.array([ [1, 1], [-1, 1], [-1, -1], [1, -1], ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1) for edge, (i, j) in zip(lattice.edges, edges_indices): u, v = edge._nodes assert i == u.label assert j == v.label
def test_lattice__add_nodes(): """make sure nodes are correctly added at init""" nodes_positions = np.array([ [1, 1], [-1, 1], [-1, -1], [1, -1], ]) edges_indices = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1) assert len(lattice.nodes) == len(nodes_positions) for node, (x, y) in zip(lattice.nodes, nodes_positions): assert x == node.x assert y == node.y
def test_lattice_fails_edges_not_in_range_down(): """make sure we raise an error when trying to instantiate with negative indices""" nodes_positions = np.array([ [1, 1], [-1, 1], [-1, -1], [1, -1], ]) edges_indices = np.array([ [0, 1], [1, 2], [2, -5], # wrong index here [3, 0], [0, 2] ]) with pytest.raises(RuntimeError): lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=0.1, angular_stiffness=0.1)
def test_lattice_add_edge(lattice: Lattice): """test that we can add edges""" for edge in lattice._possible_edges: lattice._add_edge(edge) assert edge in lattice.edges
def square_lattice_to_relax(request): """ Provide a square with its top-right vertex perturbed from its resting position. """ # create lattice nodes_positions = np.array([[1, 1], [-1, 1], [-1, -1], [1, -1]]).astype(float) edges_indices = np.array([[0, 1], [1, 2], [0, 2], [2, 3], [3, 0]]).astype(int) lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, linear_stiffness=request.param[2], angular_stiffness=request.param[3]) # activate all edges for edge in lattice._possible_edges: lattice.flip_edge(edge) ## # parameters for relax ## num_nodes = 4 frozen = np.array([0, 1, 1, 1]).astype(np.intc) # input target_in = np.array([1]).astype(np.intc) Xin = np.array([0.]) Yin = np.array([0.]) Zin = np.array([0.]) Nin = np.intc(1) # output target_out = np.array([1]).astype(np.intc) Xout = np.array([1.]) Yout = np.array([1.]) Zout = np.array([0.]) kout = 1. Nout = np.intc(1) # other epot = np.array([0]) fmax = np.array([1e-5]) method = np.intc(0) enforce2D = np.intc(1) error = np.array([0]).astype(np.intc) step_relax = np.array([10000]).astype(np.intc) # parameters that depend on the lattice params_internal = _get_params_from_lattice(lattice) # parameters that depend on the actuator params_external = { "frozen": frozen, "target_in": target_in, "Xin": Xin, "Yin": Yin, "Zin": Zin, "Nin": Nin, "target_out": target_out, "Xout": Xout, "Yout": Yout, "Zout": Zout, "Nout": Nout, "kout": kout, "epot": epot, "fmax": fmax, "method": method, "enforce2D": enforce2D, "error": error, "step_relax": step_relax } # all params params = {**params_internal, **params_external} # displace the top-right node params["X"][0] = request.param[0] params["Y"][0] = request.param[1] return params
[79, 81], [80, 81], [80, 82], [81, 83], [81, 82], [82, 83], [82, 84], [83, 84], ]) edges_thickness = np.ones(len(edges_indices)) # construct the lattice lattice = Lattice(nodes_positions=nodes_positions, edges_indices=edges_indices, edges_thickness=edges_thickness, linear_stiffness=10, angular_stiffness=0.2) # 最初に全ての接続可能なエッジすべてにエッジを存在させる for edge in lattice._possible_edges: lattice.flip_edge(edge) # input displacement is 0.1 units in -y direction # applied to top-right nodes input_nodes = [81, 82, 83, 84] input_vectors = np.array([[0., -0.1], [0., -0.1], [0., -0.1], [0., -0.1]]) # measure output at top-left nodes along -x direction output_nodes = [68, 69, 70, 71] output_vectors = np.array([
def load_crane_scaling( size: int = 8, displacement_fraction: float = 0.01, solver_tol: float = 1e-5, ) -> Actuator: """ Load crane actuator for scaling analysis. Offers a set of initial configs on a regular lattice of increasing size and preconfigured input/output vectors, suitable for scaling analysis. Parameters ---------- size : int, optional Number of nodes of side of lattice, by default 8 solver_tol : float, optional Tolerance (max force) in FIRE algorithm, by default 1e-5 displacement_fraction : float, optional Set input displacement to a fixed fraction of the length of the lattice in the y direction, by default 0.01. Returns ------- : Actuator Preconfigured crane actuator. """ # make sure size is available if size not in AVAILABLE_CRANE_SIZES: raise RuntimeError( f"Size {size} is not available. Available sizes are", AVAILABLE_CRANE_SIZES) path_to_initial_config = Path(__file__).parent / \ f"data/crane_scaling/conf{size}.data" params = read_lammps(path_to_initial_config) nodes_postions = params["nodes_positions"] edges_indices = params["edges_indices"] # define input, output and frozen nodes xs, ys, _ = nodes_postions.T frozen_nodes = [ i for i, y in enumerate(ys) if y == min(ys) ] input_nodes = [ i for i, (x, y) in enumerate(zip(xs, ys)) if (x > min(xs) + 0.8 * (max(xs) - min(xs))) and (y > min(ys) + 0.8 * (max(ys) - min(ys))) ] output_nodes = [ i for i, (x, y) in enumerate(zip(xs, ys)) if (x < min(xs) + 0.2 * (max(xs) - min(xs))) and (y > min(ys) + 0.8 * (max(ys) - min(ys))) ] # input and output vectors # displacement is 1% of y range input_vectors = np.array([ [0, -displacement_fraction * (max(ys) - min(ys))] for _ in input_nodes ]) output_vectors = np.array([ [-1, 0] for _ in output_nodes ]) lattice = Lattice( nodes_positions=nodes_postions, edges_indices=edges_indices, linear_stiffness=10, angular_stiffness=0.2, ) for edge in lattice._possible_edges: lattice.flip_edge(edge) actuator = Actuator( lattice=lattice, input_nodes=input_nodes, output_nodes=output_nodes, frozen_nodes=frozen_nodes, input_vectors=input_vectors, output_vectors=output_vectors, max_force=solver_tol, method="displacement", ) return actuator