Xyce  6.1
N_DEV_SolverState.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_SolverState.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 08/25/03
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.57 $
40 //
41 // Revision Date : $Date: 2015/05/15 19:18:29 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-----------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 #include <iostream>
49 
50 #include <N_ANP_AnalysisManager.h>
51 #include <N_DEV_DeviceOptions.h>
52 #include <N_DEV_SolverState.h>
54 #include <N_TIA_StepErrorControl.h>
55 #include <N_UTL_Expression.h>
56 #include <N_UTL_FeatureTest.h>
57 #include <N_UTL_Diagnostic.h>
58 
59 namespace Xyce {
60 namespace Device {
61 
62 //-----------------------------------------------------------------------------
63 // Function : SolverState::SolverState
64 // Purpose : constructor
65 // Special Notes :
66 // Scope : public
67 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
68 // Creation Date : 08/25/03
69 //-----------------------------------------------------------------------------
71  : isPDESystem_(false),
72  pdt_(0.0),
73  startingTimeStep_(0.0),
74  bpTol_(0.0),
75  currTimeStep_(0.0),
76  lastTimeStep_(0.0),
77  currTime_(0.0),
78  finalTime_(0.0),
79  acceptedTime_(0.0),
80  currentOrder_(0),
81  usedOrder_(0),
82  currFastTime_(0.0),
83  mpdeOnFlag_(false),
84  blockAnalysisFlag_(false),
85  doubleDCOPEnabled(false),
86  doubleDCOPStep (0),
87  timeStepNumber_(0),
88  ltraTimeIndex_(0),
89  ltraTimeHistorySize_(0),
90  ltraDoCompact_(false),
91  ltraTimePoints_(),
92  initTranFlag_(false),
93  sweepSourceResetFlag(false),
94  beginIntegrationFlag_(true),
95  dcopFlag (true),
96  inputOPFlag (false),
97  transientFlag (true),
98  dcsweepFlag (false),
99  tranopFlag (true),
100  acopFlag (false),
101  newtonIter (0),
102  locaEnabledFlag (false),
103  externalStateFlag_(false),
104  externalInitJctFlag_(false),
105  continuationStepNumber (0),
106  firstContinuationParam (true),
107  firstSolveComplete (false),
108  initJctFlag_(false),
109  initFixFlag (false),
110  debugTimeFlag (false),
111  twoLevelNewtonCouplingMode (Nonlinear::FULL_PROBLEM),
112  bjtArtParameterFlag_(false),
113  pdeAlpha_(1.0),
114  chargeAlpha_(1.0),
115  chargeHomotopy_(false),
116  PDEcontinuationFlag_(false),
117  artParameterFlag_(false),
118  gainScale_(1, 1.0),
119  nltermScale_(1.0),
120  sizeParameterFlag_(false),
121  sizeScale_(1.0)
122 {}
123 
124 
125 //-----------------------------------------------------------------------------
126 // Function : SolverState::InitializeHomotopyBlockSize
127 // Purpose : constructor
128 // Special Notes :
129 // Scope : public
130 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
131 // Creation Date : 08/25/03
132 //-----------------------------------------------------------------------------
134 {
135  gainScale_.resize(numBlocks, 1.0);
136 }
137 
138 
139 //-----------------------------------------------------------------------------
140 // Function : SolverState::operator<<
141 // Purpose : "<<" operator
142 // Special Notes :
143 // Scope : public
144 // Creator : Eric R. Keiter, SNL, Electrical and Microsystems Modeling
145 // Creation Date : 10/05/2005
146 //-----------------------------------------------------------------------------
147 std::ostream& operator<<(std::ostream & os, const SolverState & ss)
148 {
149 
150  os << section_divider << std::endl;
151  os << " Device Package Solver State:" << std::endl;
152 
153  os << " pdt = " << ss.pdt_ << std::endl;
154  os << " currTimeStep = " << ss.currTimeStep_ << std::endl;
155  os << " lastTimeStep = " << ss.lastTimeStep_ << std::endl;
156  os << " currTime = " << ss.currTime_ << std::endl;
157  os << " finalTime = " << ss.finalTime_ << std::endl;
158  os << " startingTimeStep = " << ss.startingTimeStep_ << std::endl;
159  os << " bpTol = " << ss.bpTol_ << std::endl;
160 
161  os << " acceptedTime = " << ss.acceptedTime_ << std::endl;
162  os << " currentOrder = " << ss.currentOrder_ << std::endl;
163  os << " usedOrder = " << ss.usedOrder_ << std::endl;
164 
165  os << " mpdeOnFlag = ";
166  if (ss.mpdeOnFlag_)
167  {
168  os << "yes" << std::endl;
169  os << " currFastTime = " << ss.currFastTime_ << std::endl;
170  os << " blockAnalysisFlag = " << ss.blockAnalysisFlag_ << std::endl;
171  }
172  else
173  {
174  os << "no" << std::endl;
175  }
176 
177  os << " timeStepNumber = " << ss.timeStepNumber_ << std::endl;
178  os << " ltraTimeIndex = " << ss.ltraTimeIndex_ << std::endl;
179  os << " ltraTimeStepHistorySize = " << ss.ltraTimeHistorySize_ << std::endl;
180  os << " ltraDoCompact = " << ss.ltraDoCompact_ << std::endl;
181  os << " newtonIter = " << ss.newtonIter << std::endl;
182  os << " continuationStepNumber = " << ss.continuationStepNumber << std::endl;
183  os << " firstContinuationParam = ";
184  if (ss.firstContinuationParam) os << "yes" << std::endl;
185  else os << "no" << std::endl;
186 
187  os << " firstSolveComplete = ";
188  if (ss.firstSolveComplete) os << "yes" << std::endl;
189  else os << "no" << std::endl;
190 
191  os << " initTranFlag = " << (ss.initTranFlag_ ? "yes" : "no") << std::endl;
192  os << " beginIntegrationFlag = " << (ss.beginIntegrationFlag_ ? "yes" : "no") << std::endl;
193 
194  os << " dcopFlag = ";
195  if (ss.dcopFlag) os << "yes" << std::endl;
196  else os << "no" << std::endl;
197 
198  os << " inputOPFlag = ";
199  if (ss.inputOPFlag) os << "yes" << std::endl;
200  else os << "no" << std::endl;
201 
202  os << " transientFlag = ";
203  if (ss.transientFlag) os << "yes" << std::endl;
204  else os << "no" << std::endl;
205 
206  os << " dcsweepFlag = ";
207  if (ss.dcsweepFlag) os << "yes" << std::endl;
208  else os << "no" << std::endl;
209 
210  os << " tranopFlag = ";
211  if (ss.tranopFlag) os << "yes" << std::endl;
212  else os << "no" << std::endl;
213 
214  os << " acopFlag = ";
215  if (ss.acopFlag) os << "yes" << std::endl;
216  else os << "no" << std::endl;
217 
218  os << " isPDESystem_ = ";
219  if (ss.isPDESystem_) os << "yes" << std::endl;
220  else os << "no" << std::endl;
221 
222  os << " locaEnabledFlag = ";
223  if (ss.locaEnabledFlag) os << "yes" << std::endl;
224  else os << "no" << std::endl;
225 
226  os << " initJctFlag = " << (ss.initJctFlag_ ? "yes" : "no") << std::endl;
227  os << " initFixFlag = ";
228  if (ss.initFixFlag) os << "yes" << std::endl;
229  else os << "no" << std::endl;
230 
231  os << " sweepSourceResetFlag = ";
232  if (ss.sweepSourceResetFlag) os << "yes" << std::endl;
233  else os << "no" << std::endl;
234 
235  os << " debugTimeFlag = ";
236  if (ss.debugTimeFlag) os << "yes" << std::endl;
237  else os << "no" << std::endl;
238 
239  os << section_divider << std::endl;
240  os << std::endl;
241 
242  return os;
243 }
244 
245 //-----------------------------------------------------------------------------
246 // Function : setupSolverInfo
247 //
248 // Purpose :
249 //
250 // Special Notes : This function gets called a lot, and this can be kind of
251 // confusing. Probably, this function is being used to handle
252 // too many different types of data.
253 //
254 // For example, it gets called at the beginning
255 // of the "updateSources" function. Why? Because the sources
256 // need to know which step we are at, and/or what the current
257 // time is, to do their update properly.
258 //
259 // However, at the moment, updateSources also provides
260 // information that setupSolverInfo needs. Only after the
261 // sources have been updated do we know if a sweep source has
262 // been reset. And, the sweepSourceResetFlag is used by
263 // setupSolverInfo, to set up the initJctFlag boolean.
264 // So it will need to be called at least one more
265 // time, at the beginning of the RHS load. (which it is).
266 //
267 // Anyway, any of the functions that are called from the
268 // outside, such as: updateSources, loadRHSVector,
269 // loadJacobianMatrix, etc.... have no way of knowing when,
270 // w.r.t. the solvers they are being called. The only way
271 // to do this properly is to have each of them request
272 // the current solver state, before they go to do their
273 // work. Hence, this function is called a lot.
274 //
275 // Unfortunately, this has led to a somewhat sloppy and
276 // confusing interface between the solvers and the
277 // device package. I wanted to avoid having a lot of
278 // function arguments being passed around for each of
279 // these functions, in part because the calling code
280 // (NLS) doesn't know everything. - NLS knows about the newton
281 // step, but it doesn't know the time step, for example.
282 //
283 // At some point I hope to refactor this.
284 //
285 // Scope : private
286 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
287 // Creation Date : 7/30/01
288 //-----------------------------------------------------------------------------
289 bool
291  SolverState & solver_state,
292  const Analysis::AnalysisManager & analysis_manager,
293  bool all_devices_converged,
294  const DeviceOptions & device_options,
295  const Nonlinear::NonLinInfo & nonlinear_info)
296 {
297  bool bsuccess = true;
298 
299  // Time integrator information
300  solver_state.pdt_ = analysis_manager.getWorkingIntegrationMethod().partialTimeDeriv(); // system_state.pdt;
301  solver_state.currentOrder_ = analysis_manager.getWorkingIntegrationMethod().getOrder(); // system_state.currentOrder;
302  solver_state.usedOrder_ = analysis_manager.getWorkingIntegrationMethod().getUsedOrder(); // system_state.usedOrder;
303 
304  // Time step error control information
305  solver_state.currTimeStep_ = analysis_manager.getStepErrorControl().currentTimeStep; // system_state.nextTimeStep;
306  solver_state.lastTimeStep_ = analysis_manager.getStepErrorControl().lastTimeStep; // system_state.currTimeStep;
307  solver_state.currTime_ = analysis_manager.getStepErrorControl().nextTime; // system_state.nextTime;
308  solver_state.finalTime_ = analysis_manager.getStepErrorControl().finalTime; // system_state.finalTime;
309  solver_state.startingTimeStep_ = analysis_manager.getStepErrorControl().startingTimeStep; // system_state.startingTimeStep;
310  solver_state.bpTol_ = analysis_manager.getStepErrorControl().getBreakPointLess().tolerance_; // system_state.bpTol;
311 
312  if (solver_state.mpdeOnFlag_)
313  {
314  solver_state.dcopFlag = false;
315  solver_state.initTranFlag_ = true;
316  solver_state.beginIntegrationFlag_ = true;
317  }
318  else
319  {
320  solver_state.dcopFlag = analysis_manager.getAnalysisObject().getDCOPFlag(); // system_state.dcopFlag;
321  solver_state.initTranFlag_ = analysis_manager.getInitTranFlag(); // system_state.initTranFlag;
322  solver_state.beginIntegrationFlag_ = analysis_manager.getBeginningIntegrationFlag(); // system_state.beginIntegrationFlag;
323  }
324 
325  solver_state.inputOPFlag = analysis_manager.getAnalysisObject().getInputOPFlag(); // system_state.inputOPFlag;
326  solver_state.acopFlag = analysis_manager.getACOPFlag(); // system_state.acopFlag;
327  solver_state.tranopFlag = analysis_manager.getTranOPFlag(); // system_state.tranopFlag;
328  solver_state.transientFlag = analysis_manager.getTransientFlag(); // system_state.transientFlag;
329  solver_state.dcsweepFlag = analysis_manager.getDCSweepFlag(); // system_state.dcsweepFlag;
330  solver_state.sweepSourceResetFlag = analysis_manager.getSweepSourceResetFlag(); // system_state.sweepSourceResetFlag;
331 
332  solver_state.timeStepNumber_ = analysis_manager.getStepNumber(); // system_state.timeStepNumber;
333 
334  solver_state.doubleDCOPStep = analysis_manager.getDoubleDCOPStep(); // system_state.doubleDCOPStep;
335  solver_state.doubleDCOPEnabled = analysis_manager.getDoubleDCOPEnabled(); // system_state.doubleDCOPEnabled;
336 
337  // Nonlinear solver info:
338  solver_state.newtonIter = nonlinear_info.newtonIter;
339  solver_state.twoLevelNewtonCouplingMode = nonlinear_info.twoLevelNewtonCouplingMode;
340 
341  // Get LOCA-specific information. Note - in general, LOCA is only used for
342  // steady state calculations - there isn't much point in using it
343  // for transient. A common case is one where LOCA is used for the
344  // tranOP, but not for the subsequent transient phase. The
345  // locaEnabledFlag should switch from true to false under
346  // that scenario, once the transient phase starts.
347  solver_state.locaEnabledFlag = nonlinear_info.locaFlag;
348  if (solver_state.locaEnabledFlag) // if no LOCA, these are 0, true, respectively.
349  {
350  solver_state.continuationStepNumber = nonlinear_info.continuationStep;
351  solver_state.firstContinuationParam = nonlinear_info.firstContinuationParam;
352  solver_state.firstSolveComplete = nonlinear_info.firstSolveComplete;
353  }
354  // Done with LOCA information.
355 
356  // Setup the initialize junctions flag.
357  // The initJct flag should only be true if we are at the first Newton step of
358  // an initial point in the calculation. Examples include:
359  // - 1st Newton step of the DCOP initialization for transient (tranOp)
360  // - 1st Newton step of first DC sweep step.
361  // - 1st Newton step of a sweep that has been reset. That typically
362  // happens if the sweep is multi-dimensional, and the inner loop has
363  // cycled back to the beginning again.
364  //
365  bool resetFlag = (solver_state.timeStepNumber_ == 0) || (solver_state.sweepSourceResetFlag);
366 
367  // Do this if using LOCA for a DC or tranop calculation.
368  if (solver_state.dcopFlag && solver_state.locaEnabledFlag)
369  {
370  resetFlag = resetFlag && (solver_state.continuationStepNumber==0);
371  }
372 
373  solver_state.initJctFlag_ = ((solver_state.dcopFlag) &&
374  (solver_state.newtonIter==0) &&
375  solver_state.firstContinuationParam &&
376  !solver_state.firstSolveComplete && resetFlag);
377 
378  // One final check. See if the "external state" has been set. If so,
379  // check to see if it has the initJctFlag set. If not, then we probably
380  // shouldn't either. The external state comes from a higher up level
381  // in a multi-level newton solve.
382  //
383  // This should be made more detailed later.
384  if (solver_state.externalStateFlag_)
385  {
386  if (solver_state.newtonIter==0 && solver_state.dcopFlag)
387  {
388  solver_state.initJctFlag_ = solver_state.externalInitJctFlag_;
389  }
390  }
391 
392 
393  // initFixFlag: try to mimic "MODEINITFIX" of SPICE. This is set if:
394  // DCOP or TranOP
395  // Not first iteration
396  // Any device not converged
397  solver_state.initFixFlag =
398  solver_state.dcopFlag
399  && !all_devices_converged
400  && (solver_state.newtonIter != 0)
401  && solver_state.firstContinuationParam
402  && !solver_state.firstSolveComplete
403  && resetFlag;
404 
405  if (solver_state.dcopFlag)
406  {
407  solver_state.ltraTimeIndex_ = 0;
408  solver_state.ltraTimeHistorySize_ = 10;
409  solver_state.ltraTimePoints_.resize(solver_state.ltraTimeHistorySize_);
410  }
411 
412  // The first DCOP step of a "double DCOP" simulation is a special case,
413  // in which the nonlinear poisson is solved in place of drift-diffusion
414  // equations for the PDE devices. For this initialization problem, the
415  // circuit subproblem should not be included.
416  if (solver_state.doubleDCOPEnabled && solver_state.dcopFlag && (solver_state.doubleDCOPStep == 0))
417  {
419  }
420 
421  if (DEBUG_DEVICE) {
422  if (isActive(Diag::DEVICE_SOLVER_STATE) && solver_state.debugTimeFlag)
423  {
424  dout() << solver_state;
425  }
426 
427  solver_state.debugTimeFlag =
428  (solver_state.currTime_ >= device_options.debugMinTime
429  && solver_state.currTime_ <= device_options.debugMaxTime)
430  && (solver_state.timeStepNumber_ >= device_options.debugMinTimestep
431  && solver_state.timeStepNumber_ <= device_options.debugMaxTimestep);
432  }
433 
434  return bsuccess;
435 }
436 
437 } // namespace Device
438 } // namespace Xyce
439 
double pdt_
Previous delta time alpha/dt (Many devices)
double currTimeStep_
Region, BJT, Digital, ThermalResistor, ROM, Charon, Others.
bool initTranFlag_
RxnSet, TRA, LTRA, ACC, MOSFET, BJT, true only on very first(t=0) time step.
Pure virtual class to augment a linear system.
void initializeHomotopyBlockSize(int numBlocks)
double lastTimeStep_
BJT, Others.
std::vector< double > gainScale_
MOSFET Devices, ArtificialParameters.
double startingTimeStep_
SourceData devices.
size_t ltraTimeIndex_
LTRA, DeviceMgr::acceptStep()
const AnalysisBase & getAnalysisObject() const
Nonlinear::TwoLevelNewtonMode twoLevelNewtonCouplingMode
const Util::BreakPointLess & getBreakPointLess() const
double finalTime_
Analysis final time, SourceData devices.
TimeIntg::StepErrorControl & getStepErrorControl()
bool blockAnalysisFlag_
Source devices, BJTDW, This indicates an MPDE/HB run. This is true during both IC and MPDE/HB phase...
double bpTol_
Break point tolerance, SourceData devices, Neuron devices.
bool beginIntegrationFlag_
BJT, true if 1st time step out of breakpoint (incl. t=0)
bool setupSolverInfo(SolverState &solver_state, const Analysis::AnalysisManager &analysis_manager, bool all_devices_converged, const DeviceOptions &device_options, const Nonlinear::NonLinInfo &nonlinear_info)
virtual bool getDCOPFlag() const =0
int timeStepNumber_
Memristor, LTRA, TRA, testing if debug or jacobian for testing.
bool mpdeOnFlag_
MPDE phase of MPDE problem (ie not initial condition)
TwoLevelNewtonMode twoLevelNewtonCouplingMode
size_t ltraTimeHistorySize_
LTRA, this looks like c code array sizing.
std::vector< double > ltraTimePoints_
LTRA.
TimeIntg::WorkingIntegrationMethod & getWorkingIntegrationMethod()
bool isPDESystem_
true if circuit includes a PDE device
double acceptedTime_
DeviceMgr::acceptStep(), DAC (for habanero)
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
bool initJctFlag_
true if on the first newton step of the first dcop solve of the first .STEP iteration. BJT, JFET, Diode, MOSFET, SW, Extern
double currFastTime_
Source devices,.
std::ostream & operator<<(std::ostream &os, const Configuration &configuration)
Definition: N_DEV_Dump.C:134