/* 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; }
/* This is the initialisation function for the slaved transient netlist solver. It prepares the circuit for simulation. */ int e_trsolver::init (nr_double_t start, nr_double_t firstdelta, int mode) { // run the equation solver for the netlist this->getEnv()->runSolver(); int error = 0; const char * const solver = getPropertyString ("Solver"); relaxTSR = !strcmp (getPropertyString ("relaxTSR"), "yes") ? true : false; initialDC = !strcmp (getPropertyString ("initialDC"), "yes") ? true : false; // fetch simulation properties MaxIterations = getPropertyInteger ("MaxIter"); reltol = getPropertyDouble ("reltol"); abstol = getPropertyDouble ("abstol"); vntol = getPropertyDouble ("vntol"); runs++; saveCurrent = current = 0; stepDelta = -1; converged = 0; fixpoint = 0; lastsynctime = 0.0; statRejected = statSteps = statIterations = statConvergence = 0; // Choose a solver. if (!strcmp (solver, "CroutLU")) eqnAlgo = ALGO_LU_DECOMPOSITION; 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; // Perform initial DC analysis. if (initialDC) { error = dcAnalysis (); if (error) return -1; } // Initialize transient analysis. setDescription ("transient"); initETR (start, firstdelta, mode); setCalculation ((calculate_func_t) &calcTR); solve_pre (); // Recall the DC solution. recallSolution (); // Apply the nodesets and adjust previous solutions. applyNodeset (false); fillSolution (x); fillLastSolution (x); // Tell integrators to be initialized. setMode (MODE_INIT); // reset the circuit status to not running so the histories // etc will be reinitialised on the first time step running = 0; rejected = 0; if (mode == ETR_MODE_ASYNC) { delta /= 10; } else if (mode == ETR_MODE_SYNC) { //lastsynctime = start - delta; } else { qucs::exception * e = new qucs::exception (EXCEPTION_UNKNOWN_ETR_MODE); e->setText ("Unknown ETR mode."); throw_exception (e); return -2; } fillState (dState, delta); adjustOrder (1); storeHistoryAges (); return 0; }