6.7. Cyclic Pushover Analysis

modeller.do_cpo_analysis(ref_disp, mu_levels, push_dir, dispIncr, phi, pFlag=True, max_step=None, ansys_soe='BandGeneral', constraints_handler='Transformation', numberer='RCM', test_type='NormDispIncr', init_tol=1.0e-5, init_iter=1000, algorithm_type='KrylovNewton', save_animation_path=None)[source]

Perform cyclic pushover analysis (CPO) on a stick model. This method simulates a cyclic pushover analysis where a lateral load pattern is incrementally applied to the structure. This procedure simulates a cyclic lateral loading protocol in which the stick model is subjected to alternating displacement-controlled loading cycles at the control node. This approach allows the evaluation of strength degradation, stiffness deterioration, pinching effects, and energy dissipation capacity under repeated lateral loading, providing a more realistic representation of structural behaviour under seismic cyclic demands compared to a monotonic pushover analysis.

Parameters:
  • ref_disp (float) – Reference displacement (e.g., yield displacement) for scaling the cycles.

  • mu_levels (list) – Target ductility factors (mu) for each cycle level.

  • push_dir (int) – Direction of the pushover analysis (1=X, 2=Y, 3=Z).

  • dispIncr (int) – Minimum number of displacement increments per half-cycle. Used directly when max_step is None, or as a lower bound when max_step is set. A value of 5-10 is typical.

  • max_step (float or None, optional, default=None) – Maximum displacement increment size per analysis step [m]. When set, numIncr for each half-cycle is computed as max(dispIncr, ceil(excursion / max_step)), so larger cycles are automatically subdivided more finely and all loops stay smooth. For example, setting max_step = ref_disp * 0.1 limits each step to 10% of the reference displacement. Set to None to use a fixed dispIncr for every half-cycle.

  • phi (list of floats) – The lateral load pattern shape vector (scaled by mass).

  • pFlag (bool, optional, default=True) – If True, prints feedback during the analysis steps.

  • save_animation_path (string, optional,) – If provided, the path to save the animation (e.g., ‘cpo.gif’ or ‘cpo.mp4’).

  • ansys_soe (string, optional, default='BandGeneral') – System of equations solver.

  • constraints_handler (string, optional, default='Transformation') – Constraint handler method.

  • numberer (string, optional, default='RCM') – The numberer method.

  • test_type (string, optional, default='NormDispIncr') – Convergence test type.

  • init_tol (float, optional, default=1.0e-5) – The initial tolerance for convergence.

  • init_iter (int, optional, default=1000) – The maximum number of iterations for the solver.

  • algorithm_type (string, optional, default='KrylovNewton) – The solution algorithm type.

  • save_animation_path – If provided, saves the figure to this path (e.g., ‘cpo.gif’)

Returns:

cpo_dict – A dictionary containing all the analysis results.

Return type:

dict

Theoretical Background

The cyclic pushover (CPO) analysis applies a lateral load pattern \(\phi\) (scaled by the floor masses) under displacement control at the control node, following a reversed-cyclic protocol instead of a single monotonic excursion. Each cycle level \(i\) reaches a target displacement

\[\delta_i = \mu_i \, \delta_{ref}\]

where \(\delta_{ref}\) is the reference displacement ref_disp (e.g. the yield displacement) and \(\mu_i\) the ductility levels in mu_levels. Every half-cycle is subdivided into at least dispIncr increments; if max_step is given, the number of increments is \(\max(\texttt{dispIncr}, \lceil \text{excursion}/\texttt{max\_step} \rceil)\) so larger cycles are integrated with the same resolution.

The resulting hysteresis loops expose strength degradation, stiffness deterioration, pinching and the energy dissipation capacity of the storey springs, which a monotonic pushover cannot show. Collapse is detected as in the other analyses: through the MinMax material limit and an independent cross-check of the nodal inter-storey displacement.

Example

m.compile_model()
m.do_gravity_analysis()
periods, mode_shapes = m.do_modal_analysis(num_modes=2)
cpo_dict = m.do_cpo_analysis(
    ref_disp=0.005,
    mu_levels=[1, 2, 4, 6],
    push_dir=1,
    dispIncr=10,
    phi=mode_shapes[:, 0],
    max_step=0.0005,
    save_animation_path="cpo_animation.gif",  # or None
)