Source code for mento.node
from typing import Union, Optional, List
import pandas as pd
from mento.section import Section
from mento.forces import Forces
[docs]
class Node:
"""
Node Class
The `Node` class represents a structural node that is associated with a section
(e.g., a beam) and can have forces applied to it. It provides methods for managing
forces, performing structural checks, and designing for flexure and shear.
Attributes:
section (Section): The section (e.g., beam) associated with the node.
forces (List[Forces]): A list of forces applied to the node.
Methods:
add_forces(forces: Union[Forces, List[Forces]]) -> None:
Adds one or more forces to the node.
get_forces_list() -> List[Forces]:
Returns the list of forces applied to this node.
clear_forces() -> None:
Removes all forces from the node.
check_flexure() -> pd.DataFrame:
Performs a flexural check on the section using the applied forces.
design_flexure() -> pd.DataFrame:
Designs the section for flexure based on the applied forces.
check_shear() -> pd.DataFrame:
Performs a shear check on the section using the applied forces.
design_shear() -> pd.DataFrame:
Designs the section for shear based on the applied forces.
shear_results_detailed(force: Optional[Forces] = None) -> None:
Provides detailed shear results for a specific force or all forces.
shear_results_detailed_doc(force: Optional[Forces] = None) -> None:
Provides detailed shear results documentation for a specific force or all forces.
flexure_results_detailed(force: Optional[Forces] = None) -> None:
Provides detailed flexure results for a specific force or all forces.
flexure_results_detailed_doc(force: Optional[Forces] = None) -> None:
Provides detailed flexure results documentation for a specific force or all forces.
results -> None:
A property that provides beam results for Jupyter Notebook.
id -> int:
A read-only property to access the private `_id` of the node.
"""
_id: int
_last_id: int = 0 # Class variable to keep track of last assigned ID
def __init__(self, section: Section, forces: Union[Forces, List[Forces]]) -> None:
# Initialize the private ID automatically
Node._last_id += 1 # Increment the class variable for the next ID
self._id = Node._last_id # Assign the next available ID
if not isinstance(section, Section):
raise TypeError("section must be an instance of Section")
# Ensure forces is either a single Forces object or a list of Forces
if isinstance(forces, Forces):
self.forces = [forces] # Wrap single Forces object in a list
elif isinstance(forces, list) and all(isinstance(force, Forces) for force in forces):
self.forces = forces # Assign the list directly if valid
else:
raise TypeError("forces must be an instance of Forces or a list of Forces")
self.section = section
# Set the node reference in the section (beam)
self.section.node = self # Associate the Node with the RectangularBeam
[docs]
def add_forces(self, forces: Union[Forces, List[Forces]]) -> None:
if isinstance(forces, Forces):
self.forces.append(forces) # Append single Forces object
elif isinstance(forces, list) and all(isinstance(force, Forces) for force in forces):
self.forces.extend(forces) # Extend list with multiple Forces objects
else:
raise TypeError("forces must be an instance of Forces or a list of Forces")
[docs]
def get_forces_list(self) -> List[Forces]:
"""Returns the list of forces applied to this node."""
return self.forces
[docs]
def clear_forces(self) -> None:
"""Remove all forces from the node."""
self.forces.clear()
[docs]
def check(self) -> None:
"""
Complete check: flexure + shear.
"""
return self.section.check(self.forces) # type: ignore
[docs]
def design(self) -> None:
"""
Complete design: flexure + shear + flexure check.
"""
return self.section.design(self.forces) # type: ignore
[docs]
def check_flexure(self) -> pd.DataFrame:
return self.section.check_flexure(self.forces) # type: ignore
[docs]
def design_flexure(self) -> pd.DataFrame:
return self.section.design_flexure(self.forces) # type: ignore
[docs]
def check_shear(self) -> pd.DataFrame:
return self.section.check_shear(self.forces) # type: ignore
[docs]
def design_shear(self) -> pd.DataFrame:
return self.section.design_shear(self.forces) # type: ignore
[docs]
def shear_results_detailed(self, force: Optional[Forces] = None) -> None:
return self.section.shear_results_detailed(force)
[docs]
def shear_results_detailed_doc(self, force: Optional[Forces] = None) -> None:
return self.section.shear_results_detailed_doc(force)
[docs]
def flexure_results_detailed(self, force: Optional[Forces] = None) -> None:
return self.section.flexure_results_detailed(force)
[docs]
def flexure_results_detailed_doc(self, force: Optional[Forces] = None) -> None:
return self.section.flexure_results_detailed_doc(force)
def __repr__(self) -> str:
# Get the section label (assuming Section has a `_id` attribute)
section_label = f"Section label: {self.section.label}"
# Get the list of forces applied
forces_list = [str(force) for force in self.forces] # Assuming Forces has a `__repr__` or `__str__` method
forces_str = "\n - " + "\n - ".join(forces_list) if forces_list else "No forces applied"
# Combine section label and forces into a single string
return f"Node ID: {self.id} - {section_label}\nForces Applied:{forces_str}"
# Beam results for Jupyter Notebook
@property
def results(self) -> None:
return self.section.results
@property
def id(self) -> int:
"""Read-only property to access the private _id."""
return self._id