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