OpenSees Cloud

OpenSees AMI

Modal Participation Factors

Original Post - 01 Nov 2020 - Michael H. Scott

Visit Structural Analysis Is Simple on Substack.


Computing modal participation factors (yes, I know it’s a misnomer) from an OpenSees model is straightforward if you define only nodal mass with no element mass. Examples are available online showing how to compute the factors in OpenSees using Tcl, but let’s go over how to do it with OpenSeesPy.

After you define your model with nodal mass and do an eigenvalue analysis, you can write a simple loop with a couple utility functions to evaluate \(\Gamma_n = \phi_n^T m \iota / \phi_n^T m \phi_n\) for the \(n^{th}\) mode. In the code below, I’m wrapping that simple loop with another loop over N modes.

#
# Define your model
#
ndf = 6 # Nodal degrees of freedom

N = 3 # Or whatever
omega2 = ops.eigen(N)

for n in range(N):
   Mn = 0.0
   Ln = 0.0
   for nd in ops.getNodeTags():
      ndMass = ops.nodeMass(nd)
      ndEigen = ops.nodeEigenvector(nd,n+1)
      Ln += ndEigen[0]*ndMass[0] # 0 for X, 1 for Y, 2 for Z excitation
      for dof in range(ndf):
         Mn += (ndEigen[dof]**2)*ndMass[dof]
   Gamman = Ln/Mn
   Tn = 2*3.14159/omega2[n]**0.5
   print(f'Mode {n+1}, Tn = {Tn}, Mn = {Mn}, Gamma = {Gamman}')

The default eigenvalue solver returns mass orthonormal eigenvectors, leading to unit values of modal mass. However, this solver will fail if you ask for as many modes as there are dynamic DOFs, e.g., asking for 4 modes from a model with 4 dynamic DOFs gives the following error:

Modal participation factors computed with default eigenvalue solver

To get all modes from the eigenvalue analysis, you can use the 'fullGenLapack' option to the eigen command.

omega2 = ops.eigen('fullGenLapack',Nmodes)

While this solver returns the same eigenvalues as the default solver, the eigenvectors are not normalized by mass. So, the modal masses will not be 1.0 and the modal participation factors you calculate will be different from the default solver. For example, asking for 3 modes using both solvers gives the following output. The periods are the same, but not the modal quantities.

Modal participation factors computed with fullGenLapack

Most of these differences come out in the wash. Except for modal damping. The non-mass-normalized eigenvectors can really mess up your modal damping. So, once again, be careful with modal damping.



Update: The issue with fullGenLapack not returning mass orthonormal eigenvectors was fixed in January 2022 with this commit.