Пример #1
0
/* This is the DC netlist solver.  It prepares the circuit list and
   solves it then. */
int dcsolver::solve (void) {
  // fetch simulation properties
  saveOPs |= !strcmp (getPropertyString ("saveOPs"), "yes") ? SAVE_OPS : 0;
  saveOPs |= !strcmp (getPropertyString ("saveAll"), "yes") ? SAVE_ALL : 0;
  char * solver = getPropertyString ("Solver");

  // initialize node voltages, first guess for non-linear circuits and
  // generate extra circuits if necessary
  init ();
  setCalculation ((calculate_func_t) &calc);

  // start the iterative solver
  solve_pre ();

  // choose a solver
  if (!strcmp (solver, "CroutLU"))
    eqnAlgo = ALGO_LU_DECOMPOSITION_CROUT;
  else if (!strcmp (solver, "DoolittleLU"))
    eqnAlgo = ALGO_LU_DECOMPOSITION_DOOLITTLE;
  else if (!strcmp (solver, "HouseholderQR"))
    eqnAlgo = ALGO_QR_DECOMPOSITION;
  else if (!strcmp (solver, "HouseholderLQ"))
    eqnAlgo = ALGO_QR_DECOMPOSITION_LS;
  else if (!strcmp (solver, "GolubSVD"))
    eqnAlgo = ALGO_SV_DECOMPOSITION;

  // local variables for the fallback thingies
  int retry = -1, error, fallback = 0, preferred;
  int helpers[] = {
    CONV_SourceStepping,
    CONV_GMinStepping,
    CONV_SteepestDescent,
    CONV_LineSearch,
    CONV_Attenuation,
    -1 };

  // is a certain convergence helper requested?
  char * helper = getPropertyString ("convHelper");
  convHelper = CONV_None;
  if (!strcmp (helper, "LineSearch")) {
    convHelper = CONV_LineSearch;
  } else if (!strcmp (helper, "SteepestDescent")) {
    convHelper = CONV_SteepestDescent;
  } else if (!strcmp (helper, "Attenuation")) {
    convHelper = CONV_Attenuation;
  } else if (!strcmp (helper, "gMinStepping")) {
    convHelper = CONV_GMinStepping;
  } else if (!strcmp (helper, "SourceStepping")) {
    convHelper = CONV_SourceStepping;
  }
  preferred = convHelper;

  if (!subnet->isNonLinear ()) {
    // Start the linear solver.
    convHelper = CONV_None;
    error = solve_linear ();
  }
  else do {
    // Run the DC solver once.
    try_running () {
      applyNodeset ();
      error = solve_nonlinear ();
#if DEBUG
      if (!error) {
	logprint (LOG_STATUS,
		  "NOTIFY: %s: convergence reached after %d iterations\n",
		  getName (), iterations);
      }
#endif /* DEBUG */
      if (!error) retry = -1;
    }
    // Appropriate exception handling.
    catch_exception () {
    case EXCEPTION_NO_CONVERGENCE:
      pop_exception ();
      if (preferred == helpers[fallback] && preferred) fallback++;
      convHelper = helpers[fallback++];
      if (convHelper != -1) {
	logprint (LOG_ERROR, "WARNING: %s: %s analysis failed, using fallback "
		  "#%d (%s)\n", getName (), getDescription (), fallback,
		  getHelperDescription ());
	retry++;
	restart ();
      }
      else {
	retry = -1;
      }
      break;
    default:
      // Otherwise return.
      estack.print ();
      error++;
      break;
    }
  } while (retry != -1);

  // save results and cleanup the solver
  saveOperatingPoints ();
  saveResults ("V", "I", saveOPs);

  solve_post ();
  return 0;
}
Пример #2
0
/* synchronous step solver for external ode routine
 *
 * This function solves the circuit for a single time delta provided
 * by an external source. Convergence issues etc. are expected to
 * be handled by the external solver, as it is in full control of the
 * time stepping.
 */
int e_trsolver::stepsolve_sync(nr_double_t synctime)
{

    int error = 0;
    convError = 0;

    time = synctime;
    // update the interpolation time of any externally controlled
    // components which require it.
    updateExternalInterpTime(time);

    // copy the externally chosen time step to delta
    delta = time - lastsynctime;

    // get the current solution time
    //current += delta;

    // updates the integrator coefficients, and updates the array of prev
    // 8 deltas with the new delta for this step
    updateCoefficients (delta);

    // Run predictor to get a start value for the solution vector for
    // the successive iterative corrector process
    error += predictor ();

    // restart Newton iteration
    restart (); // restart non-linear devices

    // Attempt to solve the circuit with the given delta
    try_running () // #defined as:    do {
    {
        //error += solve_nonlinear_step ();
        error += corrector ();
    }
    catch_exception () // #defined as:   } while (0); if (estack.top ()) switch (estack.top()->getCode ())
    {
    case EXCEPTION_NO_CONVERGENCE:
        pop_exception ();

        // Retry using damped Newton-Raphson.
        this->convHelper = CONV_SteepestDescent;
        convError = 2;
#if DEBUG
        messagefcn (LOG_ERROR, "WARNING: delta rejected at t = %.3e, h = %.3e "
                  "(no convergence)\n", (double) saveCurrent, (double) delta);
#endif

        try_running () // #defined as:    do {
        {
//            error += solve_nonlinear_step ();
            error += solve_nonlinear ();
        }
        catch_exception () // #defined as:   } while (0); if (estack.top ()) switch (estack.top()->getCode ())
        {
        case EXCEPTION_NO_CONVERGENCE:
            pop_exception ();

            // Update statistics.
            statRejected++;
            statConvergence++;
            rejected++;
            converged = 0;
            error = 0;

            break;
        default:
            // Otherwise return.
            estack.print ();
            error++;
            break;
        }

        // Update statistics and no more damped Newton-Raphson.
//        statIterations += iterations;
//        if (--convError < 0) this->convHelper = 0;


        break;
    default:
        // Otherwise return.
        estack.print ();
        error++;
        break;
    }
    // if there was an error other than non-convergence, return -1
    if (error) return -1;

    // check whether Jacobian matrix is still non-singular
    if (!A->isFinite ())
    {
//        messagefcn (LOG_ERROR, "ERROR: %s: Jacobian singular at t = %.3e, "
//                  "aborting %s analysis\n", getName (), (double) current,
//                  getDescription ());
        return -1;
    }

    return 0;
}