### Install Full anaStruct with Plotting Source: https://anastruct.readthedocs.io/en/latest/installation.html Install the anaStruct package with all dependencies, including plotting capabilities. Use this command for a complete installation. ```bash python -m pip install anastruct[plot] ``` -------------------------------- ### Example: Rotational Spring or Hinge Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Shows how to apply rotational springs or hinges at element nodes. ```python spring={1: k, 2: k} # Set a hinged node: spring={1: 0} ``` -------------------------------- ### Example: Maximum Plastic Moment Capacity Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Demonstrates how to set a maximum plastic moment capacity for an element at specific nodes. ```python mp={ 1: 210e3, 2: 180e3 } ``` -------------------------------- ### Install anaStruct from GitHub Source: https://anastruct.readthedocs.io/en/latest/installation.html Install the anaStruct package directly from its GitHub repository. This is useful for obtaining the latest development versions or contributing to the project. ```bash pip install git+https://github.com/ritchie46/anaStruct.git ``` -------------------------------- ### Simple Truss Example Source: https://anastruct.readthedocs.io/en/latest/examples.html Demonstrates the creation of a simple truss structure, adding elements, supports, loads, solving, and visualizing results. Requires 'math' for sqrt. ```python 1ss = SystemElements(EA=5000) 2ss.add_truss_element(location=[[0, 0], [0, 5]]) 3ss.add_truss_element(location=[[0, 5], [5, 5]]) 4ss.add_truss_element(location=[[5, 5], [5, 0]]) 5ss.add_truss_element(location=[[0, 0], [5, 5]], EA=5000 * math.sqrt(2)) 6 7ss.add_support_hinged(node_id=1) 8ss.add_support_hinged(node_id=4) 9 10ss.point_load(Fx=10, node_id=2) 11 12ss.solve() 13ss.show_structure() 14ss.show_reaction_force() 15ss.show_axial_force() 16ss.show_displacement(factor=10) ``` -------------------------------- ### Install Python 3.9 on Ubuntu Source: https://anastruct.readthedocs.io/en/latest/installation.html Install a specific version of Python (3.9) on Ubuntu systems using apt-get. This ensures the correct Python version is available if not already installed. ```bash sudo apt-get update sudo apt-get install python3.9 ``` -------------------------------- ### Modeling Structures with Vertex Objects Source: https://anastruct.readthedocs.io/en/latest/vertex.html Use Vertex objects to define points and add elements to a system. This example demonstrates creating vertices, performing arithmetic on them, and adding elements to a SystemElements object. ```python from anastruct import SystemElements, Vertex point_1 = Vertex(0, 0) point_2 = point_1 + [10, 0] point_3 = point_2 + [-5, 5] ss = SystemElements() ss.add_element([point_1, point_2]) ss.add_element(point_3) ss.add_element(point_1) ss.show_structure() ``` -------------------------------- ### Install Headless anaStruct Source: https://anastruct.readthedocs.io/en/latest/installation.html Install the anaStruct package without plotting features. This is useful for environments where plotting is not required or desired. ```bash python -m pip install anastruct ``` -------------------------------- ### Initialize SystemElements Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Initializes a SystemElements object with default or custom stiffness values, plotting size, and load factor. This is the starting point for defining a structural system. ```python def __init__( self, figsize: Tuple[float, float] = (12, 8), EA: float = 15e3, EI: float = 5e3, load_factor: float = 1.0, mesh: int = 50, ): """ * E = Young's modulus * A = Area * I = Moment of Inertia :param figsize: Set the standard plotting size. :param EA: Standard E * A. Set the standard values of EA if none provided when generating an element. :param EI: Standard E * I. Set the standard values of EA if none provided when generating an element. :param load_factor: Multiply all loads with this factor. :param mesh: Plotting mesh. Has no influence on the calculation. """ # init object self.post_processor = post_sl(self) self.plotter = plotter.Plotter(self, mesh) self.plot_values = plotter.PlottingValues(self, mesh) # standard values if none provided self.EA = EA self.EI = EI self.figsize = figsize self.orientation_cs = -1 # needed for the loads directions # structure system self.element_map: Dict[ int, Element ] = {} # maps element ids to the Element objects. self.node_map: Dict[ int, Node # pylint: disable=used-before-assignment ] = {} # maps node ids to the Node objects. self.node_element_map: Dict[ int, List[Element] ] = {} # maps node ids to Element objects # keys matrix index (for both row and columns), values K, are processed # assemble_system_matrix self.system_spring_map: Dict[int, float] = {} # list of indexes that remain after conditions are applied self._remainder_indexes: List[int] = [] # keep track of the nodes of the supports self.supports_fixed: List[Node] = [] self.supports_hinged: List[Node] = [] self.supports_rotational: List[Node] = [] self.internal_hinges: List[Node] = [] self.supports_roll: List[Node] = [] self.supports_spring_x: List[Tuple[Node, bool]] = [] self.supports_spring_z: List[Tuple[Node, bool]] = [] self.supports_spring_y: List[Tuple[Node, bool]] = [] self.supports_roll_direction: List[int] = [] self.inclined_roll: Dict[ int, float ] = {} # map node ids to inclination angle relative to global x-axis. self.supports_roll_rotate: List[bool] = [] # save tuples of the arguments for copying purposes. self.supports_spring_args: List[tuple] = [] # keep track of the loads self.loads_point: Dict[ int, Tuple[float, float] ] = {} # node ids with a point loads {node_id: (x, y)} self.loads_q: Dict[ int, List[Tuple[float, float]] ] = {} # element ids with a q-loadad self.loads_moment: Dict[int, float] = {} self.loads_dead_load: Set[ int ] = set() # element ids with q-load due to dead load # results self.reaction_forces: Dict[int, Node] = {} # node objects self.non_linear = False self.non_linear_elements: Dict[ int, Dict[int, float] ] = ( {} # keys are element ids, values are dicts: {node_index: max moment capacity} ) ``` -------------------------------- ### Install Python on Mac with Homebrew Source: https://anastruct.readthedocs.io/en/latest/installation.html Install Python 3 on macOS using the Homebrew package manager. This is a common method for managing software on Mac. ```bash brew install python ``` -------------------------------- ### Install Specific anaStruct Version Source: https://anastruct.readthedocs.io/en/latest/installation.html Install a specific version of the anaStruct package. Replace '1.4.1' with the desired version number. ```bash python -m pip install anastruct==1.4.1 ``` -------------------------------- ### Check Python Version on Linux Source: https://anastruct.readthedocs.io/en/latest/installation.html Verify the installed Python version on a Linux system. This command is useful to ensure Python 3 is available. ```bash python3 --version ``` -------------------------------- ### Add Structural Elements Source: https://anastruct.readthedocs.io/en/latest/getting_started.html Add elements to your structure by defining their start and end points. The SystemElements object will manage these elements for analysis. ```python ss.add_element(location=[[0, 0], [3, 4]]) ss.add_element(location=[[3, 4], [8, 4]]) ``` -------------------------------- ### Set up a structural model and solve Source: https://anastruct.readthedocs.io/en/latest/post_processing.html This code sets up a basic truss structure, applies loads, and solves for the structural response. It serves as a prerequisite for querying numerical results. ```python from anastruct import SystemElements import matplotlib.pyplot as plt import numpy as np ss = SystemElements() element_type = 'truss' # create triangles x = np.arange(1, 10) * np.pi y = np.cos(x) y -= y.min() ss.add_element_grid(x, y, element_type=element_type) # add top girder ss.add_element_grid(x[1:-1][::2], np.ones(x.shape) * y.max(), element_type=element_type) # add bottom girder ss.add_element_grid(x[::2], np.ones(x.shape) * y.min(), element_type=element_type) # supports ss.add_support_hinged(1) ss.add_support_roll(-1, 2) # loads ss.point_load(node_id=np.arange(2, 9, 2), Fy=-100) ss.solve() ss.show_structure() ``` -------------------------------- ### SystemElements.q_load Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Apply a q-load to an element. ```APIDOC ## SystemElements.q_load ### Description Apply a q-load to an element. ### Parameters #### Path Parameters - **element_id** (Union[int, Sequence[int]]) - Required - representing the element ID - **q** (Union[float, Sequence[float]]) - Required - value of the q-load - **direction** (Union[str, Sequence[str]]) - Optional - “element”, “x”, “y”, “parallel” - **rotation** (Union[float, Sequence[float], None]) - Optional - Rotate the force clockwise. Rotation is in degrees - **q_perp** (Union[float, Sequence[float], None]) - Optional - value of any q-load perpendicular to the indication direction/rotation ``` -------------------------------- ### Apply Loads and Solve Source: https://anastruct.readthedocs.io/en/latest/getting_started.html Apply distributed loads (q-loads) to elements and then solve the structural analysis. The solve() method computes displacements and forces. ```python ss.q_load(element_id=2, q=-10) ss.solve() ``` -------------------------------- ### Retrieve Node Coordinates Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Gets a list of x, y, or z coordinates for all nodes. Can also return (x, y) tuples for 'both'. ```python def nodes_range(self, dimension: str) -> List[Union[float, Tuple[float, float], None]]: """ Retrieve a list with coordinates x or z (y). :param dimension: "both", 'x', 'y' or 'z' """ return list( map( lambda x: x.vertex.x if dimension == "x" else x.vertex.z if dimension == "z" else x.vertex.y if dimension == "y" else (x.vertex.x, x.vertex.y) if dimension == "both" else None, self.node_map.values(), ) ) ``` -------------------------------- ### SystemElements.q_load() Source: https://anastruct.readthedocs.io/en/latest/loads.html Apply a distributed q-load to an element. These loads can act in various directions relative to the element. ```APIDOC ## SystemElements.q_load() ### Description Apply a q-load to an element. ### Method SystemElements.q_load(_q_ , _element_id_ , _direction ='element'_, _rotation =None_, _q_perp =None_) ### Parameters #### Path Parameters - **element_id** (Union[`int`, `Sequence`[`int`]]) - Required - representing the element ID - **q** (Union[`float`, `Sequence`[`float`]]) - Required - value of the q-load - **direction** (Union[`str`, `Sequence`[`str`]]) - Optional - "element", "x", "y", "parallel" - **rotation** (Union[`float`, `Sequence`[`float`], `None`]) - Optional - Rotate the force clockwise. Rotation is in degrees - **q_perp** (Union[`float`, `Sequence`[`float`], `None`]) - Optional - value of any q-load perpendicular to the indication direction/rotation ### Request Example ```python ss.add_element([5, 0]) ss.q_load(q=-1, element_id=ss.id_last_element, direction='element') ss.show_structure() ``` ``` -------------------------------- ### Get Node Coordinates Range Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Retrieves a list of coordinates (x, y, or z) for all nodes. Specify the dimension as 'both', 'x', 'y', or 'z'. ```python SystemElements.nodes_range(_dimension_) ``` -------------------------------- ### SystemElements.get_node_result_range() Source: https://anastruct.readthedocs.io/en/latest/post_processing.html Queries a list of node results, typically used to get a range of values like deflections across multiple nodes. ```APIDOC ## SystemElements.get_node_result_range() ### Description Queries a list with node results, useful for obtaining a range of a specific displacement component across all relevant nodes. ### Method `get_node_result_range(unit)` ### Parameters #### Path Parameters - **unit** (str) - Required - The unit of the result to query (e.g., 'uy' for vertical displacement). ### Response #### Success Response (200) - **List[float]**: Returns a list of float values representing the queried results for each node. ### Request Example ```python deflection = ss.get_node_result_range('uy') print(deflection) plt.plot(deflection) plt.show() ``` ### Response Example ``` [-0.0, -0.8704241688181067, -1.5321803865868588, -1.9886711039126856, -2.129555426623823, -1.9886710728856773, -1.5321805004461058, -0.8704239570876975, -0.0] ``` ``` -------------------------------- ### Initialize SystemElements Object Source: https://anastruct.readthedocs.io/en/latest/getting_started.html Instantiate the main SystemElements object to manage your structural model. This object holds all model states including elements, materials, and forces. ```python from anastruct import SystemElements ss = SystemElements() ``` -------------------------------- ### Initialize LoadCase Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/util/load.html Initializes a LoadCase object with a given name. It prepares a dictionary to store load specifications. ```python lc = LoadCase("my_load_case") ``` -------------------------------- ### SystemElements.moment_load Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Apply a moment on a node. ```APIDOC ## SystemElements.moment_load ### Description Apply a moment on a node. ### Parameters #### Path Parameters - **node_id** (Union[int, Sequence[int]]) - Required - Nodes ID. - **Ty** (Union[float, Sequence[float]]) - Required - Moments acting on the node. ``` -------------------------------- ### Get Node Result Range Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Queries a list of node results for a specified unit. This is useful for analyzing results across multiple nodes. ```python SystemElements.get_node_result_range(_unit_) ``` -------------------------------- ### Add Multiple Elements by Location Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Adds multiple elements defined by their start and end points. Supports various material and section properties. ```python spring={1: 0} ``` ```python last={'EA': 1e3, 'mp': 290} ``` -------------------------------- ### solve Method Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Evaluates the Load Combination on a given structural system. ```APIDOC ## solve ### Description Evaluate the Load Combination. ### Parameters * **system** (`anastruct.fem.system.SystemElements`) - Structure to apply loads on. * **force_linear** (bool) - Force a linear calculation. Even when the system has non linear nodes. * **verbosity** (int) - 0: Log calculation outputs. 1: silence. * **max_iter** (int) - Maximum allowed iterations. * **geometrical_non_linear** (bool) - Calculate second order effects and determine the buckling factor. ### Returns * (ResultObject) - The result of the load combination evaluation. ### Development kwargs: * **naked** (bool) - Whether or not to run the solve function without doing post processing. * **discretize_kwargs** - When doing a geometric non linear analysis you can reduce or increase the number of elements created that are used for determining the buckling_factor. ``` -------------------------------- ### SystemElements.solve Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Compute the results of current model. ```APIDOC ## SystemElements.solve ### Description Compute the results of current model. ### Method SystemElements.solve ### Parameters #### Path Parameters - **force_linear** (bool) - Optional - Force a linear calculation. Even when the system has non linear nodes. - **verbosity** (int) - Optional - 0. Log calculation outputs. 1. silence. - **max_iter** (int) - Optional - Maximum allowed iterations. - **geometrical_non_linear** (int) - Optional - Calculate second order effects and determine the buckling factor. ### Development kwargs - **naked** (bool) - Whether or not to run the solve function without doing post processing. - **discretize_kwargs** (dict) - When doing a geometric non linear analysis you can reduce or increase the number of elements created that are used for determining the buckling_factor ### Returns Displacements vector. ``` -------------------------------- ### Get Element Result Range Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Returns a list of all queried units for elements, useful when many elements are involved. Supported units include 'shear', 'moment', and 'axial'. ```python SystemElements.get_element_result_range(_unit_) ``` -------------------------------- ### Create and Add Frame Girder Elements Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Initializes a SystemElements object and defines a frame girder structure with supports. This sets up the basic model for applying loads. ```python from anastruct import SystemElements from anastruct import LoadCase, LoadCombination import numpy as np ss = SystemElements() height = 10 x = np.cumsum([0, 4, 7, 7, 4]) y = np.zeros(x.shape) x = np.append(x, x[::-1]) y = np.append(y, y + height) ss.add_element_grid(x, y) ss.add_element([[0, 0], [0, height]]) ss.add_element([[4, 0], [4, height]]) ss.add_element([[11, 0], [11, height]]) ss.add_element([[18, 0], [18, height]]) ss.add_support_hinged([1, 5]) ss.show_structure() ``` -------------------------------- ### Query node displacements Source: https://anastruct.readthedocs.io/en/latest/post_processing.html Get the displacement vector (ux, uy, phi_y) for a specific node using get_node_displacements. This method provides detailed nodal movement information. ```python print(ss.get_node_displacements(node_id=5)) ``` -------------------------------- ### SystemElements.solve() Source: https://anastruct.readthedocs.io/en/latest/calculation.html Computes the results of the current model. It supports linear, non-linear, and geometrical non-linear calculations with configurable parameters. ```APIDOC ## SystemElements.solve() ### Description Compute the results of current model. ### Method `SystemElements.solve(_force_linear =False_, _verbosity =0_, _max_iter =200_, _geometrical_non_linear =False_, _** kwargs_) ### Parameters #### Optional Parameters - **force_linear** (bool) - Force a linear calculation. Even when the system has non linear nodes. - **verbosity** (int) - 0. Log calculation outputs. 1. silence. - **max_iter** (int) - Maximum allowed iterations. - **geometrical_non_linear** (bool) - Calculate second order effects and determine the buckling factor. #### Keyword Arguments - **naked** (bool) - Whether or not to run the solve function without doing post processing. - **discretize_kwargs** (dict) - When doing a geometric non linear analysis you can reduce or increase the number of elements created that are used for determining the buckling_factor. ### Returns Displacements vector. ### Example ```python ss.solve(geometrical_non_linear=True, discretize_kwargs=dict(n=20)) ``` ``` -------------------------------- ### System Method Loading Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html This method dynamically loads system methods based on a specification dictionary. It uses `exec` to call methods and requires careful handling of keyword arguments. ```python for method, kwargs in loadcase.spec.items(): method = method.split("-")[0] kwargs = re.sub(r"[{}]", "", str(kwargs)) # pass the groups that match back to the replace kwargs = re.sub(r".??(\w+).?:", r"\1=", kwargs) exec(f"self.{method}({kwargs})") # pylint: disable=exec-used ``` -------------------------------- ### Get Node Result Range (Anastruct FEM) Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Queries a list of node results for displacement (ux, uy) and rotation (phi_y). Note the sign inversion for 'ux' results. ```python if unit == "uy": return [node.uz for node in self.node_map.values()] # - * - = + elif unit == "ux": return [-node.ux for node in self.node_map.values()] elif unit == "phi_y": return [node.phi_y for node in self.node_map.values()] else: raise NotImplementedError ``` -------------------------------- ### Solve Load Combination and Display Results Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Solves the defined load combination using the SystemElements model. It then iterates through the results, displaying the structure, displacements, and titles for each load case and the overall combination. ```python results = combination.solve(ss) for k, ss in results.items(): results[k].show_structure() results[k].show_displacement(show=False) plt.title(k) plt.show() ``` -------------------------------- ### Get Element Results (Anastruct FEM) Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Retrieves detailed results for each element in the system, differentiating between truss and beam elements. Includes options for verbose output to include all result arrays. ```python { "id": el.id, "length": el.l, "alpha": el.angle, "umax": np.max(el.extension), "umin": np.min(el.extension), "u": el.extension if verbose else None, "wmax": np.min(el.deflection), "wmin": np.max(el.deflection), "w": el.deflection if verbose else None, "Mmin": np.min(el.bending_moment), "Mmax": np.max(el.bending_moment), "M": el.bending_moment if verbose else None, "Qmin": np.min(el.shear_force), "Qmax": np.max(el.shear_force), "Q": el.shear_force if verbose else None, "Nmin": np.min(el.axial_force), "Nmax": np.max(el.axial_force), "N": el.axial_force if verbose else None, "q": el.q_load, } else: result_list = [] for el in self.element_map.values(): assert el.extension is not None assert el.axial_force is not None if el.type == "truss": result_list.append( { "id": el.id, "length": el.l, "alpha": el.angle, "umax": np.max(el.extension), "umin": np.min(el.extension), "u": el.extension if verbose else None, "Nmin": np.min(el.axial_force), "Nmax": np.max(el.axial_force), "N": el.axial_force if verbose else None, } ) else: assert el.deflection is not None assert el.shear_force is not None assert el.bending_moment is not None result_list.append( { "id": el.id, "length": el.l, "alpha": el.angle, "umax": np.max(el.extension), "umin": np.min(el.extension), "u": el.extension if verbose else None, "wmax": np.min(el.deflection), "wmin": np.max(el.deflection), "w": el.deflection if verbose else None, "Mmin": np.min(el.bending_moment), "Mmax": np.max(el.bending_moment), "M": el.bending_moment if verbose else None, "Qmin": np.min(el.shear_force), "Qmax": np.max(el.shear_force), "Q": el.shear_force if verbose else None, "Nmin": np.min(el.axial_force), "Nmax": np.max(el.axial_force), "N": el.axial_force if verbose else None, "q": el.q_load, } ) return result_list ``` -------------------------------- ### LoadCombination Methods Source: https://anastruct.readthedocs.io/en/latest/genindex.html Methods for combining different load cases for analysis. ```APIDOC ## add_load_case() ### Description Adds a load case to a load combination. ### Method (Implicitly a method of LoadCombination) ### Parameters (Not specified in source) ### Request Example (Not specified in source) ### Response (Not specified in source) ``` -------------------------------- ### Apply Distributed Load (q-load) using LoadCase Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Applies a distributed load (q) to specified elements within a LoadCase. Supports loads in 'element', 'x', 'y', or 'parallel' directions, with options for rotation and perpendicular loads. ```python q_load(_q_ , _element_id_ , _direction ='element'_, _rotation =None_, _q_perp =None_) Parameters * **element_id** – (int/ list) representing the element ID * **q** – (flt) value of the q-load * **direction** – (str) “element”, “x”, “y”, “parallel” ``` -------------------------------- ### Get Element Result Range (Anastruct FEM) Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Retrieves a list of specific result values (shear, moment, or axial force) from all elements in the system. Useful for analyzing the range of a particular force type across the structure. ```python if unit == "shear": return [el.shear_force[0] for el in self.element_map.values()] # type: ignore elif unit == "moment": return [el.bending_moment[0] for el in self.element_map.values()] # type: ignore elif unit == "axial": return [el.axial_force[0] for el in self.element_map.values()] # type: ignore else: raise NotImplementedError ``` -------------------------------- ### Define and Combine Load Cases Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Resets the system loads, creates a new LoadCase for 'cables' with point loads, and then initializes a LoadCombination object ('ULS') to which the 'wind' and 'cables' load cases are added with specified factors. ```python # reset the structure ss.remove_loads() # create another load case lc_cables = LoadCase('cables') lc_cables.point_load(node_id=[2, 3, 4], Fy=-100) combination = LoadCombination('ULS') combination.add_load_case(lc_wind, 1.5) combination.add_load_case(lc_cables, factor=1.2) ``` -------------------------------- ### Get Node Displacements Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Retrieves displacement results for a specific node or all nodes. When node_id is 0, it returns a list of tuples containing ID, displacements (ux, uy), and rotation (phi_y). For a specific node_id, it returns a dictionary. ```python SystemElements.get_node_displacements(_node_id =0_) ``` -------------------------------- ### Complex Tower Structure with Loads and Visualization Source: https://anastruct.readthedocs.io/en/latest/examples.html Builds a more complex structure resembling towers using element grids and applies various loads, including wind loads. Solves and visualizes displacements and bending moments. Requires 'numpy'. ```python 1from anastruct import SystemElements 2import numpy as np 3 4ss = SystemElements() 5element_type = 'truss' 6 7# Create 2 towers 8width = 6 9span = 30 10k = 5e3 11 12# create triangles 13y = np.arange(1, 10) * np.pi 14x = np.cos(y) * width * 0.5 15x -= x.min() 16 17for length in [0, span]: 18 x_left_column = np.ones(y[::2].shape) * x.min() + length 19 x_right_column = np.ones(y[::2].shape[0] + 1) * x.max() + length 20 21 # add triangles 22 ss.add_element_grid(x + length, y, element_type=element_type) 23 # add vertical elements 24 ss.add_element_grid(x_left_column, y[::2], element_type=element_type) 25 ss.add_element_grid(x_right_column, np.r_[y[0], y[1::2], y[-1]], element_type=element_type) 26 27 ss.add_support_spring( 28 node_id=ss.find_node_id(vertex=[x_left_column[0], y[0]]), 29 translation=2, 30 k=k) 31 ss.add_support_spring( 32 node_id=ss.find_node_id(vertex=[x_right_column[0], y[0]]), 33 translation=2, 34 k=k) 35 36# add top girder 37ss.add_element_grid([0, width, span, span + width], np.ones(4) * y.max(), EI=10e3) 38 39# Add stability elements at the bottom. 40ss.add_truss_element([[0, y.min()], [width, y.min()]]) 41ss.add_truss_element([[span, y.min()], [span + width, y.min()]]) 42 43for el in ss.element_map.values(): 44 # apply wind load on elements that are vertical 45 if np.isclose(np.sin(el.angle), 1): 46 ss.q_load( 47 q=1, 48 element_id=el.id, 49 direction='x' 50 ) 51 52ss.show_structure() 53ss.solve() 54ss.show_displacement(factor=2) 55ss.show_bending_moment() ``` -------------------------------- ### Get Node Results Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Retrieves numerical results for a specific node or all nodes. When node_id is 0, it returns a list of tuples containing ID, forces (Fx, Fy), displacements (ux, uy), and rotation (phi_y). For a specific node_id, it returns a dictionary. ```python SystemElements.get_node_results_system(_node_id =0_) ``` -------------------------------- ### Get Element Results Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Retrieves numerical results for a specific element or all elements. If verbose is True, it includes deflection and bending moments. When element_id is 0, it returns a list of tuples containing ID, length, angle (alpha), displacement (u), and axial forces (N_1, N_2). For a specific element_id, it returns a dictionary. ```python SystemElements.get_element_results(_element_id =0_, _verbose =False_) ``` -------------------------------- ### SystemElements.show_structure Source: https://anastruct.readthedocs.io/en/latest/plotting.html Plots the structure of the system. It allows for customization of scale, offset, figure size, and verbosity. Annotations can also be plotted if verbosity is 0. ```APIDOC ## SystemElements.show_structure ### Description Plot the structure. ### Parameters - **verbosity** (int) - Optional - 0: All information, 1: Suppress information. - **scale** (float) - Optional - Scale of the plot. - **offset** (Tuple[float, float]) - Optional - Offset the plots location on the figure. - **figsize** (Optional[Tuple[float, float]]) - Optional - Change the figure size. - **show** (bool) - Optional - Plot the result or return a figure. - **supports** (bool) - Optional - Whether to plot supports. - **values_only** (bool) - Optional - Return the values that would be plotted as tuple containing two arrays: (x, y). - **annotations** (bool) - Optional - if True, structure annotations are plotted. It includes section name. Note: only works when verbosity is equal to 0. ``` -------------------------------- ### SystemElements.get_node_results_system() Source: https://anastruct.readthedocs.io/en/latest/post_processing.html Retrieves the system results for nodes, which include reaction forces and moments at supports. It can return results for all nodes or a specific node. ```APIDOC ## SystemElements.get_node_results_system() ### Description Retrieves the system results for nodes, including reaction forces and moments. If `node_id` is 0, results for all nodes are returned. Otherwise, results for the specified node are returned. ### Method `get_node_results_system(node_id=0)` ### Parameters #### Path Parameters - **node_id** (int) - Required - The ID of the node for which to retrieve results. Use 0 to get results for all nodes. ### Response #### Success Response (200) - **List[Tuple[Any, Any, Any, Any, Any, Any, Any]]**: If `node_id` is 0, returns a list of tuples, where each tuple contains (id, Fx, Fy, Ty, ux, uy, phi_y). - **Dict[str, Union[int, float]]**: If `node_id` > 0, returns a dictionary with the results for the specified node. ### Request Example ```python # Get reaction forces for node 1 and node -1 print(ss.get_node_results_system(node_id=1)['Fy'], ss.get_node_results_system(node_id=-1)['Fy']) ``` ### Response Example ``` 199.9999963370603 200.00000366293816 ``` ``` -------------------------------- ### Query node reaction forces Source: https://anastruct.readthedocs.io/en/latest/post_processing.html Retrieve the reaction forces (Fy) at specific support nodes using the get_node_results_system method. This is useful for verifying equilibrium. ```python print(ss.get_node_results_system(node_id=1)['Fy'], ss.get_node_results_system(node_id=-1)['Fy']) ``` -------------------------------- ### Apply Moment Load using LoadCase Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Applies a moment load (Ty) to specified nodes within a LoadCase. Can apply to single or multiple nodes with corresponding moment values. ```python moment_load(_node_id_ , _Ty_) Parameters * **node_id** – (int/ list) Nodes ID. * **Ty** – (flt/ list) Moments acting on the node. ``` -------------------------------- ### Define and Apply Wind Load Case Source: https://anastruct.readthedocs.io/en/latest/loadcases.html Creates a LoadCase object named 'wind' and applies a distributed load (q_load) to specified elements. The load case is then applied to the SystemElements object. ```python lc_wind = LoadCase('wind') lc_wind.q_load(q=-1, element_id=[10, 11, 12, 13, 5]) print(lc_wind) ``` ```python # add the load case to the SystemElements object ss.apply_load_case(lc_wind) ss.show_structure() ``` -------------------------------- ### Apply Q-Load to Element Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/system.html Applies a distributed load (q-load) to an element. Supports loads in 'x', 'y', 'parallel' directions, or at a specified 'rotation'. 'q_perp' can be used for perpendicular loads. ```python def q_load( self, q: Union[float, Sequence[float]], element_id: Union[int, Sequence[int]], direction: Union[str, Sequence[str]] = "element", rotation: Optional[Union[float, Sequence[float]]] = None, q_perp: Union[float, Sequence[float]] = None, ): """ Apply a q-load to an element. :param element_id: representing the element ID :param q: value of the q-load :param direction: "element", "x", "y", "parallel" :param rotation: Rotate the force clockwise. Rotation is in degrees :param q_perp: value of any q-load perpendicular to the indication direction/rotation """ # TODO! this function is a duck typing hell. redesign. if q_perp is None: q_perp = [0, 0] if not isinstance(q, Sequence): q = [q, q] if not isinstance(q_perp, Sequence): q_perp = [q_perp, q_perp] q = [q] # type: ignore q_perp = [q_perp] # type: ignore if rotation is None: direction_flag = True else: direction_flag = False ( # pylint: disable=unbalanced-tuple-unpacking q, element_id, direction, rotation, q_perp, ) = args_to_lists(q, element_id, direction, rotation, q_perp) assert len(q) == len(element_id) # type: ignore assert len(q) == len(direction) # type: ignore assert len(q) == len(rotation) # type: ignore assert len(q) == len(q_perp) # type: ignore for i, element_idi in enumerate(element_id): # type: ignore id_ = _negative_index_to_id(element_idi, self.element_map.keys()) # type: ignore self.plotter.max_q = max( self.plotter.max_q, (q[i][0] ** 2 + q_perp[i][0] ** 2) ** 0.5, # type: ignore (q[i][1] ** 2 + q_perp[i][1] ** 2) ** 0.5, # type: ignore ) if direction_flag: if direction[i] == "x": rotation[i] = 0 # type: ignore elif direction[i] == "y": rotation[i] = np.pi / 2 # type: ignore elif direction[i] == "parallel": rotation[i] = self.element_map[element_id[i]].angle # type: ignore else: rotation[i] = np.pi / 2 + self.element_map[element_id[i]].angle # type: ignore else: rotation[i] = math.radians(rotation[i]) # type: ignore direction[i] = "angle" # type: ignore cos = math.cos(rotation[i]) # type: ignore sin = math.sin(rotation[i]) # type: ignore self.loads_q[id_] = [ ( (q_perp[i][0] * cos + q[i][0] * sin) * self.load_factor, # type: ignore ``` -------------------------------- ### SystemElements.point_load Source: https://anastruct.readthedocs.io/en/latest/modelling_methods.html Apply a point load to a node. ```APIDOC ## SystemElements.point_load ### Description Apply a point load to a node. ### Parameters #### Path Parameters - **node_id** (Union[int, Sequence[int]]) - Required - Nodes ID. - **Fx** (Union[float, Sequence[float]]) - Optional - Force in global x direction. - **Fy** (Union[float, Sequence[float]]) - Optional - Force in global x direction. - **rotation** (Union[float, Sequence[float]]) - Optional - Rotate the force clockwise. Rotation is in degrees. ``` -------------------------------- ### LoadCombination Class Source: https://anastruct.readthedocs.io/en/latest/_modules/anastruct/fem/util/load.html Manages combinations of different load cases with specified factors. ```APIDOC ## LoadCombination Class ### Description Manages combinations of different load cases with specified factors. ### Methods #### __init__(self, name) - **name** (str) - Name of the load combination. #### add_load_case(self, lc, factor) Add a load case to the load combination. - **lc** (:class:`anastruct.fem.util.LoadCase`) - The load case to add. - **factor** (flt) - Multiply all the loads in this LoadCase with this factor. #### solve(self, system, force_linear=False, verbosity=0, max_iter=200, geometrical_non_linear=False, **kwargs) Evaluate the Load Combination. - **system** (:class:`anastruct.fem.system.SystemElements`) - Structure to apply loads on. - **force_linear** (bool) - Force a linear calculation. Even when the system has non linear nodes. - **verbosity** (int) - 0: Log calculation outputs. 1: silence. - **max_iter** (int) - Maximum allowed iterations. - **geometrical_non_linear** (bool) - Calculate second order effects and determine the buckling factor. - **kwargs** - Additional keyword arguments. - **naked** (bool) - Whether or not to run the solve function without doing post processing. - **discretize_kwargs** - When doing a geometric non linear analysis you can reduce or increase the number of elements created that are used for determining the buckling_factor. ### Returns - (ResultObject) - The result of the load combination analysis. ```