Xyce  6.1
N_NLS_TwoLevelNewton.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_NLS_TwoLevelNewton.C,v $
27 //
28 // Purpose : Body for the two level Newton class.
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 10/20/02
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.154.2.1 $
40 //
41 // Revision Date : $Date $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 #include <cstdio>
51 #include <string>
52 #include <list>
53 
54 // ---------- Xyce Includes ----------
55 #include <N_ANP_AnalysisManager.h>
56 #include <N_ERH_ErrorMgr.h>
57 #include <N_IO_OutputMgr.h>
58 #include <N_LAS_Builder.h>
59 #include <N_LAS_Matrix.h>
60 #include <N_LAS_System.h>
61 #include <N_LAS_Vector.h>
62 #include <N_LOA_Loader.h>
64 #include <N_NLS_DampedNewton.h>
65 #include <N_NLS_Manager.h>
66 #include <N_NLS_NOX_Interface.h>
67 #include <N_NLS_ReturnCodes.h>
68 #include <N_NLS_TwoLevelNewton.h>
69 #include <N_TIA_TimeIntInfo.h>
70 #include <N_UTL_FeatureTest.h>
71 #include <N_UTL_OptionBlock.h>
72 #include <N_UTL_Param.h>
73 
74 // ---------- Static Declarations ----------
75 
76 namespace Xyce {
77 namespace Nonlinear {
78 
79 //-----------------------------------------------------------------------------
80 // Function : TwoLevelNewton::TwoLevelNewton
81 // Purpose : constructor
82 // Special Notes :
83 // Scope : public
84 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
85 // Creation Date : 10/20/02
86 //-----------------------------------------------------------------------------
88  bool noxFlag,
89  bool noxFlagInner,
90  const IO::CmdParse & cp)
91  : NonLinearSolver(cp),
92  twoLevelAlgorithm_(3),
93  twoLevelAlgorithmTran_(0),
94  maxOuterSteps_(20),
95  maxContSteps_(10),
96  contStep_(0),
97  setupOuterLoopParamsFlag_(false),
98  setupTranParamsFlag_(false),
99  externalAnalysisMode(DC_OP),
100  outerLoopActiveFlag_(true),
101  noxFlag_(noxFlag),
102  noxFlagInner_(noxFlagInner),//inner loop possibly different than outer loop.
103  numInterfaceNodesSetup_(false),
104  twoLevelCouplingMode_(FULL_PROBLEM),
105  savedRHSPtr_(0),
106  savedNextSolPtr_(0),
107  jdxpVectorPtr_(0),
108  numSubProblems_(0),
109  continuationType_(1),
110  innerLoopFailFatal_(true),
111  totalSolveFailFatal_(false),
112  doFullNewtonFinalEnforcement_(true),
113  nlsPassingPtr_(0),
114  firstDCOPFlag_(false),
115  increaseContScalar_(1.5),
116  decreaseContScalar_(0.2), // was 0.125
117  continuationCalledBefore_(false),
118  voltLimTol_(1.0e-6)
119 {
120  // allocate the "outer loop" and "inner loop" solvers.
121  if (noxFlag_)
122  {
124  }
125  else
126  {
128  }
129 
130  if (noxFlagInner_)
131  {
133  }
134  else
135  {
137  }
138 
141 
142 }
143 
144 //-----------------------------------------------------------------------------
145 // Function : TwoLevelNewton::~TwoLevelNewton
146 // Purpose : destructor
147 // Special Notes :
148 // Scope : public
149 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
150 // Creation Date : 10/20/02
151 //-----------------------------------------------------------------------------
152 
154 {
155  delete nlsOuterPtr_;
156  delete nlsInnerPtr_;
157 
158  if (savedRHSPtr_!=0) delete savedRHSPtr_;
159  if (savedNextSolPtr_!=0) delete savedNextSolPtr_;
160 }
161 
162 //-----------------------------------------------------------------------------
163 // Function : TwoLevelNewton::registerAnalysisManager
164 // Purpose :
165 // Special Notes :
166 // Scope : public
167 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
168 // Creation Date : 10/20/02
169 //-----------------------------------------------------------------------------
171 {
172  bool bsuccess = true;
173  bool tmpBool = true;
174 
175  analysisManager_ = analysis_manager;
177  bsuccess = bsuccess && tmpBool;
178 
180  bsuccess = bsuccess && tmpBool;
181 
182  return bsuccess;
183 }
184 
185 //-----------------------------------------------------------------------------
186 // Function : TwoLevelNewton::registerLinearSystem
187 // Purpose :
188 // Special Notes :
189 // Scope : public
190 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
191 // Creation Date : 10/20/02
192 //-----------------------------------------------------------------------------
194 (Linear::System * ptr)
195 {
196  bool bsuccess = true;
197  bool tmpBool = true;
198 
199  lasSysPtr_ = ptr;
200  tmpBool = nlsOuterPtr_->registerLinearSystem (ptr);
201  bsuccess = bsuccess && tmpBool;
202 
203  tmpBool = nlsInnerPtr_->registerLinearSystem (ptr);
204  bsuccess = bsuccess && tmpBool;
205 
206  return bsuccess;
207 }
208 
209 //-----------------------------------------------------------------------------
210 // Function : TwoLevelNewton::registerLoader
211 // Purpose :
212 // Special Notes :
213 // Scope : public
214 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
215 // Creation Date : 10/20/02
216 //-----------------------------------------------------------------------------
218 {
219  bool bsuccess = true;
220  bool tmpBool = true;
221 
222  loaderPtr_ = loaderPtr_tmp;
223  tmpBool = nlsOuterPtr_->registerLoader (loaderPtr_tmp);
224  bsuccess = bsuccess && tmpBool;
225 
226  tmpBool = nlsInnerPtr_->registerLoader (loaderPtr_tmp);
227  bsuccess = bsuccess && tmpBool;
228 
229  return bsuccess;
230 }
231 
232 //-----------------------------------------------------------------------------
233 // Function : TwoLevelNewton::registerOutputMgr
234 // Purpose :
235 // Special Notes :
236 // Scope : public
237 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
238 // Creation Date : 9/23/03
239 //-----------------------------------------------------------------------------
240 bool TwoLevelNewton::registerOutputMgr (IO::OutputMgr * ptr)
241 {
242  bool bsuccess = true;
243  bool tmpBool = true;
244 
245  outMgrPtr_ = ptr;
246  tmpBool = nlsOuterPtr_->registerOutputMgr (ptr);
247  bsuccess = bsuccess && tmpBool;
248 
249  tmpBool = nlsInnerPtr_->registerOutputMgr (ptr);
250  bsuccess = bsuccess && tmpBool;
251 
252  return bsuccess;
253 }
254 
255 
256 //-----------------------------------------------------------------------------
257 // Function : TwoLevelNewton::getCouplingMode
258 // Purpose :
259 // Special Notes :
260 // Scope : public
261 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
262 // Creation Date : 12/05/02
263 //-----------------------------------------------------------------------------
265 {
266  return twoLevelCouplingMode_;
267 }
268 
269 //-----------------------------------------------------------------------------
270 // Function : TwoLevelNewton::getNumResidualLoads
271 // Purpose :
272 // Special Notes :
273 // Scope : public
274 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
275 // Creation Date : 10/20/02
276 //-----------------------------------------------------------------------------
278 {
279  int numResLoads = 0;
280  numResLoads += nlsOuterPtr_->getNumResidualLoads ();
281  numResLoads += numResidualLoads_;
282  return numResLoads;
283 }
284 
285 //-----------------------------------------------------------------------------
286 // Function : TwoLevelNewton::getNumJacobianLoads
287 // Purpose :
288 // Special Notes :
289 // Scope : public
290 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
291 // Creation Date : 10/20/02
292 //-----------------------------------------------------------------------------
294 {
295  int numJacLoads = 0;
296  numJacLoads += nlsOuterPtr_->getNumJacobianLoads ();
297  numJacLoads += numJacobianLoads_;
298  return numJacLoads;
299 }
300 
301 //-----------------------------------------------------------------------------
302 // Function : TwoLevelNewton::getNumLinearSolves
303 // Purpose :
304 // Special Notes :
305 // Scope : public
306 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
307 // Creation Date : 10/20/02
308 //-----------------------------------------------------------------------------
310 {
311  int numLinSolves = 0;
312  numLinSolves += nlsOuterPtr_->getNumLinearSolves ();
313  numLinSolves += numLinearSolves_;
314  return numLinSolves;
315 }
316 
317 //-----------------------------------------------------------------------------
318 // Function : TwoLevelNewton::getNumFailedLinearSolves
319 // Purpose :
320 // Special Notes :
321 // Scope : public
322 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
323 // Creation Date : 10/20/02
324 //-----------------------------------------------------------------------------
326 {
327  int numFLinSolves = 0;
328  numFLinSolves += nlsOuterPtr_->getNumFailedLinearSolves ();
329  numFLinSolves += numFailedLinearSolves_;
330  return numFLinSolves;
331 }
332 
333 //-----------------------------------------------------------------------------
334 // Function : TwoLevelNewton::getNumJacobianFactorizations
335 // Purpose :
336 // Special Notes :
337 // Scope : public
338 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
339 // Creation Date : 10/20/02
340 //-----------------------------------------------------------------------------
342 {
343  int numJacFact = 0;
344  numJacFact += nlsOuterPtr_->getNumJacobianFactorizations ();
345  numJacFact += numJacobianFactorizations_;
346  return numJacFact;
347 }
348 
349 //-----------------------------------------------------------------------------
350 // Function : TwoLevelNewton::getTotalNumLinearIters
351 // Purpose :
352 // Special Notes :
353 // Scope : public
354 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
355 // Creation Date : 10/20/02
356 //-----------------------------------------------------------------------------
358 {
359  int numLinIters = 0;
360  numLinIters += nlsOuterPtr_->getTotalNumLinearIters ();
361  numLinIters += totalNumLinearIters_;
362  return numLinIters ;
363 }
364 
365 //-----------------------------------------------------------------------------
366 // Function : TwoLevelNewton::getTotalLinearSolveTime
367 // Purpose :
368 // Special Notes :
369 // Scope : public
370 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
371 // Creation Date : 10/20/02
372 //-----------------------------------------------------------------------------
374 {
375  double totalLinSolveTime = 0.0;
376  totalLinSolveTime += nlsOuterPtr_->getTotalLinearSolveTime();
377  totalLinSolveTime += totalLinearSolveTime_;
378  return totalLinSolveTime;
379 }
380 
381 //-----------------------------------------------------------------------------
382 // Function : TwoLevelNewton::getTotalResidualLoadTime
383 // Purpose :
384 // Special Notes :
385 // Scope : public
386 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
387 // Creation Date : 10/20/02
388 //-----------------------------------------------------------------------------
390 {
391  double totalResLoadTime = 0.0;
392  totalResLoadTime += nlsOuterPtr_-> getTotalResidualLoadTime();
393  totalResLoadTime += totalResidualLoadTime_;
394  return totalResLoadTime;
395 }
396 
397 //-----------------------------------------------------------------------------
398 // Function : TwoLevelNewton::getTotalJacobianLoadTime
399 // Purpose :
400 // Special Notes :
401 // Scope : public
402 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
403 // Creation Date : 10/20/02
404 //-----------------------------------------------------------------------------
406 {
407  double totalJacLoadTime = 0.0;
408  totalJacLoadTime += nlsOuterPtr_->getTotalJacobianLoadTime();
409  totalJacLoadTime += totalJacobianLoadTime_;
410  return totalJacLoadTime;
411 }
412 
413 //-----------------------------------------------------------------------------
414 // Function : TwoLevelNewton::getNumIterations
415 // Purpose : Returns the current number of nonlinear iterations, for
416 // the solver currently being used (for two-level more than
417 // one solver is usually being invoked).
418 // Special Notes :
419 // Scope : private
420 // Creator : Eric R. Keiter, SNL, Compuational Sciences
421 // Creation Date : 10/24/02
422 //-----------------------------------------------------------------------------
424 {
425  int numIters = 0;
427  {
428  numIters = nlsOuterPtr_->getNumIterations ();
429  }
430  else
431  {
432  numIters = nlsInnerPtr_->getNumIterations ();
433  }
434 
435  return numIters;
436 }
437 
438 //-----------------------------------------------------------------------------
439 // Function : TwoLevelNewton::getMaxNormF
440 // Purpose :
441 // Special Notes :
442 // Scope : public
443 // Creator : Rich Schiek, Electrical and Memes Modeling
444 // Creation Date : 9/27/2009
445 //-----------------------------------------------------------------------------
447 {
448  double result = nlsInnerPtr_->getMaxNormF() + nlsOuterPtr_->getMaxNormF();
449  return result;
450 }
451 
452 //-----------------------------------------------------------------------------
453 // Function : TwoLevelNewton::getMaxNormFindex
454 // Purpose :
455 // Special Notes :
456 // Scope : public
457 // Creator : Rich Schiek, Electrical and Memes Modeling
458 // Creation Date : 9/27/2009
459 //-----------------------------------------------------------------------------
461 {
462  int indexInner = nlsInnerPtr_->getMaxNormFindex();
463  int indexOuter = nlsOuterPtr_->getMaxNormFindex();
464 
465  return indexInner; // usually the inner will be the one you want,
466  // but there should be more of a detailed comparison
467  // here just in case. FIX THIS
468 }
469 
470 
471 //-----------------------------------------------------------------------------
472 // Function : TwoLevelNewton::initializeAll
473 //
474 // Purpose : This serves the same purpose as the initializeAll
475 // function in the other solvers.
476 //
477 // Special Notes : Each of the solvers (inner, outer, and this one) will
478 // ultimately call the base class initialize all function,
479 // meaning that there are potentially 3 of each linear
480 // solver (3 iterative, 3 direct). This sort of makes
481 // sense for the inner and outer, as they may want
482 // different linear solvers. But, for the wrapper class,
483 // TwoLevelNewton, I'm only doing this so that it is
484 // possible to pass a solver pointer to Sensitivity,
485 // if needed.
486 //
487 // In the future, it may make sense to clean this up a
488 // litte.
489 //
490 // Scope : public
491 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
492 // Creation Date : 10/20/02
493 //-----------------------------------------------------------------------------
495 {
496  bool bsuccess = true;
497  bool tmpBool = true;
498 
499  tmpBool = nlsInnerPtr_->initializeAll ();
500  bsuccess = bsuccess && tmpBool;
501 
502  tmpBool= nlsOuterPtr_->initializeAll ();
503  bsuccess = bsuccess && tmpBool;
504 
505  tmpBool = NonLinearSolver::initializeAll();
506  bsuccess = bsuccess && tmpBool;
507 
508  savedRHSPtr_ = lasSysPtr_->builder().createVector ();
509  savedNextSolPtr_ = lasSysPtr_->builder().createVector ();
510  jdxpVectorPtr_ = lasSysPtr_->getJDXPVector ();
511 
512  // set up the return codes so that the "inner" solver is subject to
513  // greater restrictions than the outter solver.
514  ReturnCodes retCode;
515  retCode.nearConvergence = -3;
516  nlsInnerPtr_->setReturnCodes (retCode);
517 
518  return bsuccess;
519 }
520 
521 //-----------------------------------------------------------------------------
522 // Function : TwoLevelNewton::setOptions
523 //
524 // Purpose : This function processes the options set in the
525 // ".options NONLIN" line of the netlist.
526 //
527 // Special Notes : Mostly, these options are just passed on through to the
528 // "outer" nonlinear solver. However, since the outer
529 // solver is incremented one Newton step at a time, and
530 // the actual outer control loop sits here in the two level
531 // class, a few of the parameters are needed. In
532 // particular, the maximum number of Newton steps.
533 //
534 // Scope : public
535 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
536 // Creation Date : 10/20/02
537 //-----------------------------------------------------------------------------
538 bool TwoLevelNewton::setOptions(const Util::OptionBlock & OB)
539 {
540  Util::ParamList::const_iterator it_tpL = OB.begin();
541  Util::ParamList::const_iterator end_tpL = OB.end();
542  for ( ; it_tpL != end_tpL; ++it_tpL)
543  {
544  if (it_tpL->uTag() == "MAXSTEP")
545  {
546  maxOuterSteps_ = static_cast<int>(it_tpL->getImmutableValue<int>());
547  }
548  }
549 
550  return nlsOuterPtr_->setOptions(OB);
551 }
552 
553 //-----------------------------------------------------------------------------
554 // Function : TwoLevelNewton::setTranOptions
555 // Purpose :
556 // Special Notes :
557 // Scope : public
558 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
559 // Creation Date : 10/20/02
560 //-----------------------------------------------------------------------------
561 bool TwoLevelNewton::setTranOptions(const Util::OptionBlock & OB)
562 {
563  return nlsOuterPtr_->setTranOptions(OB);
564 }
565 
566 bool TwoLevelNewton::setHBOptions(const Util::OptionBlock & OB)
567 {
568  return true;
569 }
570 
571 
572 //-----------------------------------------------------------------------------
573 // Function : TwoLevelNewton::setLocaOptions
574 // Purpose :
575 // Special Notes :
576 // Scope : public
577 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
578 // Creation Date : 09/10/03
579 //-----------------------------------------------------------------------------
580 bool TwoLevelNewton::setLocaOptions (const Util::OptionBlock & OB)
581 {
582  outerLocaOptions_ = OB;
583  return nlsOuterPtr_->setLocaOptions(OB);
584 }
585 
586 //-----------------------------------------------------------------------------
587 // Function : TwoLevelNewton::setTwoLevelLocaOptions
588 // Purpose :
589 // Special Notes :
590 // Scope : public
591 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
592 // Creation Date : 09/10/03
593 //-----------------------------------------------------------------------------
594 bool TwoLevelNewton::setTwoLevelLocaOptions (const Util::OptionBlock & OB)
595 {
596  innerLocaOptions_ = OB;
597  return nlsInnerPtr_->setLocaOptions(OB);
598 }
599 
600 
601 //-----------------------------------------------------------------------------
602 // Function : TwoLevelNewton::setTwoLevelOptions
603 // Purpose :
604 // Special Notes :
605 // Scope : public
606 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
607 // Creation Date : 10/20/02
608 //-----------------------------------------------------------------------------
609 bool TwoLevelNewton::setTwoLevelOptions(const Util::OptionBlock & OB)
610 {
611  Util::OptionBlock OBtmp;
612 
613  Util::ParamList::const_iterator it_tpL = OB.begin();
614  Util::ParamList::const_iterator end_tpL = OB.end();
615  for ( ; it_tpL != end_tpL; ++it_tpL)
616  {
617  if (it_tpL->uTag() == "ALGORITHM")
618  {
619  twoLevelAlgorithm_ = static_cast<int>(it_tpL->getImmutableValue<int>());
620  }
621  else if (it_tpL->uTag() == "NOX")
622  {
623  noxFlagInner_ = it_tpL->getImmutableValue<int>();
624  }
625  else if (it_tpL->uTag() == "MAXCONTSTEPS")
626  {
627  maxContSteps_ = static_cast<int>(it_tpL->getImmutableValue<int>());
628  }
629  else if (it_tpL->uTag() == "CONTINUATIONFLAG")
630  {
631  int tmp = static_cast<int>(it_tpL->getImmutableValue<int>());
632  continuationType_ = tmp;
633  }
634  else if (it_tpL->uTag() == "INNERFAIL")
635  {
636  int tmp = static_cast<int>(it_tpL->getImmutableValue<int>());
637  innerLoopFailFatal_ = (tmp!=0);
638  }
639  else if (it_tpL->uTag() == "EXITWITHFAILURE")
640  {
641  int tmp = static_cast<int>(it_tpL->getImmutableValue<int>());
642  totalSolveFailFatal_ = (tmp!=0);
643  }
644  else if (it_tpL->uTag() == "FULLNEWTONENFORCE")
645  {
646  int tmp = static_cast<int>(it_tpL->getImmutableValue<int>());
648  }
649  else if (it_tpL->uTag() == "CONPARAM")
650  {
651  paramNameList.push_back(it_tpL->stringValue());
652  }
653  else if (it_tpL->uTag() == "VOLTLIMTOL")
654  {
655  voltLimTol_ = static_cast<double>(it_tpL->getImmutableValue<double>());
656  }
657  else // anything that is not a "special" two-level param, push
658  // back on the the tmp param list.
659  {
660  OBtmp.getParams().push_back(*it_tpL);
661  }
662  }
663 
664  innerSolverOptions_ = OBtmp; // keep a copy of these.
665 
666  nlsInnerPtr_->setOptions(OBtmp);
667 
668  if (twoLevelAlgorithm_ < 0 || twoLevelAlgorithm_ > 5)
669  {
670  Report::UserWarning0() << "Now the only algorithms 0 to 5 are two-level algorithm. Resetting to 0";
671 
672  twoLevelAlgorithm_ = 0;
673  }
674 
675  if (VERBOSE_NONLINEAR)
676  {
677  Xyce::dout() << "\n" << std::endl
678  << Xyce::section_divider << std::endl
679  << "\n***** 2-level Inner Loop Nonlinear solver options:\n" << std::endl
680  << "\talgorithm:\t\t\t" << twoLevelAlgorithm_ << std::endl
681  << "\toutersteps:\t\t\t" << maxOuterSteps_ << std::endl
682  << "\tmaxContSteps:\t\t\t" << maxContSteps_ << std::endl;
683 
684  Xyce::dout() << "\n***** Done printing Inner Loop Params:\n" << std::endl
685  << Xyce::section_divider << std::endl
686  << "\n" << std::endl;
687  }
688 
689  // Now that the loop is done allocate the param val array:
690  paramFinalVal.resize(paramNameList.size(),0.0);
691  paramCurrentVal.resize(paramNameList.size(),0.0);
692 
693  return true;
694 }
695 
696 //-----------------------------------------------------------------------------
697 // Function : TwoLevelNewton::setTwoLevelTranOptions
698 // Purpose :
699 // Special Notes :
700 // Scope : public
701 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
702 // Creation Date : 10/20/02
703 //-----------------------------------------------------------------------------
704 bool TwoLevelNewton::setTwoLevelTranOptions(const Util::OptionBlock & OB)
705 {
706  setupTranParamsFlag_ = true;
707  if (VERBOSE_NONLINEAR)
708  Xyce::dout() << "In TwoLevelNewton::setTwoLevelTranOptions" << std::endl;
709 
710  Util::OptionBlock OBtmp;
711 
712  Util::ParamList::const_iterator it_tpL = OB.begin();
713  Util::ParamList::const_iterator end_tpL = OB.end();
714  for ( ; it_tpL != end_tpL; ++it_tpL)
715  {
716  if (it_tpL->uTag() == "ALGORITHM")
717  {
718  twoLevelAlgorithmTran_ = static_cast<int>(it_tpL->getImmutableValue<int>());
719  }
720  else if ( it_tpL->uTag() == "MAXCONTSTEPS" )
721  {
722  maxContStepsTran_ = static_cast<int>(it_tpL->getImmutableValue<int>());
723  }
724  else // anything that is not a "special" two-level param, push
725  // back on the the tmp param list.
726  {
727  OBtmp.getParams().push_back(*it_tpL);
728  }
729  }
730 
732 
733  if (twoLevelAlgorithmTran_ < 0 || twoLevelAlgorithmTran_ > 3)
734  {
735  Report::UserWarning0() << "Now the only algorithms 0 to 3 are two-level algorithm. Resetting to 0";
736 
738  }
739 
740  return true;
741 }
742 
743 
744 //-----------------------------------------------------------------------------
745 // Function : TwoLevelNewton::setAnalysisMode
746 // Purpose : This function is slightly different than the
747 // function of the same name in NLParams.
748 //
749 // Special Notes :
750 // Scope : public
751 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
752 // Creation Date : 10/21/02
753 //-----------------------------------------------------------------------------
755 {
756  // this should be 0,1 or 2 (DC_OP, DC_SWEEP, or TRANSIENT)
757  if (VERBOSE_NONLINEAR)
758  Xyce::dout() << std::endl
759  << "Setting the externalAnalysisMode = " << mode << std::endl;
760 
761  externalAnalysisMode = mode;
762 
765 }
766 
767 //-----------------------------------------------------------------------------
768 // Function : TwoLevelNewton::registerPetraOptions
769 // Purpose : see header file
770 // Special Notes : see header file
771 // Scope : public
772 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
773 // Creation Date : 11/9/00
774 //-----------------------------------------------------------------------------
775 
776 bool TwoLevelNewton::setPetraOptions(const Util::OptionBlock & OB)
777 {
778  bool bsuccess = true;
779  bool tmpBool = true;
780  tmpBool = nlsOuterPtr_->setPetraOptions(OB);
781  bsuccess = bsuccess && tmpBool;
782 
783  tmpBool = nlsInnerPtr_->setPetraOptions(OB);
784  bsuccess = bsuccess && tmpBool;
785 
786  tmpBool = NonLinearSolver::setPetraOptions(OB);
787  bsuccess = bsuccess && tmpBool;
788 
789  return bsuccess;
790 }
791 
792 
793 //-----------------------------------------------------------------------------
794 // Function : TwoLevelNewton::printStepInfo_
795 // Purpose : Print out 2-level Newton step information.
796 // Special Notes :
797 // Scope : public
798 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
799 // Creation Date : 10/21/02
800 //-----------------------------------------------------------------------------
802 (int step, int success, TwoLevelNewtonMode solveType)
803 {
804  char tmpChar[128];
805  if (solveType==FULL_PROBLEM)
806  {
807  Xyce::lout() << "---------- 2LNiter: " << step << "\t" << success << "\tFULL PROBLEM --------------------------------" << std::endl;
808  }
809  else if (solveType==INNER_PROBLEM)
810  {
811  Xyce::lout() << "---------- 2LNiter: " << step << "\t" << success << "\tINNER PROBLEM ----------------------------" << std::endl;
812  }
813  else
814  {
815  Xyce::lout() << "---------- 2LNiter: " << step << "\t" << success << "\tOUTER PROBLEM ----------------------------" << std::endl;
816  }
817 }
818 
819 //-----------------------------------------------------------------------------
820 // Function : TwoLevelNewton::zeroInnerLoopStatistics_
821 // Purpose :
822 // Special Notes :
823 // Scope : public
824 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
825 // Creation Date : 10/21/02
826 //-----------------------------------------------------------------------------
828 {
829  numResidualLoads_ = 0;
830  numJacobianLoads_ = 0;
831  numLinearSolves_ = 0;
835  totalLinearSolveTime_ = 0.0;
838 }
839 
840 //-----------------------------------------------------------------------------
841 // Function : TwoLevelNewton::calcInnerLoopStatistics_
842 // Purpose :
843 // Special Notes :
844 // Scope : public
845 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
846 // Creation Date : 10/21/02
847 //-----------------------------------------------------------------------------
849 {
859 }
860 
861 //-----------------------------------------------------------------------------
862 // Function : TwoLevelNewton::calcOuterLoopStatistics_
863 // Purpose :
864 // Special Notes :
865 // Scope : public
866 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
867 // Creation Date : 10/21/02
868 //-----------------------------------------------------------------------------
870 {
880 }
881 
882 
883 //-----------------------------------------------------------------------------
884 // Function : TwoLevelNewton::algorithm0_
885 // Purpose : This algorithm is the full newton algorithm.
886 //
887 // Special Notes : The main thing that is different about running this
888 // function, rather than just not using the 2-level class
889 // at all, is that here the conductance and capacitance
890 // calculations are performed at the end of the solve.
891 //
892 // Scope : private
893 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
894 // Creation Date : 05/07/03
895 //-----------------------------------------------------------------------------
897 {
898  int status = -1;
899 
900  if (VERBOSE_NONLINEAR)
901  Xyce::dout() << std::endl << "Running algorithm 0:" << std::endl;
902 
903  // set up the local algorithm variable:
904  int algorithm = twoLevelAlgorithm_;
905  if ( externalAnalysisMode ==2) algorithm = twoLevelAlgorithmTran_;
906 
907  // This step is neccessary in case we've just switched algorithms.
908  if ( algorithm == 0) twoLevelCouplingMode_=FULL_PROBLEM;
909 
910  status = nlsOuterPtr_->solve ();
911 
912  // Now do conductance/capacitance extractions, if it makes sense.
913  if (!firstDCOPFlag_)
914  {
916  }
917 
918  // Do this so that I can test the ConductanceExtractor class.
921 
922  return status;
923 }
924 
925 //-----------------------------------------------------------------------------
926 // Function : TwoLevelNewton::algorithm1_
927 // Purpose : This is the first two-level algorithm implemented.
928 // The idea is to have nested Newton solves.
929 //
930 // Inner loop = PDE-device only
931 // Outer loop = Full Newton.
932 //
933 // Special Notes : Doesn't work with NOX yet...
934 //
935 // This will exit immediately if the inner loop fails.
936 // The reason for this is that the point of 2-level
937 // Newton is to solve problems that are difficult
938 // as a result of two very different problem types
939 // being coupled together.
940 //
941 // Ideally, for the two-level Newton, you have a
942 // circuit problem that can be easily solved on its
943 // own, and a PDE-device problem that can easily be
944 // solved on its own, and the only problem is that
945 // they can't easily be solved together. Two level
946 // Newton separates them, and applies different
947 // (hopefully ideal) solver settings to each.
948 //
949 // If the PDE problem
950 // (the inner loop) can't be solved with its
951 // current settings, even in stand-alone mode, 2-level
952 // Newton won't help.
953 //
954 // Scope : private
955 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
956 // Creation Date : 10/22/02
957 //-----------------------------------------------------------------------------
959 {
960  int status = -1;
961 
962  if (VERBOSE_NONLINEAR)
963  Xyce::dout() << std::endl << "Running algorithm 1:" << std::endl;
964 
965  bool firstOuterStepTaken = false;
966  nlsPassingPtr_ = 0;
967 
968  if (status < 0)
969  {
970  int twoLevelStep;
971  for (twoLevelStep=0;twoLevelStep<maxOuterSteps_; ++twoLevelStep)
972  {
973  // Device Only:
975  outerLoopActiveFlag_= false;
976  int statInner = nlsInnerPtr_->solve (nlsPassingPtr_);
977  nlsPassingPtr_ = 0;
979 
980  // Output the nonlinear solver step information:
981  if (VERBOSE_NONLINEAR)
982  printStepInfo_(twoLevelStep+1,statInner, twoLevelCouplingMode_);
983 
984  // If we can't even get the inner loop to converge,
985  // just give up.
986  if (statInner < 0)
987  {
988  break;
989  }
990 
991  // Full Problem:
993  outerLoopActiveFlag_= true;
994  if (firstOuterStepTaken)
995  {
996  status = nlsOuterPtr_->takeOneSolveStep ();
997  }
998  else
999  {
1000  firstOuterStepTaken = true;
1002  }
1003 
1005 
1006  // Output the nonlinear solver step information:
1007  if (VERBOSE_NONLINEAR)
1008  printStepInfo_(twoLevelStep+1,status, twoLevelCouplingMode_);
1009 
1010  // exit?
1011  // Use the total "full Newton" error to evaluate this step.
1012  if (status >= 0)
1013  {
1014  break;
1015  }
1016 
1017  } // end of for loop
1018  } // end of status if statement
1019 
1020  if (VERBOSE_NONLINEAR && status >=0)
1021  Xyce::dout() << "TWO LEVEL Newton succeeded!" << std::endl;
1022 
1023  return status;
1024 }
1025 
1026 //-----------------------------------------------------------------------------
1027 // Function : TwoLevelNewton::algorithm2_
1028 // Purpose : Similar to algorithm1, but this one allows for the
1029 // inner PDE Newton solve to be gradually stepped up to
1030 // the circuit imposed boundary conditions. Essentially,
1031 // the inner loop Newton solve is a continuation method.
1032 //
1033 // This could almost be called a "3-level" Newton, as there
1034 // are now 3 nested loops.
1035 //
1036 // Special Notes : not finished yet...
1037 //
1038 // Scope : private
1039 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1040 // Creation Date : 10/22/02
1041 //-----------------------------------------------------------------------------
1043 {
1044  int status = -1;
1045  int statInner = 0;
1046  bool statusFull = false;
1047  bool firstOuterStepTaken = false;
1048 
1049  if (VERBOSE_NONLINEAR)
1050  Xyce::dout() << std::endl << "Running algorithm 2:" << std::endl;
1051 
1052  // Start out with a single step of the full problem:
1053  // Full Problem:
1055  firstOuterStepTaken = true;
1056  outerLoopActiveFlag_= true;
1058 
1059  // Output the nonlinear solver step information:
1060  if (VERBOSE_NONLINEAR)
1062 
1063  nlsPassingPtr_ = 0;
1064  if (status <= 0)
1065  {
1066  int twoLevelStep;
1067  for (twoLevelStep=0;twoLevelStep<maxOuterSteps_; ++twoLevelStep)
1068  {
1069  // Device Only:
1071  outerLoopActiveFlag_= false;
1072 
1073  if (continuationType_ == 1)
1074  {
1075  statInner = continuationLoop_ ();
1076  }
1077  else if (continuationType_ == 2)
1078  {
1079  statInner = locaLoop_ ();
1080  }
1081  else
1082  {
1083  statInner = nlsInnerPtr_->solve (nlsPassingPtr_);
1084  nlsPassingPtr_ = 0;
1086  }
1087 
1088  // Output the nonlinear solver step information:
1089  if (VERBOSE_NONLINEAR)
1090  printStepInfo_(twoLevelStep+1,statInner,twoLevelCouplingMode_);
1091 
1092  if (innerLoopFailFatal_)
1093  {
1094  // If we can't even get the inner loop to converge,
1095  // just give up.
1096  if (statInner <= 0)
1097  {
1098  break;
1099  }
1100  }
1101 
1102  // Full Problem:
1104  outerLoopActiveFlag_= true;
1105 
1106  if (firstOuterStepTaken)
1107  {
1108  status = nlsOuterPtr_->takeOneSolveStep ();
1109  }
1110  else
1111  {
1112  firstOuterStepTaken = true;
1114  }
1116 
1117  // Output the nonlinear solver step information:
1118  if (VERBOSE_NONLINEAR)
1119  printStepInfo_(twoLevelStep+1,status,twoLevelCouplingMode_);
1120 
1121  // exit?
1122  // Use the total "full Newton" error to evaluate this step.
1123  // If the ckt considers itself converged at this point, do a
1124  // final reality check by taking a full Newton step.
1125  statusFull = false;
1126 
1127  if (status > 0 && statInner>0) statusFull = true;
1128 
1129  if (statusFull) break;
1130 
1131  } // end of for loop
1132  } // end of status if statement
1133 
1134  if (VERBOSE_NONLINEAR && status >0 && statInner > 0)
1135  Xyce::dout() << "TWO LEVEL Newton succeeded!" << std::endl;
1136 
1137  return status;
1138 }
1139 
1140 //-----------------------------------------------------------------------------
1141 // Function : TwoLevelNewton::algorithm3_
1142 //
1143 // Purpose : This is another 2-level algorithm. For this
1144 // algorithm, the de-coupling is greater than for
1145 // algorithms 1 and 2.
1146 //
1147 // The circuit Newton steps do *not* include any
1148 // PDE device elements, and never do. The PDE
1149 // devices are replaced by approximated conductances.
1150 //
1151 // Special Notes : This is the best algorithm.
1152 //
1153 // Scope : private
1154 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1155 // Creation Date : 10/25/02
1156 //-----------------------------------------------------------------------------
1158 {
1159  int status = -1;
1160  int statInner = 0;
1161  bool statusFull = false;
1162  bool firstOuterStepTaken = false;
1163 
1164  if (VERBOSE_NONLINEAR)
1165  Xyce::dout() << std::endl << "Running algorithm 3:" << std::endl;
1166 
1167  nlsPassingPtr_ = 0;
1168 
1169  int twoLevelStep;
1170  if (status <= 0)
1171  {
1172  for (twoLevelStep=0;twoLevelStep<maxOuterSteps_; ++twoLevelStep)
1173  {
1174  // Device Only:
1175  // Solve device problem with continuation:
1177  outerLoopActiveFlag_= false;
1178  statInner = 0;
1179 
1180  if (continuationType_ == 1)
1181  {
1182  statInner = continuationLoop_ ();
1183  }
1184  else if (continuationType_ == 2)
1185  {
1186  statInner = locaLoop_ ();
1187  }
1188  else
1189  {
1190  statInner = nlsInnerPtr_->solve (nlsPassingPtr_);
1191  nlsPassingPtr_ = 0;
1193  }
1194 
1195  // Output the nonlinear solver step information:
1196  if (VERBOSE_NONLINEAR)
1197  printStepInfo_(twoLevelStep+1,statInner,twoLevelCouplingMode_);
1198 
1199  if (innerLoopFailFatal_)
1200  {
1201  // If we can't even get the inner loop to converge,
1202  // just give up.
1203  if (statInner <= 0)
1204  {
1205  break;
1206  }
1207  }
1208 
1209  // Now do all the conductance extractions:
1210  calcCouplingTerms_ ();
1211 
1212  // ckt-only problem:
1214  outerLoopActiveFlag_= true;
1215  if (firstOuterStepTaken)
1216  {
1217  status = nlsOuterPtr_->takeOneSolveStep ();
1218  }
1219  else
1220  {
1221  firstOuterStepTaken = true;
1223  }
1224 
1225  if (noxFlag_)
1226  {
1228  }
1229 
1230  // Output the nonlinear solver step information:
1231  if (VERBOSE_NONLINEAR)
1232  printStepInfo_(twoLevelStep+1,status,twoLevelCouplingMode_);
1233 
1234  // check if voltage limiting is still active by getting the norm of the
1235  // jdxp vector:
1236  double twoNormJDXP_ = 0.0;
1237  jdxpVectorPtr_->lpNorm(2, &twoNormJDXP_);
1238 
1239  bool voltLimStat = (twoNormJDXP_ <= voltLimTol_);
1240 
1241  if (VERBOSE_NONLINEAR)
1242  Xyce::dout() << std::endl
1243  << " 2-norm of voltage limiting vector: " << twoNormJDXP_ << std::endl;
1244 
1245  // exit?
1246  statusFull = false;
1247  if (status > 0 && statInner>0 && voltLimStat) statusFull = true;
1248 
1249  if (statusFull) break;
1250 
1251  } // end of outer steps "for" loop
1252 
1253  } // end of status if statement
1254 
1255  // Do a final few "full Newton" steps, to get a final consistency between
1256  // the two solvers.
1257  int statFinal = 2;
1258  if (doFullNewtonFinalEnforcement_ && statusFull)
1259  {
1261  statFinal = nlsOuterPtr_->solve ();
1262 
1263  // Output the nonlinear solver step information:
1264  if (VERBOSE_NONLINEAR)
1265  {
1266  ++twoLevelStep;
1267  printStepInfo_(twoLevelStep+1,status,twoLevelCouplingMode_);
1268  }
1269  }
1270 
1271  // Do one final conductance/capacitance extraction:
1272  calcCouplingTerms_ ();
1273 
1274  if (VERBOSE_NONLINEAR && status >0 && statInner > 0 && statFinal > 0)
1275  Xyce::dout() << "TWO LEVEL Newton succeeded!" << std::endl;
1276 
1277  return status;
1278 }
1279 
1280 //-----------------------------------------------------------------------------
1281 // Function : TwoLevelNewton::algorithm4_
1282 //
1283 // Purpose : This is mostly a test algorithm.
1284 //
1285 // This is not a two-level class algorithm, but rather a
1286 // continuation algorithm to test out
1287 // some of the new continuation capabilities.
1288 //
1289 // Mostly, I'm putting this here to test out the new
1290 // "setParam" function in the device package, which is
1291 // needed by LOCA.
1292 //
1293 // Special Notes :
1294 // Scope : private
1295 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1296 // Creation Date : 07/26/03
1297 //-----------------------------------------------------------------------------
1299 {
1300  int status = -1;
1301  int statNL;
1302  nlsPassingPtr_ = 0;
1303  bool continuationLoop = false;
1304  bool successBool;
1305  int contMaxTmp = 100; // this is just a guess for number of steps.
1306  int stepsLeft = contMaxTmp;
1307 
1308  if (VERBOSE_NONLINEAR)
1309  Xyce::dout() << std::endl << "Running algorithm 4:" << std::endl
1310  << std::endl << "Initial continuation steps: "
1311  << contMaxTmp << std::endl;
1312 
1313  // The solves should be FULL newton solves.
1315 
1316  // These values assume that any parameter will start at zero and ramp up
1317  // to a final value. The final value is the value that is set for this
1318  // parameter in the netlist. So, for example, if a voltage source is set
1319  // to 5.0 volts in the netlist:
1320  //
1321  // vid 4 0 5.00
1322  //
1323  // and one of the continuation parameters is vid:v0, then the final value
1324  // for vid:v0 is 5.00.
1325 
1326  double initVal = 0.0;
1327  double currVal = initVal;
1328  double prevVal = initVal;
1329  double stepSizeEst;
1330 
1331  std::vector<std::string>::iterator iter;
1332  std::vector<std::string>::iterator begin = paramNameList.begin ();
1333  std::vector<std::string>::iterator end = paramNameList.end ();
1334 
1335  std::vector<double>::iterator iterFinalVal;
1336  std::vector<double>::iterator beginFinalVal = paramFinalVal.begin ();
1337  std::vector<double>::iterator endFinalVal = paramFinalVal.end ();
1338 
1339  std::vector<double>::iterator iterCurrentVal;
1340  std::vector<double>::iterator beginCurrentVal = paramCurrentVal.begin ();
1341  std::vector<double>::iterator endCurrentVal = paramCurrentVal.end ();
1342 
1343  // Get the final values for each param., then set each to zero.
1344  for (iter=begin, iterFinalVal=beginFinalVal, iterCurrentVal=beginCurrentVal;
1345  iter!=end;
1346  ++iter, ++iterFinalVal, ++iterCurrentVal)
1347  {
1348  //*iterFinalVal = loaderPtr_->getParam(*iter);
1349  *iterFinalVal = 1.0;
1350  loaderPtr_->setParam(*iter, 0.0);
1351  }
1352 
1353  // now, loop over each parameter, and do a continuation loop for each.
1354  // For each param, the loop will adjust the param from 0.0 to the final
1355  // value. Once each parameter has achieved a final value, the solve is
1356  // finished.
1357  for (iter=begin, iterFinalVal=beginFinalVal;
1358  iter!=end;
1359  ++iter, ++iterFinalVal)
1360  {
1361  // get the initial stepsize:
1362  stepSizeEst = (*iterFinalVal-0.0)/(static_cast<double>(contMaxTmp));
1363  currVal = 0.0;
1364  prevVal = 0.0;
1365  contStep_=1;
1366 
1367  if (VERBOSE_NONLINEAR)
1368  Xyce::dout() << "Parameter = " << *iter
1369  << " finalVal = " << *iterFinalVal << std::endl;
1370 
1371  // begin continuation Loop for the current parameter, *iter:
1372  bool continuationLoopFinished = false;
1373  int numTotalFailures = 0;
1374  while (!continuationLoopFinished)
1375  {
1376  bool stepFinished = false;
1377  int numFailures = 0;
1378 
1379  while(!stepFinished)
1380  {
1381  if (stepSizeEst != 0.0)
1382  {
1383  stepsLeft = static_cast<int>((*iterFinalVal-currVal)/stepSizeEst) + 1;
1384  }
1385  else
1386  {
1387  stepsLeft = 1;
1388  }
1389 
1390  if (VERBOSE_NONLINEAR)
1391  Xyce::dout() << std::endl << "Continuation Step: " << contStep_
1392  << " Estimated Remaining Steps: " << stepsLeft
1393  << " " << *iter
1394  << std::endl
1395  << "currVal= " << currVal
1396  << " prevVal= " << prevVal
1397  << " step= " << stepSizeEst
1398  << std::endl;
1399 
1400  if (stepsLeft < 0)
1401  {
1402  std::string tmp = "Continuation step estimate broken. Exiting\n";
1403  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1404  }
1405 
1406  // save a copy of solution:
1407  (*savedNextSolPtr_) = (**nextSolVectorPtrPtr_);
1408 
1409  // set the continuation-parameter:
1410  loaderPtr_->setParam (*iter, currVal);
1411  *iterCurrentVal = currVal;
1412 
1413  // perform the nonlinear solve:
1414  statNL = nlsOuterPtr_->solve (nlsPassingPtr_);
1415 
1416  int stepsTaken = nlsOuterPtr_->getNumIterations ();
1417  int stepsNotTaken = abs(maxOuterSteps_ - stepsTaken);
1418 
1419  nlsPassingPtr_ = 0;
1420 
1421  // Add to the stats:
1423 
1424  // Earlier (in initializeAll), return codes should have been set,
1425  // hopefully correctly...
1426  successBool = (statNL > 0);
1427 
1428  if (successBool) // success!
1429  {
1430  stepFinished = true;
1431 
1432  //if (numFailures <= 0 && stepsNotTaken > 7)
1433  if (numFailures <= 0)
1434  {
1435  stepSizeEst *= increaseContScalar_;
1436  }
1437 
1438  --numFailures;
1439  if (numFailures < 0) numFailures = 0;
1440 
1441  prevVal = currVal;
1442  currVal += stepSizeEst;
1443 
1444  if ( (*iterFinalVal >= 0 && currVal > *iterFinalVal) ||
1445  (*iterFinalVal < 0 && currVal < *iterFinalVal) )
1446  {
1447  currVal = *iterFinalVal;
1448  stepSizeEst = currVal - prevVal;
1449  }
1450 
1451  if (DEBUG_NONLINEAR)
1452  {
1453  Xyce::dout() << "\nRight before outputHOMOTOPY:" << std::endl;
1454  for (int ieric=0;ieric<paramNameList.size();++ieric)
1455  {
1456  Xyce::dout() << paramNameList[ieric] << "\t";
1457  Xyce::dout() << paramCurrentVal[ieric] << std::endl;
1458  }
1459  }
1460 
1461 
1462  outMgrPtr_->outputHomotopy(pdsMgrPtr_->getPDSComm()->comm(), paramNameList, paramCurrentVal, **nextSolVectorPtrPtr_);
1463  }
1464  else // failure!
1465  {
1466  stepSizeEst *= decreaseContScalar_;
1467 
1468  // restore the solution:
1469  **nextSolVectorPtrPtr_ = (*savedNextSolPtr_);
1470 
1471  ++numFailures;
1472  ++numTotalFailures;
1473 
1474  currVal = prevVal + stepSizeEst;
1475  }
1476  } // end of stepFinished while loop
1477 
1478  if (!successBool) // failure...
1479  {
1480  break;
1481  }
1482 
1483  ++contStep_;
1484 
1485  continuationLoopFinished =
1486  ( (*iterFinalVal >= 0 && prevVal >= *iterFinalVal) ||
1487  (*iterFinalVal < 0 && prevVal <= *iterFinalVal) );
1488 
1489  } // end of continuation loop.
1490 
1491  if (VERBOSE_NONLINEAR)
1492  Xyce::dout() << "currVal= " << currVal
1493  << " prevVal= " << prevVal
1494  << std::endl
1495  << std::endl
1496  << "Total number of failures = " << numTotalFailures << std::endl
1497  << "Number of actual steps = " << contStep_-1
1498  << std::endl;
1499 
1500  } // end of parameter loop.
1501 
1502  status = statNL;
1503 
1504  return status;
1505 }
1506 
1507 //-----------------------------------------------------------------------------
1508 // Function : TwoLevelNewton::algorithm5_
1509 //
1510 // Purpose : Same as algorithm0, but calls the inner solver rather
1511 // than the outer.
1512 //
1513 // Special Notes : This is best used if you want to use LOCA most of the
1514 // time, but not on the nonlinear poisson solve
1515 // (firstDCOPstep).
1516 //
1517 // Scope : private
1518 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1519 // Creation Date : 05/07/03
1520 //-----------------------------------------------------------------------------
1522 {
1523  int status = -1;
1524 
1525  if (VERBOSE_NONLINEAR)
1526  Xyce::dout() << std::endl << "Running algorithm 5:" << std::endl;
1527 
1528  // set up the local algorithm variable:
1529  int algorithm = twoLevelAlgorithm_;
1530  if ( externalAnalysisMode ==2) algorithm = twoLevelAlgorithmTran_;
1531 
1533 
1534  status = nlsInnerPtr_->solve ();
1535 
1536  // Now do conductance/capacitance extractions, if it makes sense.
1537  //if (!firstDCOPFlag_)
1538  //{
1539  //calcCouplingTerms_ ();
1540  //}
1541 
1542  return status;
1543 }
1544 
1545 
1546 //-----------------------------------------------------------------------------
1547 // Function : TwoLevelNewton::solve
1548 // Purpose :
1549 // Special Notes : Doesn't work with NOX yet...
1550 // Scope : public
1551 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1552 // Creation Date : 10/20/02
1553 //-----------------------------------------------------------------------------
1555 {
1556  int status = -1;
1557 
1558  firstDCOPFlag_ = false;
1559 
1560  TimeIntg::TimeIntInfo tiInfo;
1562  bool doubleDCOPEnable = tiInfo.doubleDCOPEnabled;
1563  int tiaMode = tiInfo.timeIntMode;
1564  int ddcopStep = tiInfo.doubleDCOPStep;
1565 
1566  if (doubleDCOPEnable && (tiaMode == 0) && (ddcopStep==0) )
1567  firstDCOPFlag_ = true;
1568 
1570 
1571  // set up the local algorithm variable:
1572  int algorithm = twoLevelAlgorithm_;
1573  if ( externalAnalysisMode ==2) algorithm = twoLevelAlgorithmTran_;
1574 
1575  // Some intitial setup:
1577  {
1578  numInterfaceNodesSetup_ = true;
1581 
1582  if (VERBOSE_NONLINEAR)
1583  Xyce::dout() << std::endl
1584  << "numSubProblems_ = " << numSubProblems_ << std::endl;
1585  }
1586 
1587  // Algorithm 0:
1588  // Full Newton, same as if two level was never called.
1589  if (algorithm == 0 || firstDCOPFlag_)
1590  {
1591  status = algorithm0_();
1592  }
1593  // else if algorithm 1:
1594  // outter loop is full Newton, inner loop PDE device only.
1595  else if (algorithm == 1)
1596  {
1597  status = algorithm1_ ();
1598  }
1599  // same as algorithm 1, but with continuation applied to the inner loop.
1600  else if (algorithm == 2)
1601  {
1602  status = algorithm2_ ();
1603  }
1604  // outter loop is circuit only, inner loop PDE device only, with
1605  // continuation.
1606  else if (algorithm == 3)
1607  {
1608  status = algorithm3_ ();
1609  }
1610  else if (algorithm == 4)
1611  {
1612  status = algorithm4_ ();
1613  }
1614  else if (algorithm == 5)
1615  {
1616  status = algorithm5_ ();
1617  }
1618  else
1619  {
1620  std::string tmp =
1621  "Two-Level Newton Algorithm set to invalid number.\n";
1622  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1623  }
1624 
1625  // Sometimes, when trying to debug, you want the code to exit the first
1626  // time the solver bombs. The totalSolveFailFlag gives that option.
1627  // Right before exiting, however, it instructs the device package to
1628  // output all its stuff. (tecplot files, text files, etc.)
1629  if (totalSolveFailFatal_ && status<=0)
1630  {
1631 #ifndef Xyce_PARALLEL_MPI
1633 #endif
1634 
1635  std::string tmp =
1636  "Two-Level Newton Algorithm failed to converge. Exiting.\n";
1637  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1638  }
1639 
1640  return status;
1641 }
1642 
1643 //-----------------------------------------------------------------------------
1644 // Function : TwoLevelNewton::calcCouplingTerms_
1645 //
1646 // Purpose : The purpose of this function is to manage the extraction
1647 // of conductances (coupling terms) from each PDE device.
1648 // These conductances may be neccessary if the outter Newton
1649 // loop is to be a ckt-only loop. In that case, the
1650 // PDE devices are replaced by much smaller conductance
1651 // based models.
1652 //
1653 // Special Notes : Performing a conductance calculation on a PDE device
1654 // requires a chain rule calculation, which includes several
1655 // linear solves of the Jacobian. It is because of the
1656 // required linear solve that some of the work is done
1657 // up here in the nonlinear solver, instead of having all
1658 // of it be done by the individual PDE devices.
1659 //
1660 // There may be a better solution later, but for the time
1661 // being I didn't want linear solves to be performed down
1662 // in the device package.
1663 //
1664 // Scope : public
1665 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1666 // Creation Date : 12/03/02
1667 //-----------------------------------------------------------------------------
1669 {
1670  bool bsuccess = true;
1671  bool tmpBool = true;
1672 
1673  char filename1[256];
1674 
1675  for (int ich = 0; ich < 256; ++ich)
1676  { filename1[ich] = 0; }
1677 
1678  // If the current mode is not "INNER_PROBLEM", then we need to re-load
1679  // the matrix, as the ckt part of the matrix needs to be kept out of
1680  // this calculation. Also, re-load Jacobian to make sure it is
1681  // completely up-to-date with the current solution.
1684  {
1686  }
1688 
1689  sprintf(filename1,"%s","tmpJac.txt");
1690  Linear::Matrix *A = lasSysPtr_->getJacobianMatrix();
1691  A->writeToFile(filename1);
1692 
1693  // save a copy of the RHS, as it is going to get mangled.
1694  Linear::Vector *rhsVecPtr = lasSysPtr_->getRHSVector();
1695  Linear::Vector *newtVecPtr = nlsOuterPtr_->NewtonVectorPtr_;
1696  *savedRHSPtr_ = *rhsVecPtr;
1697 
1698  // Loop over each sub-problem (PDE device).
1699  // Within each sub-problem, loop over each coupling term. (electrode)
1700  for (int iSubProblem=0; iSubProblem<numSubProblems_; ++iSubProblem)
1701  {
1702  int iCouple;
1703  int numCoupleTerms = numInterfaceNodes_[iSubProblem];
1704 
1705  if (VERBOSE_NONLINEAR)
1706  Xyce::dout() << "\n numCoupleTerms = " << numCoupleTerms << std::endl;
1707 
1708  for (iCouple=0;iCouple<numCoupleTerms;++iCouple)
1709  {
1710  // first zero out the RHS vector
1711  rhsVecPtr->putScalar(0.0);
1712 
1713  // load RHS vector with dFdV.
1714  tmpBool = loaderPtr_->loadCouplingRHS (iSubProblem, iCouple, rhsVecPtr );
1715  bsuccess = bsuccess && tmpBool;
1716 
1717  sprintf(filename1,"dfdv%02d.txt", iCouple);
1718  rhsVecPtr->writeToFile(filename1);
1719 
1720  // solve linear system to get dVdX.
1721  tmpBool = nlsOuterPtr_->newton_();
1722  bsuccess = bsuccess && tmpBool;
1723  numLinearSolves_ += 1;
1724 
1725  sprintf(filename1,"dvdx%02d.txt", iCouple);
1726  newtVecPtr->writeToFile(filename1);
1727 
1728  // copy the newton vector (result of linear solve) into the
1729  // RHSvector. Doing this b/c device package knows about rhs, but
1730  // doesn't know about newton.
1731  *rhsVecPtr = *newtVecPtr;
1732 
1733  // instruct each PDE device to finish the conductance calc.
1734  tmpBool = loaderPtr_->calcCouplingTerms (iSubProblem, iCouple, rhsVecPtr);
1735  bsuccess = bsuccess && tmpBool;
1736  }
1737  }
1738 
1739  // now restore everything, just in case:
1740  *rhsVecPtr = *savedRHSPtr_;
1741  twoLevelCouplingMode_ = savedMode;
1742 
1743  return bsuccess;
1744 }
1745 
1746 //-----------------------------------------------------------------------------
1747 // Function : TwoLevelNewton::continuationLoop_
1748 //
1749 // Purpose : Boundary condition continuation loop:
1750 //
1751 // Special Notes : This continuation loop allows for variable step size.
1752 //
1753 // Scope : public
1754 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1755 // Creation Date : 12/06/02
1756 //-----------------------------------------------------------------------------
1758 {
1759  int statInner;
1760  bool successBool;
1761  int contMaxTmp;
1762 
1763  // Instruct the PDE devices to set up the incremental
1764  // boundary conditions
1765  int suggestedSteps = 10; // this is a guess to the number of steps.
1766  suggestedSteps = loaderPtr_->enablePDEContinuation ();
1767 
1768  if (suggestedSteps < 1) suggestedSteps = 1;
1769  contMaxTmp = suggestedSteps;
1770 
1771  double stepSizeEst = 1.0/(static_cast<double>(contMaxTmp));
1772  double currentAlpha = 0.0;
1773  double previousAlpha = 0.0;
1774  int stepsLeft = contMaxTmp;
1775 
1776  // If the continuation loop has never been called before, then leave the
1777  // initial alpha at zero, because we have no solution to start from,
1778  // probably. If it has been called before, go ahead and take the first
1779  // step, as it should just be one step beyond an already obtained
1780  // solution.
1782  {
1783  currentAlpha = stepSizeEst;
1784  }
1786 
1787  contStep_=1;
1788  bool continuationLoopFinished = false;
1789 
1790  int numTotalFailures = 0;
1791 
1792  while (!continuationLoopFinished)
1793  {
1794  bool stepFinished = false;
1795  int numFailures = 0;
1796 
1797  while(!stepFinished)
1798  {
1799 
1800  stepsLeft = static_cast<int>((1.0-currentAlpha)/stepSizeEst) + 1;
1801 
1802  if (VERBOSE_NONLINEAR)
1803  Xyce::dout() << std::endl << "Continuation Step: " << contStep_
1804  << " Estimated Remaining Steps: " << stepsLeft
1805  << std::endl
1806  << "current alpha = " << currentAlpha
1807  << " prev. alpha = " << previousAlpha
1808  << " step = " << stepSizeEst
1809  << std::endl;
1810 
1811  if (stepsLeft < 0)
1812  {
1813  std::string tmp = "Continuation step estimate broken. Exiting\n";
1814  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::USR_FATAL_0, tmp);
1815  }
1816 
1817  // save a copy of solution:
1818  (*savedNextSolPtr_) = (**nextSolVectorPtrPtr_);
1819 
1820  std::string paramName = "pdealpha";
1821  loaderPtr_->setParam (paramName, currentAlpha);
1822 
1823  // perform the nonlinear solve:
1824  statInner = nlsInnerPtr_->solve (nlsPassingPtr_);
1825  nlsPassingPtr_ = 0;
1827 
1828  // Earlier (in initializeAll), return codes for the inner solver
1829  // should have been set so that "nearConvergence" is not considered
1830  // an adequate success. In other words, it returns a negative
1831  // number, not positive.
1832 
1833  if (DEBUG_NONLINEAR)
1834  Xyce::dout() << "Status of inner loop solve: " << statInner << std::endl;
1835 
1836  successBool = (statInner > 0);
1837 
1838  if (successBool) // success!
1839  {
1840  stepFinished = true;
1841 
1842  if (numFailures <= 0)
1843  {
1844  stepSizeEst *= increaseContScalar_;
1845  }
1846 
1847  --numFailures;
1848  if (numFailures < 0) numFailures = 0;
1849 
1850  previousAlpha = currentAlpha;
1851  currentAlpha += stepSizeEst;
1852 
1853  if (currentAlpha > 1.0)
1854  {
1855  currentAlpha = 1.0;
1856  stepSizeEst = currentAlpha - previousAlpha;
1857  }
1858  }
1859  else // failure!
1860  {
1861  stepSizeEst *= decreaseContScalar_;
1862 
1863  // restore the solution:
1864  (**nextSolVectorPtrPtr_) = (*savedNextSolPtr_);
1865 
1866  ++numFailures;
1867  ++numTotalFailures;
1868 
1869  currentAlpha = previousAlpha + stepSizeEst;
1870  }
1871  } // end of stepFinished while loop
1872 
1873  if (!successBool) // failure...
1874  {
1875  break;
1876  }
1877 
1878  ++contStep_;
1879  continuationLoopFinished = (previousAlpha >= 1.0);
1880 
1881  } // end of continuation loop.
1882 
1883  if (VERBOSE_NONLINEAR)
1884  Xyce::dout() << "current alpha = " << currentAlpha
1885  << " previous alpha = " << previousAlpha
1886  << std::endl
1887  << std::endl
1888  << "Total number of failures = " << numTotalFailures << std::endl
1889  << "Number of actual steps = " << contStep_-1
1890  << std::endl;
1891 
1893  contStep_=0;
1894 
1895  return statInner;
1896 }
1897 
1898 //-----------------------------------------------------------------------------
1899 // Function : TwoLevelNewton::locaLoop_
1900 //
1901 // Purpose : Boundary condition continuation (using LOCA) loop:
1902 //
1903 // Special Notes : This continuation loop allows for variable step size.
1904 //
1905 // Scope : public
1906 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1907 // Creation Date : 2/26/04
1908 //-----------------------------------------------------------------------------
1910 {
1911  int statInner;
1912 
1913  int suggestedSteps = loaderPtr_->enablePDEContinuation ();
1914 
1915  // this ifdef'd block of code was an attempt to adjust loca parameters
1916  // in-situ. If the voltage change is really, really small, then there
1917  // isn't much point in doing a continuation, so I wanted to have to
1918  // option to on-the-fly switch to straight Newton.
1919  //
1920  // Unfortunately, it doesn't work at the moment - the second time it gets
1921  // called, everything goes haywire. ERK 2/25/04.
1922 #if 0
1923  Xyce::dout() << "suggested steps are: " << suggestedSteps << std::endl;
1924 
1925  Util::ParamList::const_iterator it_tpL;
1926  for (it_tpL = innerSolverOptions_.params.begin();
1927  it_tpL != innerSolverOptions_.params.end();
1928  ++it_tpL)
1929  {
1930  ExtendedString tmpTag = it_tpL->tag ();
1931  tmpTag.toUpper ();
1932 
1933  Xyce::dout() << "tmpTag = " << tmpTag << std::endl;
1934 
1935  if (tmpTag == "CONTINUATION")
1936  {
1937  if (suggestedSteps <= 1) // then just do one newton step.
1938  {
1939  Xyce::dout() << "Setting the solver type to 0" << std::endl;
1940  suggestedSteps = 1;
1941  it_tpL->setVal(0);
1942  }
1943  else
1944  {
1945  it_tpL->setVal(1);
1946  }
1947  }
1948  }
1949 
1952 #endif
1953  statInner = nlsInnerPtr_->solve (nlsPassingPtr_);
1954 
1955  nlsPassingPtr_ = 0;
1957 
1959 
1960  return statInner;
1961 }
1962 
1963 //-----------------------------------------------------------------------------
1964 // Function : TwoLevelNewton::enableSensitivity
1965 //
1966 // Purpose : This re-sets the code for a sensitivity calculation.
1967 // Mainly, it loads the jacobian and rhs vectors in FULL
1968 // newton mode, if neccessary.
1969 //
1970 // Special Notes : Since the implementation of the "fullNewtonEnforce"
1971 // parameter, this has become less crucial. When this option
1972 // is enabled (the default), then the last loads prior to this
1973 // function being called were full newton loads, so there is
1974 // no need to re-do them.
1975 //
1976 // Scope : public
1977 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1978 // Creation Date : 04/21/03
1979 //-----------------------------------------------------------------------------
1981 {
1982  if (VERBOSE_NONLINEAR)
1983  Xyce::dout() << std::endl
1984  << Xyce::section_divider << std::endl
1985  << "TwoLevelNewton::enableSensitivity " << std::endl;
1986 
1987  bool bsuccess = true;
1988  bool tmpBool = true;
1989 
1991  tmpBool = NonLinearSolver::rhs_ (); bsuccess = bsuccess && tmpBool;
1992  tmpBool = NonLinearSolver::jacobian_ (); bsuccess = bsuccess && tmpBool;
1993 
1994  if (VERBOSE_NONLINEAR) {
1995  // print out the norm info for this "full newton" residual:
1996  double maxNormRHS_=0, twoNormRHS_ = 0.0;
1997  rhsVectorPtr_->infNorm(&maxNormRHS_);
1998  rhsVectorPtr_->lpNorm(2, &twoNormRHS_);
1999  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2000  Xyce::dout() << std::endl;
2001  Xyce::dout() << "Max. norm of full Newton RHS: " << maxNormRHS_ << std::endl;
2002  Xyce::dout() << " 2-norm of full Newton RHS: " << twoNormRHS_ << std::endl;
2003  Xyce::dout() << Xyce::section_divider << std::endl;
2004  }
2005 
2006  if (DEBUG_NONLINEAR)
2007  {
2008 
2009  static int callsSens = 0;
2010  char filename1[256]; for (int ich = 0; ich < 256; ++ich) filename1[ich] = 0;
2011  char filename2[256]; for (int ich = 0; ich < 256; ++ich) filename2[ich] = 0;
2012 
2013  sprintf(filename1, "matrixTmp%d.txt",callsSens);
2014  Linear::Matrix *A = lasSysPtr_->getJacobianMatrix();
2015  A->writeToFile(filename1);
2016 
2017 
2018  Linear::Vector *b = lasSysPtr_->getRHSVector();
2019  sprintf(filename2, "rhsTmp%d.txt", callsSens);
2020  int size, i;
2021  FILE *fp1;
2022 
2023 #ifndef Xyce_PARALLEL_MPI
2024  fp1 = fopen(filename2,"w");
2025  size = lasSysPtr_->getSolutionSize();
2026  for (i=0;i<size;++i)
2027  {
2028  double output = b->getElementByGlobalIndex(i);
2029  fprintf(fp1,"%25.18e\n",output);
2030  }
2031  fclose(fp1);
2032 #endif
2033 
2034  Linear::Vector *x = (*nextSolVectorPtrPtr_);
2035  sprintf(filename2, "solTmp%d.txt", callsSens);
2036 
2037 #ifndef Xyce_PARALLEL_MPI
2038  fp1 = fopen(filename2,"w");
2039  size = lasSysPtr_->getSolutionSize();
2040  for (i=0;i<size;++i)
2041  {
2042  double output = x->getElementByGlobalIndex(i);
2043  fprintf(fp1,"%25.18e\n",output);
2044  }
2045  fclose(fp1);
2046 #endif
2047 
2048  ++callsSens;
2049  }
2050  return bsuccess;
2051 }
2052 
2053 //-----------------------------------------------------------------------------
2054 // Dummy function since homotopy doesn't work with 2-level. (for the outer loop)
2055 //-----------------------------------------------------------------------------
2057 {
2058  return true;
2059 }
2060 
2061 //-----------------------------------------------------------------------------
2062 // Dummy function ... for now. This probably needs to get revamped.
2063 //-----------------------------------------------------------------------------
2065 {
2066  return 0;
2067 }
2068 
2069 //-----------------------------------------------------------------------------
2070 // Dummy function ... for now. This probably needs to get revamped.
2071 //-----------------------------------------------------------------------------
2073 {
2074  return 0;
2075 }
2076 
2077 } // namespace Nonlinear
2078 } // namespace Xyce
virtual int getMaxNormFindex() const =0
std::vector< std::string > paramNameList
bool registerLoader(Loader::NonlinearEquationLoader *ptr)
bool setTwoLevelTranOptions(const Util::OptionBlock &OB)
bool loadCouplingRHS(int iSubProblem, int iCouple, Linear::Vector *dfdvPtr)
void setAnalysisMode(AnalysisMode mode)
virtual int solve(NonLinearSolver *nlsTmpPtr=NULL)=0
bool registerLinearSystem(Linear::System *ptr)
virtual bool setTranOptions(const Util::OptionBlock &OB)=0
virtual int takeFirstSolveStep(NonLinearSolver *nlsTmpPtr=NULL)
Pure virtual class to augment a linear system.
bool setTranOptions(const Util::OptionBlock &OB)
virtual int getNumIterations() const =0
bool setTwoLevelLocaOptions(const Util::OptionBlock &OB)
bool setTwoLevelOptions(const Util::OptionBlock &OB)
Analysis::AnalysisManager * analysisManager_
virtual void setReturnCodes(const ReturnCodes &retCodesTmp)
bool setLocaOptions(const Util::OptionBlock &OB)
bool registerAnalysisManager(Analysis::AnalysisManager *analysis_manager)
bool setHBOptions(const Util::OptionBlock &OB)
virtual bool setPetraOptions(const Util::OptionBlock &OB)
void getTimeIntInfo(const AnalysisManager &analysis_manager, TimeIntg::TimeIntInfo &tiInfo)
int solve(NonLinearSolver *nlsTmpPtr=NULL)
bool setParam(std::string &name, double val, bool overrideOriginal=false)
bool registerLoader(Loader::NonlinearEquationLoader *ptr)
bool setOptions(const Util::OptionBlock &OB)
bool calcCouplingTerms(int iSubProblem, int iCouple, const Linear::Vector *dxdvPtr)
bool registerTwoLevelSolver(TwoLevelNewton *ptr)
virtual unsigned int getTotalNumLinearIters()
virtual unsigned int getTotalNumLinearIters()
bool registerAnalysisManager(Analysis::AnalysisManager *tmp_anaIntPtr)
bool setPetraOptions(const Util::OptionBlock &OB)
void getNumInterfaceNodes(std::vector< int > &numINodes)
virtual void setAnalysisMode(AnalysisMode mode)=0
bool registerOutputMgr(IO::OutputMgr *ptr)
Loader::NonlinearEquationLoader * loaderPtr_
bool registerOutputMgr(IO::OutputMgr *outPtr)
void printStepInfo_(int step, int success, TwoLevelNewtonMode solveType)
virtual bool setOptions(const Util::OptionBlock &OB)=0
virtual double getMaxNormF() const =0
virtual bool output() const
Definition: N_LOA_Loader.h:260
virtual bool setLocaOptions(const Util::OptionBlock &OB)