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.63.2.1 $
35 // Revision Date : $Date: 2014/08/26 22:31:06 $
36 // Current Owner : $Author: dgbaur $
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_SweepParam.h>
48 #include <N_ANP_HB.h>
49 
50 #include <N_TIA_DataStore.h>
51 #include <N_TIA_StepErrorControl.h>
53 #include <N_LOA_Loader.h>
54 #include <N_MPDE_Manager.h>
55 #include <N_IO_CmdParse.h>
56 
57 #include <Teuchos_RefCountPtr.hpp>
58 using Teuchos::RefCountPtr;
59 using Teuchos::rcp;
60 
61 namespace Xyce {
62 namespace Analysis {
63 
65  : AnalysisBase(analysis_manager),
66  dcLoopInitialized_(false),
67  dcLoopSize_(0)
68 {}
69 
71 {}
72 
73 //-----------------------------------------------------------------------------
74 // Function : DCSweep::setAnalysisParams
75 // Purpose :
76 // Special Notes :
77 // Scope : public
78 // Creator : Eric R. Keiter, SNL
79 // Creation Date : 6/22/10
80 //-----------------------------------------------------------------------------
81 bool DCSweep::setAnalysisParams(const N_UTL_OptionBlock & paramsBlock)
82 {
83 #ifdef Xyce_DEBUG_ANALYSIS
84  if (tiaParams_.debugLevel > 0)
85  {
86  Xyce::dout() << std::endl << section_divider << std::endl;
87  Xyce::dout() << "DCSweep::setDCAnalysisParams" << std::endl;
88  }
89 #endif
90 
91  Util::ParameterList::const_iterator it_tp;
92  Util::ParameterList::const_iterator it_param;
93  Util::ParameterList::const_iterator it_type;
94  Util::ParameterList::const_iterator first = paramsBlock.getParams().begin();
95  Util::ParameterList::const_iterator last = paramsBlock.getParams().end();
96 
97  std::string msg;
98 
99  SweepParam sp;
100 #ifdef Xyce_DEBUG_ANALYSIS
101  if (tiaParams_.debugLevel > 0)
102  {
103  for (it_tp = first; it_tp != last; ++it_tp)
104  {
105  Xyce::dout() << it_tp->uTag() ;
106  Xyce::dout() << "\t";
107  if (it_tp->uTag() == "PARAM" || it_tp->uTag() == "TYPE")
108  {
109  Xyce::dout() << it_tp->stringValue();
110  }
111  else
112  {
113  Xyce::dout() << it_tp->getImmutableValue<double>();
114  }
115  Xyce::dout() << std::endl;
116  }
117  }
118 #endif
119 
120  for (it_tp = first; it_tp != last; ++it_tp)
121  {
122  if (it_tp->uTag() == "TYPE")
123  {
124  it_type = it_tp;
125  sp.type = it_tp->stringValue();
126  }
127 
128  if (it_tp->uTag() == "PARAM")
129  {
130  it_param = it_tp;
131  sp.name = it_tp->stringValue();
132  }
133  }
134 
135  it_tp = it_param;
136  ++it_tp;
137  if (sp.type == "LIN") // default
138  {
139  sp.startVal = it_tp->getImmutableValue<double>(); ++it_tp;
140  sp.stopVal = it_tp->getImmutableValue<double>(); ++it_tp;
141  sp.stepVal = it_tp->getImmutableValue<double>(); ++it_tp;
142  }
143  else if (sp.type == "DEC" || sp.type == "OCT")
144  {
145  sp.startVal = it_tp->getImmutableValue<double>(); ++it_tp;
146  sp.stopVal = it_tp->getImmutableValue<double>(); ++it_tp;
147  sp.numSteps = it_tp->getImmutableValue<int>(); ++it_tp;
148  }
149  else if (sp.type == "LIST")
150  {
151  for (;it_tp!=last;++it_tp)
152  {
153  sp.valList.push_back(it_tp->getImmutableValue<double>());
154  }
155  }
156  else
157  {
158  Report::DevelFatal().in("DCSweep::setDCParams") << "Unsupported DC type";
159  }
160 
161  // need to do a bunch of stuff to initialize the DC loop.
162  dcParamVec_.push_back(sp);
163 
164  return true;
165 }
166 
167 //-----------------------------------------------------------------------------
168 // Function : DCSweep::outputFailureStats
169 // Purpose :
170 // Special Notes :
171 // Scope : public
172 // Creator : Eric Keiter, SNL
173 // Creation Date : 6/21/2010
174 //-----------------------------------------------------------------------------
175 bool DCSweep::outputFailureStats(std::ostream &os)
176 {
177  if (!(dcSweepFailures_.empty()))
178  {
179  os << "\tFailed DC sweep steps:\t\t" << std::endl;
180 
181  for (std::list<int>::iterator iter = dcSweepFailures_.begin(); iter != dcSweepFailures_.end(); ++iter)
182  {
183  os << "\t\tDC Step # " << *iter << std::endl;
184  }
185  }
186  return true;
187 }
188 
189 //-----------------------------------------------------------------------------
190 // Function : DCSweep::getDCOPFlag
191 // Purpose :
192 // Special Notes :
193 // Scope : public
194 // Creator : Eric Keiter, SNL
195 // Creation Date : 3/24/2014
196 //-----------------------------------------------------------------------------
198 {
199  //return ((getIntegrationMethod())==TIAMethod_NONE);
200  return true;
201 }
202 
203 //-----------------------------------------------------------------------------
204 // Function : DCSweep::run()
205 // Purpose : This is the main controlling loop for DC sweep analysis.
206 // This loop calls a series of operating point calculations
207 // (ie calculations in which there is no time integration,
208 // and the time integration method is always set to "none").
209 // Special Notes :
210 // Scope : public
211 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
212 // Creation Date : 1/28/08
213 //-----------------------------------------------------------------------------
215 {
216  bool bsuccess = true;
217  bsuccess = init();
218  bsuccess &= loopProcess();
219  bsuccess &= finish();
220  return bsuccess;
221 }
222 
223 //-----------------------------------------------------------------------------
224 // Function : DCSweep::init()
225 // Purpose :
226 // Special Notes :
227 // Scope : public
228 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
229 // Creation Date : 1/28/08
230 //-----------------------------------------------------------------------------
232 {
233  bool bsuccess = true;
234 
235  if (sensFlag_)
236  {
238  }
239 
240  // set up the various sweep variables
241  // the following should only happen once, but must be isolated to
242  // prevent a step loop outside of this dc sweep from causing to
243  // occur more often
244  if( !dcLoopInitialized_ )
245  {
246 #ifdef Xyce_DEBUG_ANALYSIS
247  if (tiaParams_.debugLevel > 0)
248  {
249  Xyce::dout() << std::endl << std::endl
250  << Xyce::subsection_divider << std::endl
251  << "DCSweep::run()" << std::endl;
252  }
253 #endif
254 
256 
259 
260  dcLoopInitialized_ = true;
261  }
262 
264 
265  //setup for operating pt calculation
268 
269  stepNumber = 0;
270  doubleDCOPFlag_ = loader_.getDoubleDCOPFlag ();
272 
274 
275  return bsuccess;
276 }
277 
278 //-----------------------------------------------------------------------------
279 // Function : DCSweep::initializeSolution()
280 // Purpose : Move solution-initialization steps to separate routine so
281 // the process may be repeated cleanly when necessary.
282 // Special Notes :
283 // Scope : public
284 // Creator : Tom Russo, SNL, Electrical and Microsystem Modeling
285 // Creation Date : 2/17/2010
286 //-----------------------------------------------------------------------------
288 {
289  // set initial guess, if there is one to be set.
290  // this setInitialGuess call is to up an initial guess in the
291  // devices that have them (usually PDE devices). This is different than
292  // the "intializeProblem" call, which sets IC's. (initial conditions are
293  // different than initial guesses.
295 
296  // If available, set initial solution (.IC, .NODESET, etc).
297  inputOPFlag_ =
301 
302  // Set a constant history for operating point calculation
306 }
307 
308 //-----------------------------------------------------------------------------
309 // Function : DCSweep::loopProcess()
310 // Purpose :
311 // Special Notes :
312 // Scope : public
313 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
314 // Creation Date : 1/28/08
315 //-----------------------------------------------------------------------------
317 {
318  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::INITIALIZE, AnalysisEvent::DC));
319 
320  int currentStep = 0;
321  int finalStep = dcLoopSize_;
322  while (currentStep < finalStep)
323  {
325 
326 #ifdef Xyce_VERBOSE_TIME
327  printStepHeader(Xyce::lout());
328  stepErrorControl_->outputTimeInfo(Xyce::lout());
329 #endif
330 
331  updateSweepParams(loader_, analysisManager_, currentStep, dcParamVec_.begin(), dcParamVec_.end());
333 
334  if (currentStep != 0 && analysisManager_.getSweepSourceResetFlag())
335  {
338  }
339 
340  // Perform the step:
341  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::STEP_STARTED, AnalysisEvent::DC, 0.0, currentStep));
342 
343  takeStep_();
344 
345  // Set things up for the next time step, based on if this one was
346  // successful.
348  {
349  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::STEP_SUCCESSFUL, AnalysisEvent::DC, 0.0, currentStep));
351  }
352  else // stepAttemptStatus (ie do this if the step FAILED)
353  {
354  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::STEP_FAILED, AnalysisEvent::DC, 0.0, currentStep));
356  }
357 
358  // we don't really control the loop counter here. processSuccessfulStep
359  // and processFailedStep do that work. This needs to be cleaned up. RLS
360  currentStep = stepNumber;
361  } // end of sweep loop
362 
363  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::FINISH, AnalysisEvent::DC));
364 
365  return true;
366 }
367 
368 //-----------------------------------------------------------------------------
369 // Function : DCSweep::processSuccessfulStep()
370 //
371 // Purpose : Used by both function dcSweepLoop and 2-level solve
372 // function calls to process successful DC steps.
373 // Special Notes :
374 // Scope : public
375 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
376 // Creation Date : 1/28/08
377 //-----------------------------------------------------------------------------
379 {
380  bool bsuccess = true;
381  loader_.stepSuccess(analysisManager_.getCurrentMode());
382 
383  // This output call is for device-specific output, such as .OP,
384  // or internal plot output from PDE(TCAD) devices.
385  loader_.output();
386 
387  if (sensFlag_ && !firstDoubleDCOPStep_() )
388  {
391  }
392 
393  // Do some statistics, as long as this isn't the first "double"
394  // DCOP step. (that one doesn't count)
395  if ( !firstDoubleDCOPStep_() )
396  {
397  stepNumber += 1;
400  }
401 
402  // update the data arrays, output:
404 
405 #ifdef Xyce_DEBUG_ANALYSIS
406 #ifdef Xyce_DEBUG_TIME
407  if (tiaParams_.debugLevel > 1)
409 #endif
410 #endif
411 
412  dcSweepOutput();
413 
414  // now that output has been called, update the doubleDCOP step
415  // if neccessary. (pde-only)
417 
418  return bsuccess;
419 }
420 
421 //-----------------------------------------------------------------------------
422 // Function : DCSweep::processFailedStep()
423 // Purpose :
424 // Special Notes :
425 // Scope : public
426 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
427 // Creation Date : 1/28/08
428 //-----------------------------------------------------------------------------
430 {
431  loader_.stepFailure(analysisManager_.getCurrentMode());
432 
433  stepNumber += 1;
434  dcSweepFailures_.push_back(stepNumber);
437 
438  return true;
439 }
440 
441 //-----------------------------------------------------------------------------
442 // Function : DCSweep::finish()
443 // Purpose :
444 // Special Notes :
445 // Scope : public
446 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
447 // Creation Date : 1/28/08
448 //-----------------------------------------------------------------------------
450 {
451  bool bsuccess = true;
452 
453 #ifdef Xyce_DEBUG_ANALYSIS
454  Xyce::dout() << "Calling DCSweep::finish() outputs!" << std::endl;
455 #endif
456 
458  if (!(dcSweepFailures_.empty()))
459  {
460  bsuccess = false;
461  }
462  return bsuccess;
463 }
464 
465 
466 //-----------------------------------------------------------------------------
467 // Function : DCSweep::handlePredictor
468 // Purpose :
469 // Special Notes :
470 // Scope : private
471 // Creator : Eric Keiter, SNL
472 // Creation Date : 06/24/2013
473 //-----------------------------------------------------------------------------
475 {
479 
480  // In case this is the upper level of a 2-level sim, tell the
481  // inner solve to do its prediction:
482  loader_.startTimeStep ();
483 
484  return true;
485 }
486 
487 //-----------------------------------------------------------------------------
488 // Function : DCSweep::takeStep_
489 // Purpose : Take a DC Sweep integration step.
490 // Special Notes :
491 // Scope : private
492 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
493 // Creation Date : 01/24/08
494 //-----------------------------------------------------------------------------
496 {
497  handlePredictor();
498  loader_.updateSources();
503 
504  return;
505 }
506 
507 //-----------------------------------------------------------------------------
508 // Function : DCSweep::twoLevelStep
509 //
510 // Purpose : Used by 2-level Newton solves to execute a single DC sweep
511 // step.
512 //
513 // Special Notes : This is mostly what happens on the inner loop of
514 // dcSweepLoop, except that DC parameters are not updated,
515 // and success/failure of the step is not determined.
516 //
517 // Scope : public
518 // Creator : Eric Keiter, SNL
519 // Creation Date : 03/10/06
520 //-----------------------------------------------------------------------------
522 {
523  loader_.updateSources();
528 
530 }
531 
532 //-----------------------------------------------------------------------------
533 // Function : DCSweep::dcSweepOutput
534 // Purpose :
535 // Special Notes :
536 // Scope : public
537 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
538 // Creation Date : 1/31/08
539 //-----------------------------------------------------------------------------
541 {
542  // if this is an MPDE run, don't output anything.
543  bool mpdeFlag = analysisManager_.getMPDEFlag();
544  bool hbFlag = analysisManager_.getHBFlag();
545 
546  // Make sure this isn't the NLP step of a PDE DCOP.
547  if ( !mpdeFlag )
548  {
549  if (!firstDoubleDCOPStep_())
550  {
551  // conventional .PRINT output
553  stepNumber,
559 
560  // output for DCOP restart
562  }
563  }
564  else
565  {
566  if ( hbFlag )
567  {
568  std::vector<double> timePoints, freqPoints;
569  Teuchos::RefCountPtr<N_LAS_BlockVector> timeDomainSolnVec;
570  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainSolnVecReal;
571  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainSolnVecImaginary;
572  Teuchos::RefCountPtr<N_LAS_BlockVector> timeDomainStoreVec;
573  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainStoreVecReal;
574  Teuchos::RefCountPtr<N_LAS_BlockVector> freqDomainStoreVecImaginary;
575 
576  const HB &hb_analysis = dynamic_cast<const HB &>(analysisManager_.getAnalysisObject());
577 
578  hb_analysis.prepareHBOutput(
580  timePoints,
581  freqPoints,
582  timeDomainSolnVec,
583  freqDomainSolnVecReal,
584  freqDomainSolnVecImaginary,
585  timeDomainStoreVec,
586  freqDomainStoreVecReal,
587  freqDomainStoreVecImaginary
588  );
589 
591  timePoints,
592  freqPoints,
593  *timeDomainSolnVec,
594  *freqDomainSolnVecReal,
595  *freqDomainSolnVecImaginary,
596  *timeDomainStoreVec,
597  *freqDomainStoreVecReal,
598  *freqDomainStoreVecImaginary
599  );
600 
601  }
602  }
603 }
604 
605 //-----------------------------------------------------------------------------
606 // Function : DCSweep::printStepHeader()
607 // Purpose : Prints out time step information.
608 // Special Notes :
609 // Scope : public
610 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
611 // Creation Date : 6/26/00
612 //-----------------------------------------------------------------------------
613 void DCSweep::printStepHeader(std::ostream &os)
614 {
615 #ifdef Xyce_VERBOSE_TIME
616  lout() << std::endl << std::endl
617  << "***** "<< (DEBUG_ANALYSIS ? analysisManager_.getCommandLine().getArgumentValue("netlist") : "") << " Start of DCOP STEP # " << stepNumber+1
618  << std::endl << std::endl;
619 #endif
620 }
621 
622 //-----------------------------------------------------------------------------
623 // Function : DCSweep::printLoopInfo
624 // Purpose :
625 // Scope : public
626 // Creator : Eric Keiter
627 // Creation Date : 12/14/2010
628 //-----------------------------------------------------------------------------
629 bool DCSweep::printLoopInfo(int start, int finish)
630 {
631  bool bsuccess = AnalysisBase::printLoopInfo(start, finish);
632  if (start == 0 && finish == 0)
633  {
634  outputFailureStats(Xyce::lout());
635  }
636  return bsuccess;
637 }
638 
639 } // namespace Analysis
640 } // namespace Xyce