Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_ANP_DCSweep.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-2014 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_ANP_DCSweep.C,v $
27 // Purpose : DC Sweep class analysis functions.
28 // Special Notes :
29 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
30 // Creation Date : 01/24/08
31 //
32 // Revision Information:
33 // ---------------------
34 // Revision Number: $Revision: 1.51 $
35 // Revision Date : $Date: 2014/02/24 23:49:12 $
36 // Current Owner : $Author: tvrusso $
37 //-----------------------------------------------------------------------------
38 #include <Xyce_config.h>
39 
40 // ---------- Standard Includes ----------
41 #include <iostream>
42 
43 // ---------- Xyce Includes ----------
44 #include <N_ANP_AnalysisManager.h>
45 #include <N_ANP_OutputMgrAdapter.h>
46 #include <N_ANP_DCSweep.h>
47 #include <N_ANP_HB.h>
48 
49 #include <N_TIA_DataStore.h>
50 #include <N_LOA_Loader.h>
51 #include <N_MPDE_Manager.h>
52 #include <N_IO_CmdParse.h>
53 
54 namespace Xyce {
55 namespace Analysis {
56 
57 //-----------------------------------------------------------------------------
58 // Function : DCSweep::setAnalysisParams
59 // Purpose :
60 // Special Notes :
61 // Scope : public
62 // Creator : Eric R. Keiter, SNL
63 // Creation Date : 6/22/10
64 //-----------------------------------------------------------------------------
65 bool DCSweep::setAnalysisParams(const N_UTL_OptionBlock & paramsBlock)
66 {
67 #ifdef Xyce_DEBUG_ANALYSIS
68  if (tiaParams.debugLevel > 0)
69  {
70  Xyce::dout() << std::endl << section_divider << std::endl;
71  Xyce::dout() << "DCSweep::setDCAnalysisParams" << std::endl;
72  }
73 #endif
74 
75  std::list<N_UTL_Param>::const_iterator it_tp;
76  std::list<N_UTL_Param>::const_iterator it_param;
77  std::list<N_UTL_Param>::const_iterator it_type;
78  std::list<N_UTL_Param>::const_iterator first = paramsBlock.getParams().begin();
79  std::list<N_UTL_Param>::const_iterator last = paramsBlock.getParams().end();
80 
81  std::string msg;
82 
83  SweepParam sp;
84 #ifdef Xyce_DEBUG_ANALYSIS
85  if (tiaParams.debugLevel > 0)
86  {
87  for (it_tp = first; it_tp != last; ++it_tp)
88  {
89  Xyce::dout() << it_tp->uTag() ;
90  Xyce::dout() << "\t";
91  if (it_tp->uTag() == "PARAM" || it_tp->uTag() == "TYPE")
92  {
93  Xyce::dout() << it_tp->stringValue();
94  }
95  else
96  {
97  Xyce::dout() << it_tp->getImmutableValue<double>();
98  }
99  Xyce::dout() << std::endl;
100  }
101  }
102 #endif
103 
104  for (it_tp = first; it_tp != last; ++it_tp)
105  {
106  if (it_tp->uTag() == "TYPE")
107  {
108  it_type = it_tp;
109  sp.type = it_tp->stringValue();
110  }
111 
112  if (it_tp->uTag() == "PARAM")
113  {
114  it_param = it_tp;
115  sp.name = it_tp->stringValue();
116  }
117  }
118 
119  it_tp = it_param;
120  ++it_tp;
121  if (sp.type == "LIN") // default
122  {
123  sp.startVal = it_tp->getImmutableValue<double>(); ++it_tp;
124  sp.stopVal = it_tp->getImmutableValue<double>(); ++it_tp;
125  sp.stepVal = it_tp->getImmutableValue<double>(); ++it_tp;
126  }
127  else if (sp.type == "DEC" || sp.type == "OCT")
128  {
129  sp.startVal = it_tp->getImmutableValue<double>(); ++it_tp;
130  sp.stopVal = it_tp->getImmutableValue<double>(); ++it_tp;
131  sp.numSteps = it_tp->getImmutableValue<int>(); ++it_tp;
132  }
133  else if (sp.type == "LIST")
134  {
135  for (;it_tp!=last;++it_tp)
136  {
137  sp.valList.push_back(it_tp->getImmutableValue<double>());
138  }
139  }
140  else
141  {
142  msg = "DCSweep::setDCParams: ";
143  msg += " unsupported DC type\n";
144  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
145  }
146 
147  // need to do a bunch of stuff to initialize the DC loop.
148  (*dcParamVec_).push_back(sp);
149 
150  // set analysis type
151  //analysis = ANP_MODE_DC_SWEEP;
152 
153  // good idea to put this here, but this code isn't touched in
154  // no .dc runs and check_outputs will expcect the param vec
155  // to exist (but be empty) even if this isn't a .dc run
156  //outputMgrAdapterRCPtr_->setDCParamVec( & dcParamVec_ );
157 
158  //analysisParamsRegistered = true;
159 
160  return true;
161 }
162 
163 //-----------------------------------------------------------------------------
164 // Function : DCSweep::outputFailureStats
165 // Purpose :
166 // Special Notes :
167 // Scope : public
168 // Creator : Eric Keiter, SNL
169 // Creation Date : 6/21/2010
170 //-----------------------------------------------------------------------------
171 bool DCSweep::outputFailureStats(std::ostream &os)
172 {
173  if (!(dcSweepFailures_.empty()))
174  {
175  os << "\tFailed DC sweep steps:\t\t" << std::endl;
176 
177  for (std::list<int>::iterator iter = dcSweepFailures_.begin(); iter != dcSweepFailures_.end(); ++iter)
178  {
179  os << "\t\tDC Step # " << *iter << std::endl;
180  }
181  }
182  return true;
183 }
184 
185 //-----------------------------------------------------------------------------
186 // Function : DCSweep::run()
187 // Purpose : This is the main controlling loop for DC sweep analysis.
188 // This loop calls a series of operating point calculations
189 // (ie calculations in which there is no time integration,
190 // and the time integration method is always set to "none").
191 // Special Notes :
192 // Scope : public
193 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
194 // Creation Date : 1/28/08
195 //-----------------------------------------------------------------------------
197 {
198  bool bsuccess = true;
199  bsuccess = init();
200  bsuccess &= loopProcess();
201  bsuccess &= finish();
202  return bsuccess;
203 }
204 
205 //-----------------------------------------------------------------------------
206 // Function : DCSweep::init()
207 // Purpose :
208 // Special Notes :
209 // Scope : public
210 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
211 // Creation Date : 1/28/08
212 //-----------------------------------------------------------------------------
214 {
215  bool bsuccess = true;
216 
217  if (sensFlag_)
218  {
219  nlsMgrRCPtr_->enableSensitivity();
220  }
221 
222  // set up the various sweep variables
223  // the following should only happen once, but must be isolated to
224  // prevent a step loop outside of this dc sweep from causing to
225  // occur more often
226  if( !dcLoopInitialized_ )
227  {
228 #ifdef Xyce_DEBUG_ANALYSIS
229  if (tiaParams.debugLevel > 0)
230  {
231  Xyce::dout() << std::endl << std::endl
232  << Xyce::subsection_divider << std::endl
233  << "DCSweep::run()" << std::endl;
234  }
235 #endif
236 
238 
239  outputMgrAdapterRCPtr_->setDCAnalysisMaxSteps( dcLoopSize_ );
240 
241  dcLoopInitialized_ = true;
242  }
243 
244  anaManagerRCPtr_->currentMode_ = 2;
245 
246  //setup for operating pt calculation
248  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
249 
250  stepNumber = 0;
251  doubleDCOPFlag_ = loaderRCPtr_->getDoubleDCOPFlag ();
253 
255 
256  return bsuccess;
257 }
258 
259 //-----------------------------------------------------------------------------
260 // Function : DCSweep::initializeSolution()
261 // Purpose : Move solution-initialization steps to separate routine so
262 // the process may be repeated cleanly when necessary.
263 // Special Notes :
264 // Scope : public
265 // Creator : Tom Russo, SNL, Electrical and Microsystem Modeling
266 // Creation Date : 2/17/2010
267 //-----------------------------------------------------------------------------
269 {
270  // set initial guess, if there is one to be set.
271  // this setInitialGuess call is to up an initial guess in the
272  // devices that have them (usually PDE devices). This is different than
273  // the "intializeProblem" call, which sets IC's. (initial conditions are
274  // different than initial guesses.
275  loaderRCPtr_->setInitialGuess (anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr);
276 
277  // If available, set initial solution (.IC, .NODESET, etc).
278  inputOPFlag_ =
279  outputMgrAdapterRCPtr_->setupInitialConditions( *(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr),
280  *(anaManagerRCPtr_->getTIADataStore()->flagSolutionPtr));
281 
282  // Set a constant history for operating point calculation
283  anaManagerRCPtr_->getTIADataStore()->setConstantHistory();
284  anaManagerRCPtr_->getTIADataStore()->computeDividedDifferences();
285  wimRCPtr_->obtainCorrectorDeriv();
286 }
287 
288 //-----------------------------------------------------------------------------
289 // Function : DCSweep::loopProcess()
290 // Purpose :
291 // Special Notes :
292 // Scope : public
293 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
294 // Creation Date : 1/28/08
295 //-----------------------------------------------------------------------------
297 {
298  bool bsuccess = true;
299  // DC Sweep loop:
300 
301  int currentStep = 0;
302  int finalStep = dcLoopSize_;
303  while (currentStep < finalStep)
304  {
305  outputMgrAdapterRCPtr_->setDCAnalysisStepNumber( currentStep );
306 
307 #ifdef Xyce_VERBOSE_TIME
308  printStepHeader(Xyce::lout());
309  secRCPtr_->outputTimeInfo(Xyce::lout());
310 #endif
311 
312  updateSweepParams_(currentStep, *dcParamVec_);
313  if (currentStep != 0 &&(anaManagerRCPtr_->getSweepSourceResetFlag()))
314  {
315  anaManagerRCPtr_->getTIADataStore()->setZeroHistory();
317  }
318 
319  // Perform the step:
320  takeStep_ ();
321 
322  // Set things up for the next time step, based on if this one was
323  // successful.
324  if (secRCPtr_->stepAttemptStatus)
325  {
327  }
328  else // stepAttemptStatus (ie do this if the step FAILED)
329  {
331  }
332 
333  // we don't really control the loop counter here. processSuccessfulStep
334  // and processFailedStep do that work. This needs to be cleaned up. RLS
335  currentStep = stepNumber;
336  } // end of sweep loop
337 
338  return bsuccess;
339 }
340 
341 //-----------------------------------------------------------------------------
342 // Function : DCSweep::processSuccessfulStep()
343 //
344 // Purpose : Used by both function dcSweepLoop and 2-level solve
345 // function calls to process successful DC steps.
346 // Special Notes :
347 // Scope : public
348 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
349 // Creation Date : 1/28/08
350 //-----------------------------------------------------------------------------
352 {
353  bool bsuccess = true;
354  loaderRCPtr_->stepSuccess(anaManagerRCPtr_->currentMode_);
355 
356  // This output call is for device-specific output, such as .OP,
357  // or internal plot output from PDE(TCAD) devices.
358  loaderRCPtr_->output();
359 
360  if (sensFlag_ && !firstDoubleDCOPStep_() )
361  {
362  nlsMgrRCPtr_->calcSensitivity(objectiveVec_,
364  }
365 
366  // Do some statistics, as long as this isn't the first "double"
367  // DCOP step. (that one doesn't count)
368  if ( !firstDoubleDCOPStep_() )
369  {
370  stepNumber += 1;
373  }
374 
375  // update the data arrays, output:
376  anaManagerRCPtr_->getTIADataStore()->updateSolDataArrays();
377 
378 #ifdef Xyce_DEBUG_ANALYSIS
379 #ifdef Xyce_DEBUG_TIME
380  if (tiaParams.debugLevel > 1)
381  anaManagerRCPtr_->getTIADataStore()->outputSolDataArrays(Xyce::dout());
382 #endif
383 #endif
384 
385  dcSweepOutput();
386 
387  // now that output has been called, update the doubleDCOP step
388  // if neccessary. (pde-only)
390 
391  return bsuccess;
392 }
393 
394 //-----------------------------------------------------------------------------
395 // Function : DCSweep::processFailedStep()
396 // Purpose :
397 // Special Notes :
398 // Scope : public
399 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
400 // Creation Date : 1/28/08
401 //-----------------------------------------------------------------------------
403 {
404  loaderRCPtr_->stepFailure (anaManagerRCPtr_->currentMode_);
405 
406  stepNumber += 1;
407  dcSweepFailures_.push_back(stepNumber);
409  secRCPtr_->numberSuccessiveFailures += 1;
410 
411  return true;
412 }
413 
414 //-----------------------------------------------------------------------------
415 // Function : DCSweep::finish()
416 // Purpose :
417 // Special Notes :
418 // Scope : public
419 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
420 // Creation Date : 1/28/08
421 //-----------------------------------------------------------------------------
423 {
424  bool bsuccess = true;
425 
426 #ifdef Xyce_DEBUG_ANALYSIS
427  Xyce::dout() << "Calling DCSweep::finish() outputs!" << std::endl;
428 #endif
429 
430  outputMgrAdapterRCPtr_->finishOutput();
431  if (!(dcSweepFailures_.empty()))
432  {
433  bsuccess = false;
434  }
435  return bsuccess;
436 }
437 
438 
439 //-----------------------------------------------------------------------------
440 // Function : DCSweep::handlePredictor
441 // Purpose :
442 // Special Notes :
443 // Scope : private
444 // Creator : Eric Keiter, SNL
445 // Creation Date : 06/24/2013
446 //-----------------------------------------------------------------------------
448 {
449  anaManagerRCPtr_->getTIADataStore()->setErrorWtVector();
450  wimRCPtr_->obtainPredictor();
451  wimRCPtr_->obtainPredictorDeriv();
452 
453  // In case this is the upper level of a 2-level sim, tell the
454  // inner solve to do its prediction:
455  loaderRCPtr_->startTimeStep ();
456 
457  return true;
458 }
459 
460 //-----------------------------------------------------------------------------
461 // Function : DCSweep::takeStep_
462 // Purpose : Take a DC Sweep integration step.
463 // Special Notes :
464 // Scope : private
465 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
466 // Creation Date : 01/24/08
467 //-----------------------------------------------------------------------------
469 {
470  handlePredictor();
471  loaderRCPtr_->updateSources();
472  secRCPtr_->newtonConvergenceStatus = nlsMgrRCPtr_->solve();
473  anaManagerRCPtr_->getTIADataStore()->stepLinearCombo ();
475  secRCPtr_->evaluateStepError ();
476 
477  return;
478 }
479 
480 //-----------------------------------------------------------------------------
481 // Function : DCSweep::twoLevelStep
482 //
483 // Purpose : Used by 2-level Newton solves to execute a single DC sweep
484 // step.
485 //
486 // Special Notes : This is mostly what happens on the inner loop of
487 // dcSweepLoop, except that DC parameters are not updated,
488 // and success/failure of the step is not determined.
489 //
490 // Scope : public
491 // Creator : Eric Keiter, SNL
492 // Creation Date : 03/10/06
493 //-----------------------------------------------------------------------------
495 {
496  loaderRCPtr_->updateSources();
497  secRCPtr_->newtonConvergenceStatus = nlsMgrRCPtr_->solve();
498  anaManagerRCPtr_->getTIADataStore()->stepLinearCombo ();
500  secRCPtr_->evaluateStepError ();
501 
502  return secRCPtr_->stepAttemptStatus;
503 }
504 
505 //-----------------------------------------------------------------------------
506 // Function : DCSweep::dcSweepOutput
507 // Purpose :
508 // Special Notes :
509 // Scope : public
510 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
511 // Creation Date : 1/31/08
512 //-----------------------------------------------------------------------------
514 {
515  // if this is an MPDE run, don't output anything.
516  bool mpdeFlag = anaManagerRCPtr_->getMPDEFlag();
517  bool hbFlag = anaManagerRCPtr_->getHBFlag();
518 
519  // Make sure this isn't the NLP step of a PDE DCOP.
520  if ( !mpdeFlag )
521  {
522  if (!firstDoubleDCOPStep_())
523  {
524  // conventional .PRINT output
525  outputMgrAdapterRCPtr_->dcOutput(
526  stepNumber,
527  *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr),
528  *(anaManagerRCPtr_->getTIADataStore()->currStatePtr),
529  *(anaManagerRCPtr_->getTIADataStore()->currStorePtr),
532 
533  // output for DCOP restart
534  outputMgrAdapterRCPtr_->outputDCOP( *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr) );
535  }
536  }
537  else
538  {
539  if ( hbFlag )
540  {
541  std::vector<double> timePoints, freqPoints;
542  Teuchos::RefCountPtr<N_LAS_BlockVector> timeDomainSolnVec;
543  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainSolnVecReal;
544  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainSolnVecImaginary;
545  Teuchos::RefCountPtr<N_LAS_BlockVector> timeDomainStoreVec;
546  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainStoreVecReal;
547  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainStoreVecImaginary;
548 
549 
550  Teuchos::RCP<const AnalysisBase> analysisObject
551  = anaManagerRCPtr_->getAnalysisObject();
552 
553  Teuchos::rcp_dynamic_cast<const HB>( analysisObject )->prepareHBOutput(
554  *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr),
555  timePoints,
556  freqPoints,
557  timeDomainSolnVec,
558  freqDomainSolnVecReal,
559  freqDomainSolnVecImaginary,
560  timeDomainStoreVec,
561  freqDomainStoreVecReal,
562  freqDomainStoreVecImaginary
563  );
564 
565  outputMgrAdapterRCPtr_->outputHB(
566  timePoints,
567  freqPoints,
568  *timeDomainSolnVec,
569  *freqDomainSolnVecReal,
570  *freqDomainSolnVecImaginary,
571  *timeDomainStoreVec,
572  *freqDomainStoreVecReal,
573  *freqDomainStoreVecImaginary
574  );
575 
576  }
577  }
578 }
579 
580 //-----------------------------------------------------------------------------
581 // Function : DCSweep::printStepHeader()
582 // Purpose : Prints out time step information.
583 // Special Notes :
584 // Scope : public
585 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
586 // Creation Date : 6/26/00
587 //-----------------------------------------------------------------------------
588 void DCSweep::printStepHeader(std::ostream &os)
589 {
590 #ifdef Xyce_VERBOSE_TIME
591  lout() << std::endl << std::endl
592  << "***** "<< (DEBUG_ANALYSIS ? commandLine_.getArgumentValue("netlist") : "") << " Start of DCOP STEP # " << stepNumber+1
593  << std::endl << std::endl;
594 #endif
595 }
596 
597 //-----------------------------------------------------------------------------
598 // Function : DCSweep::printLoopInfo
599 // Purpose :
600 // Scope : public
601 // Creator : Eric Keiter
602 // Creation Date : 12/14/2010
603 //-----------------------------------------------------------------------------
604 bool DCSweep::printLoopInfo(int start, int finish)
605 {
606  bool bsuccess = AnalysisBase::printLoopInfo(start, finish);
607  if (start == 0 && finish == 0)
608  {
609  outputFailureStats(Xyce::lout());
610  }
611  return bsuccess;
612 }
613 
614 } // namespace Analysis
615 } // namespace Xyce