text: from o3seespy.base_model import OpenSeesObject
  
  
  class IntegratorBase(OpenSeesObject):
      op_base_type = "integrator"
  
  
  class LoadControl(IntegratorBase):
      """
      The LoadControl Integrator Class
      
      Create a OpenSees LoadControl integrator object.
      """
      op_type = 'LoadControl'
  
      def __init__(self, osi, incr, num_iter=1, min_incr: float=None, max_incr: float=None):
          r"""
          Initial method for LoadControl
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          incr: float
              Load factor increment :math:`\lambda`.
          num_iter: int, optional
              Number of iterations the user would like to occur in the solution algorithm. 
          min_incr: float (default=True), optional
              Min stepsize the user will allow :math:`\lambda_{min}`. 
          max_incr: float (default=True), optional
              Max stepsize the user will allow :math:`\lambda_{max}`. 
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.LoadControl(osi, incr=1.0, num_iter=1, min_incr=None, max_incr=None)
          """
          self.osi = osi
          self.incr = float(incr)
          self.num_iter = int(num_iter)
          if min_incr is None:
              self.min_incr = None
          else:
              self.min_incr = float(min_incr)
          if max_incr is None:
              self.max_incr = None
          else:
              self.max_incr = float(max_incr)
          self._parameters = [self.op_type, self.incr, self.num_iter]
          special_pms = ['min_incr', 'max_incr']
          packets = [False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class DisplacementControl(IntegratorBase):
      """
      The DisplacementControl Integrator Class
      
      Create a DisplacementControl integrator.  In an analysis step with Displacement Control we seek to determine the
      time step that will result in a displacement increment for a particular degree-of-freedom at a node to be a
      prescribed value.
      """
      op_type = 'DisplacementControl'
  
      def __init__(self, osi, node, dof, incr, num_iter=1, d_umin: float=None, d_umax: float=None):
          r"""
          Initial method for DisplacementControl
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          node: obj
              Object of node whose response controls solution
          dof: int
              Degree of freedom at the node, 1 through ndf.
          incr: float
              First displacement increment :math:`\delta u_{dof}`.
          num_iter: int, optional
              Number of iterations the user would like to occur in the solution algorithm. 
          d_umin: None (default=True), optional
              
          d_umax: None (default=True), optional
              
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> node = o3.node.Node(osi, 0.0, 0.0)
          >>> o3.integrator.DisplacementControl(osi, node, dof=1, incr=1.0, num_iter=1, d_umin=None, d_umax=None)
          """
          self.osi = osi
          self.node = node
          self.dof = int(dof)
          self.incr = float(incr)
          self.num_iter = int(num_iter)
          self.d_umin = d_umin
          self.d_umax = d_umax
          self._parameters = [self.op_type, self.node.tag, self.dof, self.incr, self.num_iter]
          special_pms = ['d_umin', 'd_umax']
          packets = [False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class ParallelDisplacementControl(IntegratorBase):
      """
      The ParallelDisplacementControl Integrator Class
      
      Create a Parallel version of DisplacementControl integrator.  In an analysis step with Displacement Control we seek
      to determine the time step that will result in a displacement increment for a particular degree-of-freedom at a node
      to be a prescribed value.
      """
      op_type = 'ParallelDisplacementControl'
  
      def __init__(self, osi, node, dof, incr, num_iter=1, d_umin: float=None, d_umax: float=None):
          r"""
          Initial method for ParallelDisplacementControl
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          node: obj
              Object of node whose response controls solution
          dof: int
              Degree of freedom at the node, 1 through ndf.
          incr: float
              First displacement increment :math:`\delta u_{dof}`.
          num_iter: int, optional
              Number of iterations the user would like to occur in the solution algorithm. 
          d_umin: None (default=True), optional
              
          d_umax: None (default=True), optional
              
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> node = o3.node.Node(osi, 0.0, 0.0)
          >>> o3.integrator.ParallelDisplacementControl(osi, node, dof=1, incr=1.0, num_iter=1, d_umin=None, d_umax=None)
          """
          self.osi = osi
          self.node = node
          self.dof = int(dof)
          self.incr = float(incr)
          self.num_iter = int(num_iter)
          self.d_umin = d_umin
          self.d_umax = d_umax
          self._parameters = [self.op_type, self.node.tag, self.dof, self.incr, self.num_iter]
          special_pms = ['d_umin', 'd_umax']
          packets = [False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class MinUnbalDispNorm(IntegratorBase):
      """
      The MinUnbalDispNorm Integrator Class
      
      Create a MinUnbalDispNorm integrator.
      """
      op_type = 'MinUnbalDispNorm'
  
      def __init__(self, osi, dlambda1, jd=1, min_lambda: float=None, max_lambda: float=None, det: float=None):
          """
          Initial method for MinUnbalDispNorm
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          dlambda1: float
              First load increment (pseudo-time step) at the first iteration in the next invocation of the analysis
              command.
          jd: int, optional
              Factor relating first load increment at subsequent time steps. 
          min_lambda: float (default=True), optional
              Min load increment. 
          max_lambda: float (default=True), optional
              Max load increment. 
          det: None (default=True), optional
              
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.MinUnbalDispNorm(osi, dlambda1=1.0, jd=1, min_lambda=None, max_lambda=None, det=None)
          """
          self.osi = osi
          self.dlambda1 = float(dlambda1)
          self.jd = int(jd)
          if min_lambda is None:
              self.min_lambda = None
          else:
              self.min_lambda = float(min_lambda)
          if max_lambda is None:
              self.max_lambda = None
          else:
              self.max_lambda = float(max_lambda)
          self.det = det
          self._parameters = [self.op_type, self.dlambda1, self.jd]
          special_pms = ['min_lambda', 'max_lambda', 'det']
          packets = [False, False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class ArcLength(IntegratorBase):
      """
      The ArcLength Integrator Class
      
      Create a ArcLength integrator. In an analysis step with ArcLength we seek to determine the time step that will
      result in our constraint equation being satisfied.
      """
      op_type = 'ArcLength'
  
      def __init__(self, osi, s, alpha):
          r"""
          Initial method for ArcLength
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          s: float
              The arclength.
          alpha: float
              :math:`\alpha` a scaling factor on the reference loads.
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.ArcLength(osi, s=1.0, alpha=1.0)
          """
          self.osi = osi
          self.s = float(s)
          self.alpha = float(alpha)
          self._parameters = [self.op_type, self.s, self.alpha]
          self.to_process(osi)
  
  
  class CentralDifference(IntegratorBase):
      r"""
      The CentralDifference Integrator Class
      
      Create a centralDifference integrator.#. The calculation of :math:`U_t + \Delta t`, is based on using the
      equilibrium equation at time t. For this reason the method is called an explicit integration method.#. If
      there is no rayleigh damping and the C matrix is 0, for a diagonal mass matrix a diagonal solver may and
      should be used.#. For stability, :math:`\frac{\Delta t}{T_n} < \frac{1}{\pi}`
      """
      op_type = 'CentralDifference'
  
      def __init__(self, osi):
          """
          Initial method for CentralDifference
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.CentralDifference(osi)
          """
          self.osi = osi
          self._parameters = [self.op_type]
          self.to_process(osi)
  
  
  class Newmark(IntegratorBase):
      """
      The Newmark Integrator Class
      
      Create a Newmark integrator.
      """
      op_type = 'Newmark'
  
      def __init__(self, osi, gamma, beta, form: str=None):
          r"""
          Initial method for Newmark
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          gamma: float
              :math:`\gamma` factor.
          beta: float
              :math:`\beta` factor.
          form: str, optional
              Flag to indicate which variable to be used as primary variable  * ``'d'`` -- displacement (default) *
              ``'v'`` -- velocity * ``'a'`` -- acceleration
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.Newmark(osi, gamma=1.0, beta=1.0, form=1)
          """
          self.osi = osi
          self.gamma = float(gamma)
          self.beta = float(beta)
          self.form = form
          self._parameters = [self.op_type, self.gamma, self.beta]
          if getattr(self, 'form') is not None:
              self._parameters += ['-form', self.form]
          self.to_process(osi)
  
  
  class HHT(IntegratorBase):
      """
      The HHT Integrator Class
      
      Create a Hilber-Hughes-Taylor (HHT) integrator. This is an implicit method that allows for energy dissipation and
      second order accuracy (which is not possible with the regular Newmark object). Depending on choices of input
      parameters, the method can be unconditionally stable.
      """
      op_type = 'HHT'
  
      def __init__(self, osi, alpha, gamma: float=None, beta: float=None):
          r"""
          Initial method for HHT
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          alpha: float
              :math:`\alpha` factor.
          gamma: float (default=True), optional
              :math:`\gamma` factor. 
          beta: float (default=True), optional
              :math:`\beta` factor. 
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.HHT(osi, alpha=1.0, gamma=1.0, beta=1.0)
          """
          self.osi = osi
          self.alpha = float(alpha)
          if gamma is None:
              self.gamma = None
          else:
              self.gamma = float(gamma)
          if beta is None:
              self.beta = None
          else:
              self.beta = float(beta)
          self._parameters = [self.op_type, self.alpha]
          special_pms = ['gamma', 'beta']
          packets = [False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class GeneralizedAlpha(IntegratorBase):
      r"""
      The GeneralizedAlpha Integrator Class
      
      Create a GeneralizedAlpha integrator. This is an implicit method that like the HHT method allows for high frequency
      energy dissipation and second order accuracy, i.e. :math:`\Delta t^2`. Depending on choices of input parameters, the
      method can be unconditionally stable.
      """
      op_type = 'GeneralizedAlpha'
  
      def __init__(self, osi, alpha_m, alpha_f, gamma: float=None, beta: float=None):
          r"""
          Initial method for GeneralizedAlpha
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
          alpha_m: float
              :math:`\alpha_m` factor.
          alpha_f: float
              :math:`\alpha_f` factor.
          gamma: float (default=True), optional
              :math:`\gamma` factor. 
          beta: float (default=True), optional
              :math:`\beta` factor. 
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.GeneralizedAlpha(osi, alpha_m=1.0, alpha_f=1.0, gamma=1.0, beta=1.0)
          """
          self.osi = osi
          self.alpha_m = float(alpha_m)
          self.alpha_f = float(alpha_f)
          if gamma is None:
              self.gamma = None
          else:
              self.gamma = float(gamma)
          if beta is None:
              self.beta = None
          else:
              self.beta = float(beta)
          self._parameters = [self.op_type, self.alpha_m, self.alpha_f]
          special_pms = ['gamma', 'beta']
          packets = [False, False]
          for i, pm in enumerate(special_pms):
              if getattr(self, pm) is not None:
                  if packets[i]:
                      self._parameters += [*getattr(self, pm)]
                  else:
                      self._parameters += [getattr(self, pm)]
              else:
                  break
          self.to_process(osi)
  
  
  class TRBDF2(IntegratorBase):
      """
      The TRBDF2 Integrator Class
      
      Create a TRBDF2 integrator. The TRBDF2 integrator is a composite scheme that alternates between the Trapezoidal
      scheme and a 3 point backward Euler scheme. It does this in an attempt to conserve energy and momentum, something
      Newmark does not always do.As opposed to dividing the time-step in 2 as outlined in the `Bathe2007`_, we just
      switch alternate between the 2 integration strategies,i.e. the time step in our implementation is double
      that described in the `Bathe2007`_.
      """
      op_type = 'TRBDF2'
  
      def __init__(self, osi):
          """
          Initial method for TRBDF2
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.TRBDF2(osi)
          """
          self.osi = osi
          self._parameters = [self.op_type]
          self.to_process(osi)
  
  
  class ExplicitDifference(IntegratorBase):
      r"""
      The ExplicitDifference Integrator Class
      
      Create a ExplicitDifference integrator.#. When using Rayleigh damping, the damping ratio of high vibration modes is
      overrated, and the critical time step size will be much smaller. Hence Modal damping is more suitable for this
      method.#. There should be no zero element on the diagonal of the mass matrix when using this method.#.
      Diagonal solver should be used when lumped mass matrix is used because the equations are uncoupled.#.
      For stability, :math:`\Delta t \leq \left(\sqrt{\zeta^2+1}-\zeta\right)\frac{2}{\omega}`
      """
      op_type = 'ExplicitDifference'
  
      def __init__(self, osi):
          """
          Initial method for ExplicitDifference
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
  
          Examples
          --------
          >>> import o3seespy as o3
          >>> osi = o3.OpenSeesInstance(ndm=2)
          >>> o3.integrator.ExplicitDifference(osi)
          """
          self.osi = osi
          self._parameters = [self.op_type]
          self.to_process(osi)
  
  
  class NewmarkExplicit(IntegratorBase):
      """
      Pass
      """
      op_type = 'NewmarkExplicit'
  
      def __init__(self, osi, gamma):
          """
          Initial method for NewmarkExplicit
  
          Parameters
          ----------
          osi: o3seespy.OpenSeesInstance
  
          """
          self.osi = osi
          self.gamma = gamma
          self._parameters = [self.op_type, self.gamma]
          self.to_process(osi)
  
  class GimmeMCK(IntegratorBase):
      """
      Integrator to obtain M, C and K matrices
      """
      op_type = 'GimmeMCK'
      def __init__(self, osi, m=0.0, c=0.0, k=0.0):
          self.osi = osi
          self.m = float(m)
          self.c = float(c)
          self.k = float(k)
          self._parameters = [self.op_type, self.m, self.c, self.k]
          self.to_process(osi)