# SPDX-License-Identifier: MIT
# Copyright (c) 2011–2026 Joris J.C. Remmers
from pyfem.util.BaseModule import BaseModule
from pyfem.util.dataStructures import Properties, GlobalData
from numpy import zeros, array, pi
from pyfem.fem.Assembly import assembleInternalForce, assembleTangentStiffness
from pyfem.fem.Assembly import assembleExternalForce
from pyfem.util.logger import getLogger
from typing import Any, Sequence, Tuple
logger = getLogger()
#------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------
[docs]
class BuckEigSolver(BaseModule):
"""
Eigenvalue solver for buckling analysis.
This solver assembles the initial and current tangent stiffness matrices,
solves the static problem to obtain the prebuckling state and computes
eigenvalues/eigenvectors for the buckling problem.
Attributes:
tol: convergence tolerance for internal iterations
iterMax: maximum iterations (unused currently)
fext: external force vector (numpy array-like)
"""
def __init__(self, props: Properties, globdat: GlobalData) -> None:
"""
Initialize solver.
Args:
props: analysis properties
globdat: global data structure containing mesh, dofs and state
"""
self.tol = 1.0e-3
self.iterMax = 10
BaseModule.__init__(self, props)
# external force vector sized to global dof vector
self.fext: Any = zeros(len(globdat.dofs))
#------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------
[docs]
def run(self, props: Properties, globdat: GlobalData) -> None:
"""
Execute the buckling eigenvalue analysis.
Steps:
- assemble initial tangent stiffness K0 and internal force fint
- assemble external force fext and solve for prebuckling state
- assemble updated stiffness K and compute eigenpairs using DOF solver
- commit element history and deactivate model if appropriate
Args:
props: analysis properties
globdat: global data structure (modified in-place)
"""
self.writeHeader()
# initial tangent stiffness and internal force
K0, fint = assembleTangentStiffness(props, globdat) # type: Tuple[Any, Any]
# assemble external force
fext = assembleExternalForce(props, globdat) # type: Any
# solve static problem for prebuckling state
globdat.state = globdat.dofs.solve(K0, fext)
# assemble updated stiffness at prebuckling state
K, fint = assembleTangentStiffness(props, globdat) # type: Tuple[Any, Any]
# compute eigenvalues/eigenvectors for buckling: generalized problem
globdat.eigenvals, globdat.eigenvecs = globdat.dofs.eigensolve(K0, (K0 - K))
# commit element history and finalize
globdat.elements.commitHistory()
globdat.active = False
self.printResults(globdat.eigenvals)
#------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------
[docs]
def printResults(self, eigenvals: Sequence[float]) -> None:
"""
Print computed eigenvalues.
Args:
eigenvals: iterable of eigenvalues (loads) to report
"""
logger.info(" Eigen modes")
logger.info(" ---------------------------------------------------------")
logger.info(" Mode | Load")
for i, f in enumerate(eigenvals):
logger.info(f" {i+1:4d} | {f:6.4e} ")