pycufsm.fsm

Functions

strip(→ Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray])

Perform a finite strip analysis

strip_new(→ Tuple[numpy.ndarray, numpy.ndarray, ...)

Converts new format of inputs to old (original CUFSM) format

signature_ss(→ Tuple[numpy.ndarray, numpy.ndarray, ...)

generate the signature curve solution, part 2: actually solve the signature curve

m_recommend(→ Tuple[numpy.ndarray, numpy.ndarray, ...)

Suggested longitudinal terms are calculated based on the characteristic

Module Contents

pycufsm.fsm.strip(props: numpy.ndarray, nodes: numpy.ndarray, elements: numpy.ndarray, lengths: numpy.ndarray, springs: numpy.ndarray, constraints: numpy.ndarray, GBT_con: pycufsm._types.GBT_Con, B_C: pycufsm._types.BC, m_all: numpy.ndarray, n_eigs: int, sect_props: pycufsm._types.Sect_Props) Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Perform a finite strip analysis

Args:
props (np.ndarray): Material properties
[[mat_num, stiff_x, E_y, nu_x, nu_y, G_bulk], …]
nodes (np.ndarray): Nodal properties
[[node#, x, y, dof_x, dof_y, dof_z, dof_r, stress], …]
elements (np.ndarray): Element properties
[[elem#, node_i, node_j, thick, mat_num], …]
lengths (np.ndarray): Half-wavelengths to analyse
[length1, length2, …]

These could be half-wavelengths for signature curve or physical lengths for general b.c.

springs (np.ndarray): Nodal springs (if any)
[[node#, node_pair, k_x, k_y, k_z, k_q, k_type, discrete, y_s], …]

where k_flag is 0 for a foundation spring, or 1 for a total spring. discrete is 1 for a discrete spring. k_* are the spring stiffnesses for each DOF, and y_s is the location of the discrete spring; it is ignored if the spring is not discrete.

constraints (np.ndarray):
`[[node#_e dof_e coeff node#_k dof_k], …]

where k=kept dof, e=dof to be eliminated. Each DOF is set as an integer where 1=x, 2=y, 3=z, 4=q. The resulting constraint will be node_e_dof = coeff * node_k_dof

GBT_con (GBT_Con): GBT Configuration
{
“glob”: [0|1, 0|1, …],
“dist”: [0|1, 0|1, …],
“local”: [0|1, 0|1, …],
“other”: [0|1, 0|1, …],
“o_space”: 1|2|3|4,
“norm”: 0|1|2|3,
“couple”: 1|2,
“orth”: 1|2|3,
}
GBT_con.glob,GBT_con.dist, GBT_con.local, GBT_con.other:

vectors of 1’s and 0’s referring to the inclusion (1) or exclusion of a given mode from the analysis,

GBT_con.o_space - choices of ST/O mode
1: ST basis
2: O space (null space of GDL) with respect to K_global
3: O space (null space of GDL) with respect to Kg_global
4: O space (null space of GDL) in vector sense
GBT_con.norm - code for normalization (if normalization is done at all)
0: no normalization,
1: vector norm
2: strain energy norm
3: work norm
GBT_con.couple - coupled basis vs uncoupled basis

for general B.C. especially for non-simply supported B.C. | 1: uncoupled basis, the basis will be block diagonal | 2: coupled basis, the basis is fully spanned

GBT_con.orth - natural basis vs modal basis
1: natural basis
2: modal basis, axial orthogonality
3: modal basis, load dependent orthogonality
B_C (str): Boundary condition to be analyzed
‘S-S’ simply-pimply supported boundary condition at loaded edges
‘C-C’ clamped-clamped boundary condition at loaded edges
‘S-C’ simply-clamped supported boundary condition at loaded edges
‘C-F’ clamped-free supported boundary condition at loaded edges
‘C-G’ clamped-guided supported boundary condition at loaded edges
m_all (np.ndarray): Longitudinal terms for each half-wavelength
m_all[length#] = [longitudinal_num, …],

Longitudinal terms m for all the lengths in cell notation each cell has a vector including the longitudinal terms for this length

n_eigs (int): Number of eigenvalues

The number of eigenvalues to be determined at length (default=10)

sect_props (Sect_Props): Section properties
{
“A”: float,
“cx”: float,
“cy”: float,
“Ixx”: float,
“Iyy”: float,
“Ixy”: float,
“phi”: float,
“I11”: float,
“I22”: float,
“J”: float,
“x0”: float,
“y0”: float,
“Cw”: float,
“B1”: float,
“B2”: float,
“wn”: np.ndarray
}

Dictionary of section properties of cross-section

Returns:
signature (np.ndarray): Signature curve
signature[length#] = load_factor
curve (np.ndarray): buckling curve (load factor) for each length
curve[length#] = [mode1_load_factor, mode2_load_factor, …]
shapes (np.ndarray): mode shapes for each length
shapes[length#] = [disp_mode1, disp_mode2, …]

Each disp_* is an array of displacements for each node in the section

pycufsm.fsm.strip_new(props: Dict[str, Dict[str, float]], nodes: pycufsm._types.ArrayLike, elements: Sequence[pycufsm._types.New_Element], yield_force: pycufsm._types.Yield_Force | None = None, forces: pycufsm._types.Forces | None = None, sect_props: pycufsm._types.Sect_Props | None = None, lengths: pycufsm._types.ArrayLike | set | Dict[float, pycufsm._types.ArrayLike] | None = None, node_props: Dict[Literal['all'] | int, pycufsm._types.New_Node_Props] | None = None, springs: Sequence[pycufsm._types.New_Spring] | None = None, constraints: Sequence[pycufsm._types.New_Constraint] | None = None, analysis_config: pycufsm._types.Analysis_Config | None = None, cfsm_config: pycufsm._types.Cfsm_Config | None = None) Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

Converts new format of inputs to old (original CUFSM) format

Args:
props (Dict[str, Dict[str, float]]): Material properties
{“mat_name”: {E_x: float, E_y: float, nu_x: float, nu_y: float, G_bulk: float}, …}
or
{“mat_name”: {E: float, nu: float}}

The latter option assumes an isotropic material.

nodes (ArrayLike): Nodal coordinates
[[x, y, stress], …]
or
[[x, y], …]

The latter option assumes that the stress will be set using Note that any node numbers used in later inputs refer to the index of the node in this nodes array, with the first node being node number 0.

elements (Sequence[New_Element]): Element connectivity and properties
[{
nodes: “all”|List[int],
t: float,
mat: str
)].
elements[“nodes”]:

nodes: “all” is a special indicator that all nodes should be connected sequentially. If nodes is given as an array, any number of nodal indices may be listed in order

elements[“t”]:

Material thickness

elements[“mat”]:

material name as a string

yield_force (Optional[Yield_Force]): Single yield force to apply to section.
{
force: “Mxx”|”Myy”|”M11”|”M22”|”P”,
direction: “Pos”|”Neg”|”+”|”-“,
f_y: float,
restrain: bool,
offset: ArrayLike
}

Either this or ‘forces’ must be set, or stresses must be set manually in nodes. yield_force[“restrain”]:

Note that ‘restrain’ only affects “Mxx” or “Myy” forces, and then only for sections in which the principal axes are no aligned with the geometric axes (such as Z sections)

yield_force[“offset”]:
[x_offset, y_offset]

Offset from the (0,0) coordinate used in calculating section properties and the (0,0) coordinate used to define the nodal coordinates. This may commonly differ by thickness/2, for example, if an external section properties calculator is used

forces (Optional[Forces]): Specific forces to apply to the section.
{
‘P’: float,
‘Mxx’: float,
‘Myy’: float,
‘M11’: float,
‘M22’: float,
‘restrain’: bool,
‘offset’: ArrayLike
}
forces[“restrain”]:

Note that ‘restrain’ only affects “Mxx” or “Myy” forces, and then only for sections in which the principal axes are no aligned with the geometric axes (such as Z sections)

forces[“offset”]:
[x_offset, y_offset]

Offset from the (0,0) coordinate used in calculating section properties and the (0,0) coordinate used to define the nodal coordinates. This may commonly differ by thickness/2, for example, if an external section properties calculator is used

Either this or ‘yield_force’ must be set, or stresses must be set manually in nodes.

sect_props (Optional[Sect_Props]): Section properties
{
“A”: float,
“cx”: float,
“cy”: float,
“Ixx”: float,
“Iyy”: float,
“Ixy”: float,
“phi”: float,
“I11”: float,
“I22”: float,
“J”: float,
“x0”: float,
“y0”: float,
“Cw”: float,
“B1”: float,
“B2”: float,
“wn”: np.ndarray
}

Dictionary of section properties of cross-section. If None, section properties will be calculated using the included CUTWP based on the geometry defined by nodes and elements, and the material properties defined in props.

lengths (Optional[Union[ArrayLike, set, Dict[float, ArrayLike]]]): Half-wavelengths for analysis
[length1, length2, …]
or
`{length1: List[int], length2: List[int], …}

If given as a simple array, then the longitudinal m term will be taken as [1] for each half-wavelength (which is normally what you want for a signature curve analysis). If given as a dictionary, then the longitudinal m terms must be set to an array with appropriate values. If None, then lengths will be taken as the recommended lengths based on the geometry of the section, and the longitudinal m terms will be taken as [1] for each length.

node_props (Optional[Dict[Union[Literal[“all”, int], New_Node_Props]]): Nodal DOF inclusion
{
node_#|”all”: {
dof_x: bool,
dof_y: bool,
dof_z: bool,
dof_q: bool,
}
}

Defaults to None, and taken as all DOFs included if so. Any DOFs set to false will be taken as fully constrained to ground

springs (Optional[Sequence[New_Spring]]): Definition of any springs in cross-section
[{
node: int,
k_x: float,
k_y: float,
k_z: float,
k_q: float,
k_type: “foundation”|”node_pair”|”total”,
node_pair: int,
discrete: bool,
y: float,
}, …]

k_type is the stiffness type. node_pair and y keys are only required if the k_type or discrete options are set to require them. Defaults to None.

constraints (Optional[Sequence[New_Constraint]]): Definition of any constraints in section
[{
elim_node: int,
elim_dof: “x”|”y”|”z”|”q”,
coeff: float,
keep_node: int,
keep_dof: “x”|”y”|”z”|”q”
}, …]

“q” is the twist DOF. Each constraint takes the form of elim_dof = coeff * keep_dof. Defaults to None.

analysis_config (Optional[Analysis_Config]): Configuration options for any analysis
{
B_C: “S-S”|”C-C”|”S-C”|”C-F”|”C-G”,
n_eigs: int
}

Defaults to None, and taken as {B_C: “S-S”, n_eigs: 10} if so. analysis_config[“B_C”]: Boundary condition types (at loaded edges):

‘S-S’ simple-simple
‘C-C’ clamped-clamped
‘S-C’ simple-clamped
‘C-F’ clamped-free
‘C-G’ clamped-guided
cfsm_config (Optional[Cfsm_Config]): Configuration options for cFSM (constrained modes)
{
glob_modes: list(int),
dist_modes: list(int),
local_modes: list(int),
other_modes: list(int),
null_space: “ST”|”K_global”|”Kg_global”|”vector”,
normalization: “none”|”vector”|”strain_energy”|”work”,
coupled: bool,
orthogonality: “natural”|”modal_axial”|”modal_load”

} Defaults to None, in which case no cFSM analysis is performed analysis_config[”*_modes”]:

list of 1’s (inclusion) and 0’s (exclusion) for each mode from the analysis

analysis_config[“null_space”]:
“ST”: ST basis
“K_global”: null space of GDL with respect to K_global
“Kg_global”: null space of GDL with respect to Kg_global
“vector”: null space of GDL in vector sense
analysis_config[“normalization”]: Type of normalization

If any is performed.

analysis_config[“coupled”]: basis for general boundary conditions
uncoupled basis = the basis will be block diagonal
coupled basis = the basis is fully spanned
analysis_config[“orthogonality”]: natural basis vs modal basis
“natural”: natural basis
“modal_axial”: modal basis, axial orthogonality
“modal_load”: modal basis, load dependent orthogonality
Returns:
signature (np.ndarray): Signature curve
signature[length#] = load_factor
curve (np.ndarray): buckling curve (load factor) for each length
curve[length#] = [mode1_load_factor, mode2_load_factor, …]
shapes (np.ndarray): mode shapes for each length
shapes[length#] = [disp_mode1, disp_mode2, …]

Each disp_* is an array of displacements for each node in the section

nodes_stressed: Nodal coordinates with stresses
[[x, y, stress], …]
lengths: Half-wavelengths used in analysis
[length1, length2, …]
pycufsm.fsm.signature_ss(props: numpy.ndarray, nodes: numpy.ndarray, elements: numpy.ndarray, i_GBT_con: pycufsm._types.GBT_Con, sect_props: pycufsm._types.Sect_Props, lengths: numpy.ndarray) Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

generate the signature curve solution, part 2: actually solve the signature curve

Args:

props (np.ndarray): standard parameter nodes (np.ndarray): standard parameter elements (np.ndarray): standard parameter i_GBT_con (GBT_Con): cFSM configuration options sect_props (Sect_Props): section properties lengths (np.ndarray): half-wavelengths

Returns:

signature: signature curve, curve: all the curve results, shapes: deformed shapes at each point

(function originally in helpers; moved to fsm because it drives entire fsm analyses) Z. Li, July 2010 (last modified)

pycufsm.fsm.m_recommend(props: numpy.ndarray, nodes: numpy.ndarray, elements: numpy.ndarray, sect_props: pycufsm._types.Sect_Props, length_append: float | None = None, n_lengths: int = 50, lengths: numpy.ndarray | None = None) Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

Suggested longitudinal terms are calculated based on the characteristic half-wave lengths of local, distortional, and global buckling from the signature curve.

Args:

props (np.ndarray): standard parameter nodes (np.ndarray): standard parameter elements (np.ndarray): standard parameter sect_props (Sect_Props): section properties length_append (Optional[float], optional): any additional half-wavelength to include.

Defaults to None.

n_lengths (int, optional): number of half-wavelengths. Defaults to 50. lengths (Optional[np.ndarray], optional): specific half-wavelengths to use.

Defaults to None.

Returns:

_type_: _description_

(function originally in helpers; moved to fsm because it drives entire fsm analyses) Z. Li, Oct. 2010