Tutorial
How to use CRA for your analysis
1. Creating geometries
We create two blocks: one as support and another one as free block.
from compas.geometry import Box, Frame, Translation
support = Box(Frame.worldXY(), 4, 2, 1) # supporting block
free1 = Box(
Frame.worldXY().transformed(
Translation.from_vector([0, 0, 1])
* Rotation.from_axis_and_angle([0, 0, 1], 0.2)
), 1, 3, 1
) # block to analyse
2. CRA Assembly data structure
Add them to assembly data structure.
from compas_assembly.datastructures import Block
from compas_cra.datastructures import CRA_Assembly
assembly = CRA_Assembly()
assembly.add_block(Block.from_shape(support), node=0)
assembly.add_block(Block.from_shape(free1), node=1)
3. Boundary conditions
Set boundary conditions.
assembly.set_boundary_conditions([0])
4. Identifying interfaces
Then we identify planar interfaces between blocks automatically.
from compas_cra.algorithms import assembly_interfaces_numpy
assembly_interfaces_numpy(assembly)
5. Solving equilibrium
compas_cra
provides three solvers:
RBE Solve:
compas_cra.equilibrium.rbe_solve
.CRA Solve:
compas_cra.equilibrium.cra_solve
.CRA Penalty Solve:
compas_cra.equilibrium.cra_penalty_solve
.
from compas_cra.equilibrium import cra_solve
cra_solve(assembly, verbose=True, timer=True)
6. Visualisation
from compas_cra.viewers import cra_view
cra_view(assembly, resultant=False, nodal=True, grid=True)
The complete tutorial script can be downloaded from scripts/tutorial_cubes.py
To reproduce our paper’s examples or to see more how to construct assembly and solve equilibrium, please check Examples.
Optional: Export geometry from CAD software (Rhino)
For the step 1. Creating geometries, we can also input geometry from CAD software. Here we use Rhino as an example.
Export mesh blocks as Assembly json file
Use this script at scripts/mesh_to_assembly_json.py
to select Rhino mesh blocks and export to assembly data structure as a .json
file.
"""This is the script to add assembly without interfaces from rhino meshes"""
import os
import compas
import rhinoscriptsyntax as rs
from compas_rhino import select_meshes
from compas_cra.datastructures import CRA_Assembly
HERE = os.path.abspath(os.path.dirname(__file__))
PATH = os.path.abspath(
os.path.join(HERE, "..", "data")
) # or change to your own directory
guid = select_meshes()
assembly = CRA_Assembly()
assembly.add_blocks_from_rhinomeshes(guid)
filename = rs.GetString("file name (xxx.json):")
file_o = os.path.join(PATH, filename)
compas.json_dump(assembly, file_o)
print("file save to: ", file_o)
Note: The selection sequence is important because it represents the node indices.
Then we can load the .json
file from local path.
import os
import compas
import compas_cra
from compas_cra.datastructures import CRA_Assembly
FILE_I = os.path.join(compas_cra.DATA, "XXX.json") # or your own path
assembly = compas.json_load(FILE_I)
assembly = assembly.copy(cls=CRA_Assembly)
After loading the .json
file and convert it to compas_cra.datastructures.CRA_Assembly
,
we can follow the previous step 3. Boundary conditions for the analysis.
Export mesh blocks and interfaces as Assembly json file
Currently, we do not implement automatic interface detection algorithm for blocks with curve/free-form interfaces, so they have to be discretised manually as planar faces or triangles.
Use this script at scripts/mesh_to_assembly_interfaces_json.py to select mesh blocks with interfaces and export to assembly data structure and store it as json file.
"""This is the script to add assembly and interfaces from rhino meshes"""
import os
import compas
import rhinoscriptsyntax as rs
from compas_rhino.geometry import RhinoMesh
from compas_cra.datastructures import CRA_Assembly
HERE = os.path.abspath(os.path.dirname(__file__))
PATH = os.path.abspath(
os.path.join(HERE, "..", "data")
) # or change to your own directory
guid = rs.GetObjects(
"select blocks",
preselect=False,
select=False,
group=False,
filter=rs.filter.mesh,
)
assembly = CRA_Assembly()
assembly.add_blocks_from_rhinomeshes(guids=guid)
node_labels = []
for node in assembly.nodes():
block = assembly.graph.node_attribute(node, "block")
c = block.centroid()
node_labels.append(rs.AddTextDot(node, c))
IS_FINISHED = False
while not IS_FINISHED:
interface_guids = rs.GetObjects(
"select interfaces",
preselect=False,
select=False,
group=False,
filter=rs.filter.mesh,
)
interfaces = []
for interface_guid in interface_guids:
mesh = RhinoMesh.from_guid(interface_guid)
interfaces.append(mesh.to_compas())
edge_a = rs.GetInteger("assign interface from")
edge_b = rs.GetInteger("assign interface to")
assembly.add_interfaces_from_meshes(interfaces, edge_a, edge_b)
IS_FINISHED = rs.GetBoolean(
"Continue select interface?", ("Continue", "Continue", "Stop"), (False)
)[0]
rs.DeleteObjects(node_labels)
filename = rs.GetString("file name (xxx.json):")
file_o = os.path.join(PATH, filename)
compas.json_dump(assembly, file_o)
print("file save to: ", file_o)
Note:
The selection sequence is important because it represents the node indices.
The interface normal directions are important, it must point from assign interface from to assign interface to. For example, in Figure 1, assign interface from: 1 and assign interface to: 0 for the interface from 1 to 0.
More Rhino files and precomputed .json
files are located at data folder.
Note:
Every time a new file is opened in Rhino, be sure to restart Rhino or reset the Python Script Engine before running scripts.