docs: def run(self):
          """
          Run time domain simulation
  
          Returns
          -------
          bool
              Success flag
          """
          ret = False
          system = self.system
          config = self.config
          dae = self.system.dae
  
          # maxit = config.maxit
          # tol = config.tol
  
          if system.pflow.solved is False:
              logger.warning('Power flow not solved. Simulation cannot continue.')
              return ret
          t0, _ = elapsed()
          t1 = t0
  
          self.streaming_init()
  
          logger.info('')
          logger.info('-> Time Domain Simulation: {} method, t={} s'
                      .format(self.config.method, self.config.tf))
  
          self.load_pert()
  
          self.run_step0()
  
          config.qrtstart = time()
  
          while self.t < config.tf:
              self.check_fixed_times()
              self.calc_time_step()
  
              if self.callpert is not None:
                  self.callpert(self.t, self.system)
  
              if self.h == 0:
                  break
              # progress time and set time in dae
              self.t += self.h
              dae.t = self.t
  
              # backup actual variables
              self.x0 = matrix(dae.x)
              self.y0 = matrix(dae.y)
              self.f0 = matrix(dae.f)
  
              # apply fixed_time interventions and perturbations
              self.event_actions()
  
              # reset flags used in each step
              self.err = 1
              self.niter = 0
              self.convergence = False
  
              self.implicit_step()
  
              if self.convergence is False:
                  try:
                      self.restore_values()
                      continue
                  except ValueError:
                      self.t = config.tf
                      ret = False
                      break
  
              self.step += 1
              self.compute_flows()
              system.varout.store(self.t, self.step)
              self.streaming_step()
  
              # plot variables and display iteration status
              perc = max(min((self.t - config.t0) / (config.tf - config.t0) * 100, 100), 0)
  
              # show iteration info every 30 seconds or every 20%
  
              t2, _ = elapsed(t1)
              if t2 - t1 >= 30:
                  t1 = t2
                  logger.info(' ({:.0f}%) time = {:.4f}s, step = {}, niter = {}'
                              .format(100 * self.t / config.tf, self.t, self.step,
                                      self.niter))
  
              if perc > self.next_pc or self.t == config.tf:
                  self.next_pc += 20
                  logger.info(' ({:.0f}%) time = {:.4f}s, step = {}, niter = {}'
                              .format(100 * self.t / config.tf, self.t, self.step, self.niter))
  
              # compute max rotor angle difference
              # diff_max = anglediff()
  
              # quasi-real-time check and wait
              rt_end = config.qrtstart + (self.t - config.t0) * config.kqrt
  
              if config.qrt:
                  # the ending time has passed
                  if time() - rt_end > 0:
                      # simulation is too slow
                      if time() - rt_end > config.kqrt:
                          logger.debug('Simulation over-run at t={:4.4g} s.'.format(self.t))
                  # wait to finish
                  else:
                      self.headroom += (rt_end - time())
                      while time() - rt_end < 0:
                          sleep(1e-5)
  
          if config.qrt:
              logger.debug('RT headroom time: {} s.'.format(str(self.headroom)))
  
          if self.t != config.tf:
              logger.error('Reached minimum time step. Convergence is not likely.')
              ret = False
          else:
              ret = True
  
          if system.config.dime_enable:
              system.streaming.finalize()
  
          _, s = elapsed(t0)
  
          if ret is True:
              logger.info(' Time domain simulation finished in {:s}.'.format(s))
          else:
              logger.info(' Time domain simulation failed in {:s}.'.format(s))
  
          self.success = ret
          self.dump_results(success=self.success)
  
          return ret