Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_TIA_BackwardDifferentiation15.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_TIA_BackwardDifferentiation15.C,v $
27 //
28 // Purpose : This file contains the functions which define the
29 // backward differentiation, order 1-5, class.
30 //
31 // Special Notes :
32 //
33 // Creator : Todd Coffey
34 //
35 // Creation Date : 2/16/04
36 //
37 // Revision Information:
38 // ---------------------
39 //
40 // Revision Number: $Revision: 1.148 $
41 //
42 // Revision Date : $Date: 2014/02/24 23:49:27 $
43 //
44 // Current Owner : $Author: tvrusso $
45 //-----------------------------------------------------------------------------
46 
47 #include <Xyce_config.h>
48 
49 
50 // ---------- Standard Includes ----------
51 #include <N_UTL_Misc.h>
52 
53 #ifdef HAVE_IOSTREAM
54 #include <iostream>
55 #else
56 #include <iostream.h>
57 #endif
58 
59 // ---------- Xyce Includes ----------
62 #include <N_TIA_StepErrorControl.h>
63 #include <N_TIA_DataStore.h>
64 #include <N_TIA_TIAParams.h>
65 #include <N_ERH_ErrorMgr.h>
66 
67 #include <N_LAS_Vector.h>
68 #include <N_LAS_Matrix.h>
69 #include <N_LAS_BlockVector.h>
70 #include <N_LAS_System.h>
71 
72 #include <N_PDS_Comm.h>
73 #include <N_PDS_Manager.h>
74 
75 using namespace std;
76 
77 //-----------------------------------------------------------------------------
78 // Function : N_TIA_BackwardDifferentiation15::
79 // N_TIA_BackwardDifferentiation15
80 // Purpose : constructor
81 // Special Notes :
82 // Scope : public
83 // Creator : Todd Coffey, SNL
84 // Creation Date : 2/16/04
85 //-----------------------------------------------------------------------------
86 
88  (N_TIA_TIAParams & tiaP,
89  N_TIA_StepErrorControl & secTmp,
90  N_TIA_DataStore & dsTmp)
91 : N_TIA_TimeIntegrationMethod(tiaP,secTmp,dsTmp)
92 {
93  leadingCoeff = 1;
94  sec.maxOrder_=(Xycemin(5,tiaParams.maxOrder));
95  sec.minOrder_=(Xycemax(1,tiaParams.minOrder));
96  if (sec.minOrder_ > sec.maxOrder_)
97  {
98  sec.minOrder_ = sec.maxOrder_;
99  }
100  timept_ = -1.0;
101  return ;
102 }
103 
104 //-----------------------------------------------------------------------------
105 // Function : N_TIA_BackwardDifferentiation15::obtainPredictor
106 // Purpose : Calculate predictor
107 // Special Notes : stored in ds.xn0Ptr,qn0Ptr,qpn0Ptr
108 // Scope : public
109 // Creator : Todd Coffey, SNL
110 // Creation Date : 2/16/04
111 //-----------------------------------------------------------------------------
112 
114 {
115  // prepare history array for prediction
116  for (int i=sec.nscsco_;i<=sec.currentOrder_;++i)
117  {
118  (ds.xHistory[i])->scale(sec.beta_[i]);
119  (ds.qHistory[i])->scale(sec.beta_[i]);
120  (ds.sHistory[i])->scale(sec.beta_[i]);
121  (ds.stoHistory[i])->scale(sec.beta_[i]);
122  (ds.stoLeadCurrQCompHistory[i])->scale(sec.beta_[i]);
123  }
124 
125  // evaluate predictor
126  *ds.xn0Ptr = *(ds.xHistory[0]);
127  *ds.qn0Ptr = *(ds.qHistory[0]);
128  *ds.sn0Ptr = *(ds.sHistory[0]);
129  *ds.ston0Ptr = *(ds.stoHistory[0]);
130  *ds.stoQCn0Ptr = *(ds.stoLeadCurrQCompHistory[0]);
131 
132  ds.qpn0Ptr->putScalar(0.0);
133  ds.spn0Ptr->putScalar(0.0);
134  ds.stopn0Ptr->putScalar(0.0);
135  ds.stoQCpn0Ptr->putScalar(0.0);
136  for (int i=1;i<=sec.currentOrder_;++i)
137  {
138  ds.xn0Ptr->linearCombo(1.0,*(ds.xHistory[i]),1.0,*ds.xn0Ptr);
139  ds.qn0Ptr->linearCombo(1.0,*(ds.qHistory[i]),1.0,*ds.qn0Ptr);
140  ds.sn0Ptr->linearCombo(1.0,*(ds.sHistory[i]),1.0,*ds.sn0Ptr);
141  ds.ston0Ptr->linearCombo(1.0,*(ds.stoHistory[i]),1.0,*ds.ston0Ptr);
142  ds.stoQCn0Ptr->linearCombo(1.0,*(ds.stoLeadCurrQCompHistory[i]),1.0,*ds.stoQCn0Ptr);
143  ds.qpn0Ptr->linearCombo(sec.gamma_[i],*(ds.qHistory[i]),1.0,*ds.qpn0Ptr);
144  ds.spn0Ptr->linearCombo(sec.gamma_[i],*(ds.sHistory[i]),1.0,*ds.spn0Ptr);
145  ds.stopn0Ptr->linearCombo(sec.gamma_[i],*(ds.stoHistory[i]),1.0,*ds.stopn0Ptr);
146  ds.stoQCpn0Ptr->linearCombo(sec.gamma_[i],*(ds.stoLeadCurrQCompHistory[i]),1.0,*ds.stoQCpn0Ptr);
147 
148  }
149 
150 #ifdef Xyce_DEBUG_TIME
151  Xyce::dout().width(21); cout.precision(13); cout.setf(std::ios::scientific);
152 
153  if (tiaParams.debugLevel > 1)
154  {
155  Xyce::dout() << std::endl;
156  Xyce::dout() << Xyce::section_divider << std::endl;
157  Xyce::dout() << " N_TIA_BackwardDifferentiation15::obtainPredictor" << std::endl;
158  Xyce::dout() << "\n currentOrder = " << sec.currentOrder_ << endl;
159  Xyce::dout() << "\n sec.nscsco_: " << sec.nscsco_ << endl;
160  for (int i=0; i<=sec.currentOrder_ ; ++i)
161  Xyce::dout() << "\n sec.beta_[" << i << "] = " << sec.beta_[i] << "\n" << endl;
162  for (int i=0; i<=sec.currentOrder_ ; ++i)
163  {
164  Xyce::dout() << "\n xHistory["<< i << "]: \n" << endl;
165  (ds.xHistory[i])->printPetraObject(Xyce::dout());
166  Xyce::dout() << endl;
167  }
168  for (int i=0; i<=sec.currentOrder_ ; ++i)
169  {
170  Xyce::dout() << "\n qHistory["<< i << "]: \n" << endl;
171  (ds.qHistory[i])->printPetraObject(Xyce::dout());
172  Xyce::dout() << endl;
173  }
174  for (int i=0; i<=sec.currentOrder_ ; ++i)
175  {
176  Xyce::dout() << "\n sHistory["<< i << "]: \n" << endl;
177  (ds.sHistory[i])->printPetraObject(Xyce::dout());
178  Xyce::dout() << endl;
179  }
180  Xyce::dout() << "\n xn0: \n" << endl;
181  ds.xn0Ptr->printPetraObject(Xyce::dout());
182  Xyce::dout() << endl;
183  Xyce::dout() << "\n qn0: \n" << endl;
184  ds.qn0Ptr->printPetraObject(Xyce::dout());
185  Xyce::dout() << endl;
186  Xyce::dout() << "\n qpn0: \n" << endl;
187  ds.qpn0Ptr->printPetraObject(Xyce::dout());
188  Xyce::dout() << endl;
189  Xyce::dout() << "\n sn0: \n" << endl;
190  ds.sn0Ptr->printPetraObject(Xyce::dout());
191  Xyce::dout() << endl;
192  Xyce::dout() << "\n spn0: \n" << endl;
193  ds.spn0Ptr->printPetraObject(Xyce::dout());
194  Xyce::dout() << endl;
195  Xyce::dout() << "\n stoQCn0Ptr: \n" << endl;
196  ds.stoQCn0Ptr->printPetraObject(Xyce::dout());
197  Xyce::dout() << endl;
198  Xyce::dout() << "\n stoQCpn0Ptr: \n" << endl;
199  ds.stoQCpn0Ptr->printPetraObject(Xyce::dout());
200  Xyce::dout() << endl;
201  Xyce::dout() << Xyce::section_divider << std::endl;
202  }
203 #endif // Xyce_DEBUG_TIME
204  // copy the prediction into the next solution:
205  *(ds.nextSolutionPtr) = *(ds.xn0Ptr);
206 
207  return;
208 }
209 
210 //-----------------------------------------------------------------------------
211 // Function : N_TIA_BackwardDifferentiation15::obtainResidual
212 // Purpose : Calculate Residual
213 // Special Notes :
214 // Scope : public
215 // Creator : Todd Coffey, SNL
216 // Creation Date : 3/8/04
217 //-----------------------------------------------------------------------------
218 
220 {
221  // output: ds.RHSVectorPtr
222 
223  // This function returns the following residual:
224  // $qpn0 - (sec.alphas_/hn)(Q(x)-qn0)+F(x)-B(t)$
225 
226  // Note: ds.nextSolutionPtr is used to get Q,F,B in N_ANP_AnalysisManager::loadRHS.
227  ds.RHSVectorPtr->linearCombo(1.0,*ds.daeQVectorPtr,-1.0,*ds.qn0Ptr);
228  ds.RHSVectorPtr->linearCombo(1.0,*ds.qpn0Ptr,-sec.alphas_/sec.currentTimeStep,*ds.RHSVectorPtr);
229 
230 #ifdef Xyce_DEBUG_TIME
231  if (tiaParams.debugLevel > 1)
232  {
233  Xyce::dout() << std::endl;
234  Xyce::dout() << Xyce::section_divider << std::endl;
235  Xyce::dout() << " N_TIA_BackwardDifferentiation15::obtainResidual" << std::endl;
236  Xyce::dout() << "\n t = " << sec.nextTime << "\n" << endl;
237  Xyce::dout() << "\n solution: \n" << endl;
238  ds.nextSolutionPtr->printPetraObject(Xyce::dout());
239  Xyce::dout() << "\n daeQVector: \n" << endl;
240  ds.daeQVectorPtr->printPetraObject(Xyce::dout());
241  Xyce::dout() << "\n qn0: \n" << endl;
242  ds.qn0Ptr->printPetraObject(Xyce::dout());
243  Xyce::dout() << "\n qpn0: \n" << endl;
244  ds.qpn0Ptr->printPetraObject(Xyce::dout());
245  Xyce::dout() << "\n sec.alphas_/hn: " << sec.alphas_/sec.currentTimeStep << "\n" << endl;
246  Xyce::dout() << "\n daeFVector: \n" << endl;
247  ds.daeFVectorPtr->printPetraObject(Xyce::dout());
248 
249  Xyce::dout() << "\n dQdt-vector: \n" << endl;
250  ds.RHSVectorPtr->printPetraObject(Xyce::dout());
251  Xyce::dout() << endl;
252  }
253 #endif
254 
255  ds.RHSVectorPtr->linearCombo(1.0,*ds.RHSVectorPtr,+1.0,*ds.daeFVectorPtr);
256 
257  // since the nonlinear solver is expecting a -f, scale by -1.0:
258  ds.RHSVectorPtr->scale(-1.0);
259 
260  // if voltage limiting is on, add it in:
261  if (ds.limiterFlag)
262  {
263  (ds.dQdxdVpVectorPtr)->scale( -sec.alphas_/sec.currentTimeStep );
264 
265  (ds.RHSVectorPtr)->daxpy(
266  *(ds.RHSVectorPtr), +1.0, *(ds.dQdxdVpVectorPtr));
267 
268  (ds.RHSVectorPtr)->daxpy(
269  *(ds.RHSVectorPtr), +1.0, *(ds.dFdxdVpVectorPtr));
270  }
271 
272 #ifdef Xyce_DEBUG_TIME
273  if (tiaParams.debugLevel > 1)
274  {
275  Xyce::dout() << "\n Residual-vector: \n" << endl;
276  Xyce::dout() << "-(qpn0-(sec.alpha_s/h)*(Q-qn0)+F-B) \n" << endl;
277  ds.RHSVectorPtr->printPetraObject(Xyce::dout());
278  Xyce::dout() << Xyce::section_divider << std::endl;
279  Xyce::dout() << endl;
280  }
281 #endif
282 
283 }
284 
285 //-----------------------------------------------------------------------------
286 // Function : N_TIA_BackwardDifferentiation15::obtainJacobian
287 // Purpose : Calculate Jacobian
288 // Special Notes :
289 // Scope : public
290 // Creator : Todd Coffey, SNL
291 // Creation Date : 3/8/04
292 //-----------------------------------------------------------------------------
293 
295 {
296 
297 #ifdef Xyce_DEBUG_TIME
298  if (tiaParams.debugLevel > 1)
299  {
300  Xyce::dout() << std::endl;
301  Xyce::dout() << Xyce::section_divider << std::endl;
302  Xyce::dout() << " N_TIA_BackwardDifferentiation15::obtainJacobian" << std::endl;
303  }
304 #endif
305  // output: ds.JMatrixPtr
306 
307  // This function returns the following matrix:
308  // $-(sec.alphas_/hn)dQdx(x)+dFdx$
309 
310  // Note: ds.nextSolutionPtr is used to get dQdx,dFdx in N_ANP_AnalysisManager::loadJacobian.
311 // ds.JmatrixPtr->linearCombo(-sec.alphas_/sec.currentTimeStep,*ds.dQdxMatrixPtr,+1.0,*ds.dFdxMatrixPtr);
312 
313  N_LAS_Matrix & dQdx = *(ds.dQdxMatrixPtr);
314  N_LAS_Matrix & dFdx = *(ds.dFdxMatrixPtr);
315  N_LAS_Matrix & Jac = *(ds.JMatrixPtr);
316 
317  double qscalar(-sec.alphas_/sec.currentTimeStep);
318 
319  Jac.linearCombo( qscalar, dQdx, 1.0, dFdx );
320 
321 #ifdef Xyce_DEBUG_TIME
322  if (tiaParams.debugLevel > 1)
323  {
324  Xyce::dout() << "\n dFdx:" <<endl;
325  dFdx.printPetraObject(Xyce::dout());
326  Xyce::dout() << "\n Total Jacobian:" <<endl;
327  Jac.printPetraObject(Xyce::dout());
328 // for (int i=0;i<3;++i)
329 // {
330 // printf("[ %25.20g\t%25.20g\t%25.20g ]\n",Jac[i][0],Jac[i][1],Jac[i][2]);
331 // }
332 
333  Xyce::dout() << Xyce::section_divider << std::endl;
334  Xyce::dout() << endl;
335  }
336 #endif
337 
338 }
339 
340 //-----------------------------------------------------------------------------
341 // Function : N_TIA_BackwardDifferentiation15::interpolateSolution
342 // Purpose : Interpolate solution approximation at prescribed time point.
343 // Special Notes : This routine computes the solution at the output
344 // : timepoint by intepolation of the history using the order
345 // : used for the most recent completed step, orderUsed.
346 // : The output is put into ds.tmpSolVectorPtr.
347 // Scope : public
348 // Creator : Todd Coffey, SNL
349 // Creation Date : 2/16/04
350 //-----------------------------------------------------------------------------
351 
353  N_LAS_Vector * tmpSolVectorPtr, std::vector<N_LAS_Vector*> & historyVec)
354 {
355  // 03/23/04 tscoffe: Currently this code is nearly identical to the IDA code
356  // for interpolating to an output time. Either we acknowledge the copyright,
357  // the list of conditions in the license and the disclaimer or we rewrite this
358  // function. The IDA license is included after this routine.
359  double tfuzz; // fuzz factor to check for valid output time
360  double tp; // approximately t_{n-1}
361  double delt; // distance between timepoint and currentTime
362  double c = 1.0; // coefficient for interpolation
363  double gam; // coefficient for interpolation
364  int kord; // order of interpolation
365  double tn = sec.currentTime;
366  double hh = sec.currentTimeStep;
367  double hused = sec.usedStep_;
368  int kused = sec.usedOrder_;
369  // TVR: changed line below in addressing bug 1258
370  // This is what was here prior to my change:
371  // double uround = 0.0; // unit round-off (set to zero for now)
372  // The value below is a WAG
373  double uround = N_UTL_MachineDependentParams::MachinePrecision();
374 
375  tfuzz = 100 * uround * (tn + hh);
376  tp = tn - hused - tfuzz;
377 
378  if ( (timepoint - tp)*hh < 0.0 )
379  return false;
380 
381  *tmpSolVectorPtr = *(historyVec[0]);
382  kord = kused;
383  if ( (kused == 0) || (timepoint == tn) )
384  kord = 1;
385 
386  delt = timepoint - tn;
387  gam = delt/sec.psi_[0];
388  for (int j=1 ; j <= kord ; ++j)
389  {
390  c = c*gam;
391  gam = (delt + sec.psi_[j-1])/sec.psi_[j];
392  tmpSolVectorPtr->linearCombo(1.0,*tmpSolVectorPtr,c,*(historyVec[j]));
393  }
394  return true;
395 }
396 
397 //-----------------------------------------------------------------------------
398 // Function : N_TIA_BackwardDifferentiation15::interpolateMPDESolution
399 // Purpose : Interpolate solution approximation at prescribed time points.
400 // Special Notes : This routine computes the solution at the output
401 // : timepoints by intepolation of the history using the order
402 // : used for the most recent completed step, orderUsed.
403 // : The output is put into provided N_LAS_Vector pointer.
404 // : The interpolation is as follows:
405 // : tmpSolVectorPtr->block(i) is interpolated at timepoint(i)
406 // : Therefore, if you want them all interpolated at the same time,
407 // : then use timepoint(i) = timepoint(0) forall i
408 // : or use interpolateSolution.
409 // Scope : public
410 // Creator : Todd Coffey, Eric Keiter, SNL
411 // Creation Date : 11/28/06
412 //-----------------------------------------------------------------------------
413 
414 bool N_TIA_BackwardDifferentiation15::interpolateMPDESolution(std::vector<double>& timepoint,
415  N_LAS_Vector * tmpSolVectorPtr)
416 {
417 /*
418 #ifdef Xyce_PARALLEL_MPI
419  std::string msg = "N_TIA_BackwardDifferentiation15::interpolateMPDESolution: ";
420  msg += "Not set up for Parallel yet";
421  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
422  return(false);
423 #endif
424 */
425 
426  N_LAS_BlockVector * blockTempSolVectorPtr =
427  dynamic_cast<N_LAS_BlockVector*>(tmpSolVectorPtr);
428  if (blockTempSolVectorPtr == NULL)
429  {
430  std::string msg = "N_TIA_BackwardDifferentiation15::interpolateMPDESolution: ";
431  msg += "N_LAS_Vector tmpSolVectorPtr is not of type N_LAS_BlockVector";
432  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
433  return(false);
434  }
435 
436  double tfuzz; // fuzz factor to check for valid output time
437  double tp; // approximately t_{n-1}
438  int numblocks = timepoint.size();
439  int blockCount = blockTempSolVectorPtr->blockCount();
440  if (numblocks > blockCount)
441  {
442  std::string msg = "N_TIA_BackwardDifferentiation15::interpolateMPDESolution: ";
443  msg += "Number of time points requested is greater than number of fast time points in MPDE block vector";
444  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
445  return(false);
446  }
447  double delt;
448  double c = 1.0;
449  double gam;
450  int kord; // order of interpolation
451  double tn = sec.currentTime;
452  double hh = sec.currentTimeStep;
453  double hused = sec.usedStep_;
454  int kused = sec.usedOrder_;
455  double uround = 0.0; // unit round-off (set to zero for now)
456 
457  tfuzz = 100 * uround * (tn + hh);
458  tp = tn - hused - tfuzz;
459  for (int i=0; i<numblocks ; ++i)
460  {
461  if ( (timepoint[i] - tp)*hh < 0.0 )
462  return false;
463  }
464 
465  *tmpSolVectorPtr = *(ds.xHistory[0]);
466 
467  N_LAS_Vector * solVectorPtr;
468  N_LAS_Vector * xHistoryVectorPtr;
469  // Loop over blocks first so that maximal order can be maintained
470  for (int i=0; i < numblocks ; ++i)
471  {
472  if ((kused == 0) || (timepoint[i] == tn)) { kord = 1; }
473  else { kord = kused; }
474  solVectorPtr = &(blockTempSolVectorPtr->block(i));
475  c = 1.0;
476  delt = timepoint[i] - tn;
477  gam = delt/sec.psi_[0];
478  for (int j=1 ; j <= kord ; ++j)
479  {
480  c = c*gam;
481  gam = (delt + sec.psi_[j-1])/sec.psi_[j];
482  N_LAS_BlockVector * blockXHistoryVectorPtr =
483  dynamic_cast<N_LAS_BlockVector*>(ds.xHistory[j]);
484  if (blockXHistoryVectorPtr == NULL)
485  {
486  Xyce::Report::DevelFatal0().in("N_TIA_BackwardDifferentiation15::interpolateMPDESolution") << "N_LAS_Vector ds.xHistory[j] is not of type N_LAS_BlockVector\n j = " << j;
487  return(false);
488  }
489  xHistoryVectorPtr = &(blockXHistoryVectorPtr->block(i));
490  solVectorPtr->linearCombo(1.0,*solVectorPtr,c,*xHistoryVectorPtr);
491  }
492  }
493  return true;
494 }
495 
496 //-----------------------------------------------------------------------------
497 // Function : N_TIA_BackwardDifferentiation15::printMPDEOutputSolution()
498 // Purpose : Print transient output from MPDE simulation
499 // Special Notes : This routine uses interpolateMPDESolution.
500 // Scope : public
501 // Creator : Todd Coffey, SNL, 1414
502 // Creation Date : 11/28/06
503 //-----------------------------------------------------------------------------
505  RefCountPtr< N_ANP_OutputMgrAdapter > outputMgrAdapterRCPtr,
506  const double time,
507  N_LAS_Vector * solnVecPtr,
508  const std::vector<double> & fastTimes )
509 {
510 #ifdef Xyce_DEBUG_TIME
511  if (tiaParams.debugLevel > 0)
512  {
513  Xyce::dout() << std::endl;
514  Xyce::dout() << Xyce::section_divider << std::endl;
515  Xyce::dout() << " N_TIA_BackwardDifferentiation15::printMPDEOutputSolution" << std::endl;
516  }
517 #endif // Xyce_DEBUG_TIME
518  double timestep = sec.lastAttemptedTimeStep;
519  double lasttime = sec.currentTime - timestep;
520  double tn = sec.currentTime;
521  // Set these values up to read output time intervals. FIXME
522  double beg_of_output_time_interval = lasttime;
523  double end_of_output_time_interval = tn;
524  double start_time = max(lasttime,beg_of_output_time_interval);
525  double stop_time = min(tn,end_of_output_time_interval);
526 #ifdef Xyce_DEBUG_TIME
527  if (tiaParams.debugLevel > 0)
528  {
529  Xyce::dout() << "timestep = " << timestep << endl;
530  Xyce::dout() << "lasttime = " << lasttime << endl;
531  Xyce::dout() << "tn = " << tn << endl;
532  Xyce::dout() << "beg_of_output_time_interval = " << beg_of_output_time_interval << endl;
533  Xyce::dout() << "end_of_output_time_interval = " << end_of_output_time_interval << endl;
534  Xyce::dout() << "start_time = " << start_time << endl;
535  Xyce::dout() << "stop_time = " << stop_time << endl;
536  }
537 #endif // Xyce_DEBUG_TIME
538 
539 
540  N_LAS_BlockVector * blockTmpSolVectorPtr =
541  dynamic_cast<N_LAS_BlockVector*>(ds.tmpSolVectorPtr);
542 
543  if (blockTmpSolVectorPtr == NULL)
544  {
545  std::string msg = "N_TIA_BackwardDifferentiation15::printMPDEOutputSolution: ";
546  msg += "N_LAS_Vector ds.tmpSolVectorPtr is not of type N_LAS_BlockVector";
547  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
548  return(false);
549  }
550  int blockCount = blockTmpSolVectorPtr->blockCount();
551 
552  // Create list of timepoints to interpolate (along characteristic curve)
553  double T2 = fastTimes.back();
554  //double charcross = start_time - floor(start_time/T2)*T2; // (start_time mod T2)
555  double charcross = fmod(start_time,T2); // (start_time mod T2)
556  int s_ind_0 = -1;
557  // find s_ind_0 = first fast time point >= charcross.
558  // This could probably be made faster: FIXME
559  for (int i=0 ; i<=blockCount ; ++i)
560  {
561  if (fastTimes[i] >= charcross)
562  {
563  s_ind_0 = i;
564  break;
565  }
566  }
567  if (s_ind_0 == -1)
568  {
569  std::string msg = "N_TIA_BackwardDifferentiation15::printMPDEOutputSolution: ";
570  msg += "Cannot find where characteristic curve crosses fast time slice at start_time";
571  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
572  return(false);
573  }
574  std::vector<double> h2(blockCount,0);
575  for (int j=0 ; j < blockCount ; ++j)
576  {
577  h2[j] = fastTimes[j+1] - fastTimes[j];
578  }
579  std::vector<double> ti;
580  //double first_interp = floor(start_time/T2)*T2 + fastTimes[s_ind_0];
581  double first_interp = start_time - charcross + fastTimes[s_ind_0];
582 #ifdef Xyce_DEBUG_TIME
583  if (tiaParams.debugLevel > 0)
584  {
585  Xyce::dout() << "first_interp = " << first_interp << endl;
586  }
587 #endif // Xyce_DEBUG_TIME
588  if (s_ind_0 == blockCount) { s_ind_0 = 0; };
589  // Don't interpolate the first point
590  double eps = fabs(start_time)*1.0e-6;
591  if ( fabs(first_interp-timept_) <= eps )
592  {
593  first_interp += h2[s_ind_0];
594  s_ind_0++;
595  if (s_ind_0 == blockCount) { s_ind_0 = 0; };
596 #ifdef Xyce_DEBUG_TIME
597  if (tiaParams.debugLevel > 0)
598  {
599  Xyce::dout() << "Moving first_interp forward to avoid duplicate outputs: " << first_interp << endl;
600  }
601 #endif // Xyce_DEBUG_TIME
602  }
603  int sn = s_ind_0;
604  double t = first_interp;
605  while (t <= stop_time)
606  {
607  ti.push_back(t);
608  t += h2[sn];
609  sn++;
610  if (sn >= blockCount) { sn = 0; }
611  }
612 #ifdef Xyce_DEBUG_TIME
613  if (tiaParams.debugLevel > 0)
614  {
615  Xyce::dout() << "T2 = " << T2 << endl;
616  Xyce::dout() << "charcross = " << charcross << endl;
617  Xyce::dout() << "s_ind_0 = " << s_ind_0 << endl;
618  Xyce::dout() << "Expecting to interpolate the following points:" << endl;
619  unsigned int numinterp = ti.size();
620  for (unsigned int i=0 ; i < numinterp ; ++i)
621  {
622  Xyce::dout() << ti[i] << endl;
623  }
624  Xyce::dout() << "Total of " << numinterp << " points" << endl;
625  }
626 #endif // Xyce_DEBUG_TIME
627  timept_ = start_time; // used later for interpolating stop_time
628  unsigned int tinum = ti.size();
629  int total_interp = 0;
630  std::vector<double> timepoint_vec(blockCount,stop_time);
631  int num_interp_this_cycle = 0;
632  int s_ind = s_ind_0;
633  for (unsigned int i=0; i < tinum ; ++i)
634  {
635  timepoint_vec[s_ind] = ti[i];
636  num_interp_this_cycle++;
637  s_ind++;
638  if (s_ind >= blockCount) { s_ind = 0; };
639  // If we're back to s_ind_0 or out of ti points, then interpolate:
640  if ((s_ind == s_ind_0) || (i == tinum-1))
641  {
642  interpolateMPDESolution(timepoint_vec, ds.tmpSolVectorPtr);
643  // Now we print these points out
644  int s = s_ind_0;
645  for (int j=0 ; j < num_interp_this_cycle ; ++j)
646  {
647  timept_ = timepoint_vec[s];
648  outputMgrAdapterRCPtr->tranOutput(
649  timept_, blockTmpSolVectorPtr->block(s),
650  *ds.tmpStaVectorPtr, *ds.tmpStoVectorPtr,
651  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
652  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_);
653  total_interp++;
654  s++;
655  if (s >= blockCount) { s = 0; }
656 #ifdef Xyce_DEBUG_TIME
657  Xyce::dout() << "Interpolated to t = " << timept_ << endl;
658 #endif // Xyce_DEBUG_TIME
659  }
660  num_interp_this_cycle = 0;
661  }
662  }
663 #ifdef Xyce_DEBUG_TIME
664  Xyce::dout() << "Total of " << total_interp << " points" << endl;
665 #endif // Xyce_DEBUG_TIME
666 
667  // Now we interpolate stop_time unless its too close to the last timept interpolated.
668  eps = fabs(stop_time)*1.0e-8;
669  // fudge factor for printing, this should come from elsewhere FIXME
670  if (fabs(timept_ - stop_time) >= eps)
671  {
672 #ifdef Xyce_DEBUG_TIME
673  if (tiaParams.debugLevel > 0)
674  {
675  Xyce::dout() << "Previous timept = " << timept_ << endl;
676  Xyce::dout() << "Expecting to interpolate the following point: " << stop_time << endl;
677  }
678 #endif // Xyce_DEBUG_TIME
679  N_LAS_Vector* tmpSolnVecPtr = solnVecPtr;
680  N_LAS_Vector* tmpVecPtr = ds.tmpXn0APtr;
681  if (stop_time < tn)
682  {
683  interpolateSolution(stop_time,ds.tmpXn0BPtr, ds.xHistory);
684  tmpSolnVecPtr = ds.tmpXn0BPtr;
685  }
686  N_LAS_BlockVector * blockTmpSolnVecPtr =
687  dynamic_cast<N_LAS_BlockVector*>(tmpSolnVecPtr);
688  N_LAS_BlockVector * blockTmpVecPtr =
689  dynamic_cast<N_LAS_BlockVector*>(tmpVecPtr);
690  if (blockTmpSolnVecPtr == NULL)
691  {
692  std::string msg = "N_TIA_BackwardDifferentiation15::printMPDEOutputSolution: ";
693  msg += "N_LAS_Vector tmpSolnVecPtr is not of type N_LAS_BlockVector";
694  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
695  return(false);
696  }
697  if (blockTmpVecPtr == NULL)
698  {
699  std::string msg = "N_TIA_BackwardDifferentiation15::printMPDEOutputSolution: ";
700  msg += "N_LAS_Vector tmpVecPtr is not of type N_LAS_BlockVector";
701  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
702  return(false);
703  }
704  // Interpolate where the caracteristic crosses stop_time (instead of start_time).
705  //charcross = stop_time - floor(stop_time/T2)*T2;
706  charcross = fmod(stop_time,T2);
707  int s_ind_1 = -1;
708  // Find index just before charcross:
709  if( charcross < fastTimes[0] )
710  {
711  // by periodicity, the one before in this case is the one at the end
712  s_ind_1 = blockCount-1;
713  }
714  else
715  {
716  for (int i=blockCount-1 ; i>=0 ; --i)
717  {
718  if (fastTimes[i] <= charcross)
719  {
720  s_ind_1 = i;
721  break;
722  }
723  }
724  }
725  if (s_ind_1 == -1)
726  {
727  std::string msg = "N_TIA_BackwardDifferentiation15::printMPDEOutputSolution: ";
728  msg += "Cannot find where characteristic curve crosses fast time slice at stop_time";
729  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
730  return(false);
731  }
732  int sm = s_ind_1;
733  int sp = s_ind_1+1;
734  double coeff_sm = fastTimes[sp]-charcross;
735  double coeff_sp = charcross-fastTimes[sm];
736  if (sp == blockCount) { sp = 0; }
737  double dt = h2[s_ind_1];
738  timept_ = stop_time;
739 #ifdef Xyce_DEBUG_TIME
740  Xyce::dout() << "charcross = " << charcross << endl;
741  Xyce::dout() << "s_ind_1 = " << s_ind_1 << endl;
742  Xyce::dout() << "sp = " << sp << endl;
743  Xyce::dout() << "sm = " << sm << endl;
744  Xyce::dout() << "dt = " << dt << endl;
745  Xyce::dout() << "timept = " << timept_ << endl;
746  Xyce::dout() << "coeff_sm = " << coeff_sm << endl;
747  Xyce::dout() << "coeff_sp = " << coeff_sp << endl;
748 #endif // Xyce_DEBUG_TIME
749  blockTmpVecPtr->block(0).linearCombo(
750  coeff_sm/dt, blockTmpSolnVecPtr->block(sm),
751  coeff_sp/dt, blockTmpSolnVecPtr->block(sp)
752  );
753  outputMgrAdapterRCPtr->tranOutput(
754  timept_, blockTmpVecPtr->block(0),
755  *ds.tmpStaVectorPtr, *ds.tmpStoVectorPtr,
756  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
757  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_);
758 
759 #ifdef Xyce_DEBUG_TIME
760  Xyce::dout() << "Interpolated to t = " << timept_ << endl;
761 #endif // Xyce_DEBUG_TIME
762  }
763 #ifdef Xyce_DEBUG_TIME
764  else // no extra interpolation
765  {
766  if (tiaParams.debugLevel > 0)
767  {
768  Xyce::dout() << "No further interpolation required." << endl;
769  }
770  }
771 #endif // Xyce_DEBUG_TIME
772 
773 #ifdef Xyce_DEBUG_TIME
774  Xyce::dout() << Xyce::section_divider << std::endl;
775 #endif // Xyce_DEBUG_TIME
776  return true;
777 }
778 
779 
780 //-----------------------------------------------------------------------------
781 // Function : N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution()
782 // Purpose : Print transient output from WaMPDE simulation
783 // Special Notes : This routine uses interpolateSolution.
784 // Scope : public
785 // Creator : Todd Coffey, SNL, 1414
786 // Creation Date : 12/15/06
787 //-----------------------------------------------------------------------------
789  RefCountPtr< N_ANP_OutputMgrAdapter > outputMgrAdapterRCPtr,
790  const double time,
791  N_LAS_Vector * solnVecPtr,
792  const std::vector<double> & fastTimes,
793  const int phiGID )
794 {
795 #ifdef Xyce_DEBUG_TIME
796  if (tiaParams.debugLevel > 0)
797  {
798  Xyce::dout() << std::endl;
799  Xyce::dout() << Xyce::section_divider << std::endl;
800  Xyce::dout() <<
801  " N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution" << std::endl;
802  }
803 #endif // Xyce_DEBUG_TIME
804  double timestep = sec.lastAttemptedTimeStep;
805  double lasttime = sec.currentTime - timestep;
806  double tn = sec.currentTime;
807  // Set these values up to read output time intervals. FIXME
808  double beg_of_output_time_interval = lasttime;
809  double end_of_output_time_interval = tn;
810  double start_time = max(lasttime,beg_of_output_time_interval);
811  double stop_time = min(tn,end_of_output_time_interval);
812 #ifdef Xyce_DEBUG_TIME
813  if (tiaParams.debugLevel > 0)
814  {
815  Xyce::dout() << "start_time = " << start_time << endl;
816  Xyce::dout() << "stop_time = " << stop_time << endl;
817  }
818 #endif // Xyce_DEBUG_TIME
819 
820  // 12/15/06 tscoffe:
821  // First break the interval up as printOutputSolution does:
822  // hh = timestep/(sec.usedOrder_) and interpolate in the intervals:
823  // [tn+(i-1)*hh,tn+i*hh], i=1..usedOrder
824  // Assume phi(t_1) is linear in these intervals and approximate with:
825  // phi(t) = (1/hh)*(phi(tn)(tn+hh-t)+phi(tn+hh)(t-tn))
826  // Then the t_1 values we want to interpolate are:
827  // n2 = number of fast time points.
828  // T2 = fast time period
829  // h2 = T2/n2 = average spacing on fast time scale
830  // t1_vals = [tn:h2:tn+hh]
831  // And the t_2 values we want to interpolate are:
832  // t2_vals = phi(t1_vals) mod T2
833  // Then take the N_LAS blocks and do 2D linear interpolation on the intervals:
834  // (t1,s1), (t1,s2), (t2,s1), (t2,s2)
835  // x(t) = x(t,s) approx =
836  // (1/(t2-t1))(1/(s2-s1))[ x(t1,s1)(t2-t)(s2-s)
837  // +x(t1,s2)(t2-t)(s-s1)
838  // +x(t2,s1)(t-t1)(s2-s)
839  // +x(t2,s2)(t-t1)(s-s1) ]
840  // where t = t1_vals and s = t2_vals
841 
842  N_LAS_BlockVector * blockTmpSolVectorPtr =
843  dynamic_cast<N_LAS_BlockVector*>(ds.tmpSolVectorPtr);
844  N_LAS_BlockVector * blockTmpXn0APtr =
845  dynamic_cast<N_LAS_BlockVector*>(ds.tmpXn0APtr);
846  N_LAS_BlockVector * blockTmpXn0BPtr =
847  dynamic_cast<N_LAS_BlockVector*>(ds.tmpXn0BPtr);
848  if (blockTmpSolVectorPtr == NULL)
849  {
850  std::string msg = "N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution: ";
851  msg += "N_LAS_Vector ds.tmpSolVectorPtr is not of type N_LAS_BlockVector";
852  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
853  return(false);
854  }
855  if (blockTmpXn0APtr == NULL)
856  {
857  std::string msg = "N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution: ";
858  msg += "N_LAS_Vector ds.tmpXn0APtr is not of type N_LAS_BlockVector";
859  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
860  return(false);
861  }
862  if (blockTmpXn0BPtr == NULL)
863  {
864  std::string msg = "N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution: ";
865  msg += "N_LAS_Vector ds.tmpXn0BPtr is not of type N_LAS_BlockVector";
866  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
867  return(false);
868  }
869  int phiLID = blockTmpSolVectorPtr->pmap()->globalToLocalIndex(phiGID);
870  double hh = timestep/(sec.usedOrder_);
871  double timeA = -1.0;
872  double timeB = -1.0;
873 #ifdef Xyce_DEBUG_TIME
874  if (tiaParams.debugLevel > 0)
875  {
876  Xyce::dout() << " sec.usedOrder_ = " << sec.usedOrder_ << endl;
877  Xyce::dout() << " sec.currentTime_ = " << sec.currentTime << endl;
878  Xyce::dout() << " lasttime = " << lasttime << endl;
879  }
880 #endif // Xyce_DEBUG_TIME
881 
882  for (int i=0 ; i < sec.usedOrder_ ; ++i)
883  {
884  if (i == 0)
885  {
886  bool junk;
887  timeA = lasttime + hh*i;
888  junk = interpolateSolution(timeA,ds.tmpXn0APtr, ds.xHistory);
889  if (!junk)
890  {
891  std::string msg = "interpolateSolution returned false!";
892  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0,msg);
893  }
894  }
895  else
896  {
897  // We don't need to interpolate this again.
898  *ds.tmpXn0APtr = *ds.tmpXn0BPtr;
899  timeA = timeB;
900  }
901  timeB = lasttime + hh*(i+1);
902  interpolateSolution(timeB,ds.tmpXn0BPtr, ds.xHistory);
903 #ifdef Xyce_DEBUG_TIME
904  if (tiaParams.debugLevel > 0)
905  {
906  Xyce::dout() << "Interpolating in [ " << timeA << ", " << timeB << " ]" << endl;
907  Xyce::dout() << "timeA = " << timeA << endl;
908  Xyce::dout() << "timeB = " << timeB << endl;
909  }
910 #endif // Xyce_DEBUG_TIME
911 
912  // Now we can interpolate [tmpXn0APtr,tmpXn0BPtr] in [timeA,timeB].
913  std::vector<double> t1vals;
914  double T2 = fastTimes.back();
915  int blockCount = blockTmpSolVectorPtr->blockCount();
916  double h2 = T2/blockCount; // Average mesh width in fast time-scale
917  double tval = timeA+h2;
918  while (tval <= timeB)
919  {
920  t1vals.push_back(tval);
921  tval += h2;
922  }
923  // fudge factor for printing, this should come from elsewhere FIXME
924  double eps = fabs(timeB)*1.0e-8;
925  if ( (t1vals.size() == 0) || (fabs(t1vals.back() - timeB) >= eps) )
926  {
927  t1vals.push_back(timeB);
928  }
929  std::vector<double> t2vals, phiAB(2);
930  std::vector<double> tmpPhiAB(2, 0.0);
931  if (phiLID >= 0)
932  {
933  tmpPhiAB[0] = (*ds.tmpXn0APtr)[phiLID]; // Get from MPDE Manager
934  tmpPhiAB[1] = (*ds.tmpXn0BPtr)[phiLID]; // Get from MPDE Manager
935  }
936  blockTmpSolVectorPtr->pmap()->pdsComm()->sumAll( &tmpPhiAB[0], &phiAB[0], 2 );
937 
938  double phiA = phiAB[0], phiB = phiAB[1];
939  for (unsigned int j=0 ; j<t1vals.size() ; ++j)
940  {
941  double phi = (1/(timeB-timeA))*(phiA*(timeB-t1vals[j])+phiB*(t1vals[j]-timeA));
942  t2vals.push_back(fmod(phi,T2)); // phi(t1vals[j]) mod T2
943  }
944 #ifdef Xyce_DEBUG_TIME
945  if (tiaParams.debugLevel > 0)
946  {
947  Xyce::dout() << "t1vals = " << endl;
948  for (unsigned int j=0 ; j < t1vals.size() ; ++j)
949  {
950  Xyce::dout() << t1vals[j] << endl;
951  }
952  Xyce::dout() << "phi(" << timeA << ") = " << phiA << endl;
953  Xyce::dout() << "phi(" << timeB << ") = " << phiB << endl;
954  Xyce::dout() << "t2vals = " << endl;
955  for (unsigned int j=0 ; j< t2vals.size() ; ++j)
956  {
957  Xyce::dout() << t2vals[j] << endl;
958  }
959  }
960 #endif // Xyce_DEBUG_TIME
961  // Now we can do our block 2D interpolations
962  // loop through t1vals and move the fast time blocks as we go
963  double t1 = timeA; // slow time indices
964  double t2 = timeB;
965  double t = t1vals[0]; // current time indices
966  double s = t2vals[0];
967  int b1,b2; // fast time block indices corresponding to s1,s2
968  // Find the block surrounding s:
969  b1 = -2;
970  for (int j=0 ; j < blockCount ; ++j)
971  {
972  if ((fastTimes[j] <= s) && (s < fastTimes[j+1]))
973  {
974  b1 = j;
975  }
976  }
977  b2 = b1+1;
978  if (b2 == blockCount)
979  {
980  b2 = 0;
981  }
982  double s1 = fastTimes[b1];
983  double s2 = fastTimes[b1+1]; // Note: fastTimes[blockCount] = T2
984  if ((s < s1) || (s > s2))
985  {
986  std::string msg = "N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution: ";
987  msg += " Interpolator cannot find a fast time block containing the first point ";
988  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
989  }
990 #ifdef Xyce_DEBUG_TIME
991  Xyce::dout() << "Found s = " << s << " in block " << b1;
992  Xyce::dout() << " with boundary = [" << s1 << "," << s2 << "]" << endl;
993 #endif // Xyce_DEBUG_TIME
994  for (unsigned int j=0 ; j < t1vals.size() ; ++j)
995  {
996  t = t1vals[j];
997  s = t2vals[j];
998  if (t > t2) break; // This should never occur
999  // If s has moved outside our block, then increment block.
1000  if ( (s < s1) || (s > s2) )
1001  {
1002 #ifdef Xyce_DEBUG_TIME
1003  Xyce::dout() << "Incrementing fast time block for next interpolation." << endl;
1004 #endif // Xyce_DEBUG_TIME
1005  b1++;
1006  if (b1 == blockCount)
1007  {
1008  b1 = 0;
1009  }
1010  b2 = b1+1;
1011  if (b2 == blockCount)
1012  {
1013  b2 = 0;
1014  }
1015  s1 = fastTimes[b1];
1016  s2 = fastTimes[b1+1];
1017  }
1018  // If s isn't in the next block, then search for it.
1019  if ((s < s1) || (s > s2))
1020  {
1021 #ifdef Xyce_DEBUG_TIME
1022  Xyce::dout() << "Searching for fast time block for next interpolation." << endl;
1023 #endif // Xyce_DEBUG_TIME
1024  b1 = -2;
1025  for (int j2=0 ; j2 < blockCount ; ++j2)
1026  {
1027  if ((fastTimes[j2] <= s) && (s < fastTimes[j2+1]))
1028  {
1029  b1 = j2;
1030  }
1031  }
1032  b2 = b1+1;
1033  if (b2 == blockCount)
1034  {
1035  b2 = 0;
1036  }
1037  s1 = fastTimes[b1];
1038  s2 = fastTimes[b1+1];
1039  }
1040  // If a block surrounding s can't be found, then quit.
1041  if ((s < s1) || (s > s2))
1042  {
1043  std::string msg = "N_TIA_BackwardDifferentiation15::printWaMPDEOutputSolution: ";
1044  msg += " Interpolator moved fast time block but new point is not in this block ";
1045  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
1046  }
1047  if (s > T2) break; // Just double checking...
1048  //blockTmpXn0APtr->block(b1) // x(t1,s1)
1049  //blockTmpXn0APtr->block(b2) // x(t1,s2)
1050  //blockTmpXn0BPtr->block(b1) // x(t2,s1)
1051  //blockTmpXn0BPtr->block(b2) // x(t2,s2)
1052  // (1/(t2-t1))(1/(s2-s1))[ x(t1,s1)(t2-t)(s2-s)
1053  // +x(t1,s2)(t2-t)(s-s1)
1054  // +x(t2,s1)(t-t1)(s2-s)
1055  // +x(t2,s2)(t-t1)(s-s1) ]
1056 #ifdef Xyce_DEBUG_TIME
1057  if (tiaParams.debugLevel > 0)
1058  {
1059  Xyce::dout() << "Interpolating in the block:" << endl;
1060  Xyce::dout() << "(t1,t2) = (" << t1 << "," << t2 << ")" << endl;
1061  Xyce::dout() << "(s1,s2) = (" << s1 << "," << s2 << ")" << endl;
1062  }
1063 #endif // Xyce_DEBUG_TIME
1064  double denom = (t2-t1)*(s2-s1);
1065  double coeff0 = (t2-t)*(s2-s)/denom;
1066  double coeff1 = (t2-t)*(s-s1)/denom;
1067  double coeff2 = (t-t1)*(s2-s)/denom;
1068  double coeff3 = (t-t1)*(s-s1)/denom;
1069  (blockTmpSolVectorPtr->block(b1)).linearCombo(
1070  coeff0, blockTmpXn0APtr->block(b1),
1071  coeff1, blockTmpXn0APtr->block(b2),
1072  coeff2, blockTmpXn0BPtr->block(b1) );
1073  (blockTmpSolVectorPtr->block(b1)).update(
1074  coeff3, blockTmpXn0BPtr->block(b2), 1.0 );
1075 
1076  // erkeite 2/24/07. This is needed because currently the interpolation goes back to t=-1.0.
1077  if (t >= 0.0)
1078  {
1079  outputMgrAdapterRCPtr->tranOutput(
1080  t, blockTmpSolVectorPtr->block(b1),
1081  *ds.tmpStaVectorPtr, *ds.tmpStoVectorPtr,
1082  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
1083  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_);
1084 
1085 #ifdef Xyce_DEBUG_TIME
1086  Xyce::dout() << "Interpolated to (t,phi(t)) = (" << t << "," << s << ")" << endl;
1087 #endif // Xyce_DEBUG_TIME
1088  }
1089  }
1090  }
1091 
1092 #ifdef Xyce_DEBUG_TIME
1093  Xyce::dout() << Xyce::section_divider << std::endl;
1094 #endif // Xyce_DEBUG_TIME
1095  return true;
1096 }
1097 
1098 //-----------------------------------------------------------------------------
1099 // Function : N_TIA_BackwardDifferentiation15::printOutputSolution()
1100 // Purpose : Print output that is dumbed down in order.
1101 // Special Notes : This routine picks smaller time steps to approximate first
1102 // : order integration from the perspective of the output.
1103 // Scope : public
1104 // Creator : Todd Coffey, SNL, 1414
1105 // Creation Date : 11/21/05
1106 //-----------------------------------------------------------------------------
1108  RefCountPtr< N_ANP_OutputMgrAdapter > outputMgrAdapterRCPtr,
1109  const double time,
1110  N_LAS_Vector * solnVecPtr,
1111  const bool doNotInterpolate,
1112  const std::vector<double> &outputInterpolationTimes,
1113  bool skipPrintLineOutput)
1114 {
1115 #ifdef Xyce_DEBUG_TIME
1116  if (tiaParams.debugLevel > 0)
1117  {
1118  Xyce::dout() << std::endl;
1119  Xyce::dout() << Xyce::section_divider << std::endl;
1120  Xyce::dout() <<
1121  " N_TIA_BackwardDifferentiation15::printOutputSolution" << std::endl;
1122  Xyce::dout() << "usedOrder_ = " << sec.usedOrder_ << endl;
1123  }
1124 #endif // Xyce_DEBUG_TIME
1125  double timestep = sec.lastAttemptedTimeStep;
1126  double lasttime = sec.currentTime - timestep;
1127  bool dointerp = true;
1128  double hh = timestep/(sec.usedOrder_);
1129  if (hh <= 10*sec.minTimeStep)
1130  {
1131  dointerp = false;
1132  }
1133 
1134  if (!(tiaParams.interpOutputFlag))
1135  {
1136  dointerp = false;
1137  }
1138 
1139  if (doNotInterpolate)
1140  {
1141  dointerp = false;
1142  }
1143 
1144  if (dointerp && !outputInterpolationTimes.empty())
1145  {
1146  for (unsigned int i=0;i<outputInterpolationTimes.size();++i)
1147  {
1148  interpolateSolution(outputInterpolationTimes[i], ds.tmpSolVectorPtr, ds.xHistory); // interpolate solution vector
1149  interpolateSolution(outputInterpolationTimes[i], ds.tmpStaVectorPtr, ds.sHistory); // interpolate state vector
1150  interpolateSolution(outputInterpolationTimes[i], ds.tmpStoVectorPtr, ds.stoHistory); // interpolate store vector
1151  outputMgrAdapterRCPtr->tranOutput(outputInterpolationTimes[i], *ds.tmpSolVectorPtr,
1152  *ds.tmpStaVectorPtr, *ds.tmpStoVectorPtr,
1153  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
1154  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_,
1155  skipPrintLineOutput);
1156  }
1157  }
1158  else if ( (sec.usedOrder_ > 2) && dointerp )
1159  {
1160  for (int i=1 ; i<sec.usedOrder_; ++i)
1161  {
1162  double timept = lasttime + hh*i;
1163  interpolateSolution(timept,ds.tmpSolVectorPtr, ds.xHistory); // interpolate solution vector
1164  interpolateSolution(timept,ds.tmpStaVectorPtr, ds.sHistory); // interpolate state vector
1165  interpolateSolution(timept,ds.tmpStoVectorPtr, ds.stoHistory); // interpolate store vector
1166  outputMgrAdapterRCPtr->tranOutput(timept, *ds.tmpSolVectorPtr,
1167  *ds.tmpStaVectorPtr, *ds.tmpStoVectorPtr,
1168  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
1169  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_,
1170  skipPrintLineOutput);
1171 
1172 #ifdef Xyce_DEBUG_TIME
1173  Xyce::dout() << "Interpolated to t = " << timept << endl;
1174 #endif // Xyce_DEBUG_TIME
1175  }
1176  }
1177 
1178  // Either way, do an output on the actual computed time step, but only
1179  // if we weren't given a list of specific times *or* we were told not to
1180  // interpoloate.
1181  if (outputInterpolationTimes.empty() || doNotInterpolate)
1182  outputMgrAdapterRCPtr->tranOutput(time, *ds.currSolutionPtr,
1183  *ds.currStatePtr, *ds.currStorePtr,
1184  ds.objectiveVec_, ds.dOdpVec_, ds.dOdpAdjVec_,
1185  ds.scaled_dOdpVec_, ds.scaled_dOdpAdjVec_,
1186  skipPrintLineOutput);
1187 
1188 #ifdef Xyce_DEBUG_TIME
1189  Xyce::dout() << Xyce::section_divider << std::endl;
1190 #endif // Xyce_DEBUG_TIME
1191  return true;
1192 }
1193 
1194 //-----------------------------------------------------------------------------
1195 // Function : N_TIA_BackwardDifferentiation15::saveOutputSolution
1196 // Purpose : This is similar to printOutputSolution, but is in support of
1197 // the .SAVE capability, rather than .PRINT.
1198 // Special Notes :
1199 // Scope : public
1200 // Creator : Eric Keiter, SNL
1201 // Creation Date : 10/21/07
1202 //-----------------------------------------------------------------------------
1204  RefCountPtr< N_ANP_OutputMgrAdapter > outputMgrAdapterRCPtr,
1205  N_LAS_Vector * solnVecPtr,
1206  const double saveTime,
1207  const bool doNotInterpolate)
1208 {
1209 #ifdef Xyce_DEBUG_TIME
1210  if (tiaParams.debugLevel > 0)
1211  {
1212  Xyce::dout() << std::endl;
1213  Xyce::dout() << Xyce::section_divider << std::endl;
1214  Xyce::dout() <<
1215  " N_TIA_BackwardDifferentiation15::saveOutputSolution" << std::endl;
1216  }
1217 #endif // Xyce_DEBUG_TIME
1218 
1219  double timestep = sec.lastAttemptedTimeStep;
1220  double lasttime = sec.currentTime - timestep;
1221  bool dointerp = true;
1222  double hh = timestep/(sec.usedOrder_);
1223  if (hh <= 10*sec.minTimeStep)
1224  {
1225  dointerp = false;
1226  }
1227 
1228  if (!(tiaParams.interpOutputFlag))
1229  {
1230  dointerp = false;
1231  }
1232 
1233  if (doNotInterpolate)
1234  {
1235  dointerp = false;
1236  }
1237 
1238  if (dointerp)
1239  {
1240  interpolateSolution(saveTime,ds.tmpSolVectorPtr, ds.xHistory);
1241  outputMgrAdapterRCPtr->outputDCOP( *(ds.tmpSolVectorPtr) );
1242  }
1243  else
1244  {
1245  outputMgrAdapterRCPtr->outputDCOP( *(solnVecPtr) );
1246  }
1247 
1248 #ifdef Xyce_DEBUG_TIME
1249  Xyce::dout() << Xyce::section_divider << std::endl;
1250 #endif // Xyce_DEBUG_TIME
1251  return true;
1252 }
1253 
1254 //-----------------------------------------------------------------------------
1255 // IDA source license:
1256 //-----------------------------------------------------------------------------
1257 // Copyright (c) 2002, The Regents of the University of California.
1258 // Produced at the Lawrence Livermore National Laboratory.
1259 // Written by Alan Hindmarsh, Allan Taylor, Radu Serban.
1260 // UCRL-CODE-2002-59
1261 // All rights reserved.
1262 //
1263 // This file is part of IDA.
1264 //
1265 // Redistribution and use in source and binary forms, with or without
1266 // modification, are permitted provided that the following conditions
1267 // are met:
1268 //
1269 // 1. Redistributions of source code must retain the above copyright
1270 // notice, this list of conditions and the disclaimer below.
1271 //
1272 // 2. Redistributions in binary form must reproduce the above copyright
1273 // notice, this list of conditions and the disclaimer (as noted below)
1274 // in the documentation and/or other materials provided with the
1275 // distribution.
1276 //
1277 // 3. Neither the name of the UC/LLNL nor the names of its contributors
1278 // may be used to endorse or promote products derived from this software
1279 // without specific prior written permission.
1280 //
1281 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1282 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1283 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1284 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1285 // REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY
1286 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1287 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1288 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1289 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1290 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1291 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1292 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1293 //
1294 // Additional BSD Notice
1295 // ---------------------
1296 // 1. This notice is required to be provided under our contract with
1297 // the U.S. Department of Energy (DOE). This work was produced at the
1298 // University of California, Lawrence Livermore National Laboratory
1299 // under Contract No. W-7405-ENG-48 with the DOE.
1300 //
1301 // 2. Neither the United States Government nor the University of
1302 // California nor any of their employees, makes any warranty, express
1303 // or implied, or assumes any liability or responsibility for the
1304 // accuracy, completeness, or usefulness of any information, apparatus,
1305 // product, or process disclosed, or represents that its use would not
1306 // infringe privately-owned rights.
1307 //
1308 // 3. Also, reference herein to any specific commercial products,
1309 // process, or services by trade name, trademark, manufacturer or
1310 // otherwise does not necessarily constitute or imply its endorsement,
1311 // recommendation, or favoring by the United States Government or the
1312 // University of California. The views and opinions of authors expressed
1313 // herein do not necessarily state or reflect those of the United States
1314 // Government or the University of California, and shall not be used for
1315 // advertising or product endorsement purposes.
1316 //-----------------------------------------------------------------------------
1317 
1318 
1319 //-----------------------------------------------------------------------------
1320 // Function : N_TIA_BackwardDifferentiation15::updateHistory
1321 // Purpose : Update history array after a successful step
1322 // Special Notes :
1323 // Scope : public
1324 // Creator : Todd Coffey, SNL
1325 // Creation Date : 03/08/04
1326 //-----------------------------------------------------------------------------
1328 {
1329 
1330 #ifdef Xyce_DEBUG_TIME
1331  if (tiaParams.debugLevel > 1)
1332  {
1333  Xyce::dout() << std::endl;
1334  Xyce::dout() << Xyce::section_divider << std::endl;
1335  Xyce::dout() <<
1336  " N_TIA_BackwardDifferentiation15::updateHistory" << std::endl;
1337  Xyce::dout() << "\n Before updates \n" << endl;
1338  for (int i=0; i<=sec.maxOrder_ ; ++i)
1339  {
1340  Xyce::dout() << "\n xHistory["<< i << "]: \n" << endl;
1341  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1342  Xyce::dout() << endl;
1343  }
1344  for (int i=0; i<=sec.maxOrder_ ; ++i)
1345  {
1346  Xyce::dout() << "\n qHistory["<< i << "]: \n" << endl;
1347  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1348  Xyce::dout() << endl;
1349  }
1350  for (int i=0; i<=sec.maxOrder_ ; ++i)
1351  {
1352  Xyce::dout() << "\n sHistory["<< i << "]: \n" << endl;
1353  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1354  Xyce::dout() << endl;
1355  }
1356  Xyce::dout() << Xyce::section_divider << std::endl;
1357  }
1358 #endif // Xyce_DEBUG_TIME
1359 
1360  // Save Newton correction for potential order increase on next step.
1361  if (sec.usedOrder_ < sec.maxOrder_)
1362  {
1363  *(ds.xHistory[sec.usedOrder_+1]) = *ds.newtonCorrectionPtr;
1364  *(ds.qHistory[sec.usedOrder_+1]) = *ds.qNewtonCorrectionPtr;
1365  }
1366  // Update history arrays
1367  (ds.xHistory[sec.usedOrder_])->linearCombo(1.0,*(ds.xHistory[sec.usedOrder_]),1.0,*ds.newtonCorrectionPtr);
1368  (ds.qHistory[sec.usedOrder_])->linearCombo(1.0,*(ds.qHistory[sec.usedOrder_]),1.0,*ds.qNewtonCorrectionPtr);
1369  for (int j=sec.usedOrder_-1;j>=0;j--)
1370  {
1371  (ds.xHistory[j])->linearCombo(1.0,*(ds.xHistory[j]),1.0,*(ds.xHistory[j+1]));
1372  (ds.qHistory[j])->linearCombo(1.0,*(ds.qHistory[j]),1.0,*(ds.qHistory[j+1]));
1373  }
1374 
1375  // Update State History
1376  if (sec.usedOrder_ < sec.maxOrder_)
1377  {
1378  *(ds.sHistory[sec.usedOrder_+1]) = *ds.sNewtonCorrectionPtr;
1379  }
1380  // Update history arrays
1381  (ds.sHistory[sec.usedOrder_])->linearCombo(1.0,*(ds.sHistory[sec.usedOrder_]),1.0,*ds.sNewtonCorrectionPtr);
1382  for (int j=sec.usedOrder_-1;j>=0;j--)
1383  {
1384  (ds.sHistory[j])->linearCombo(1.0,*(ds.sHistory[j]),1.0,*(ds.sHistory[j+1]));
1385  }
1386 
1387  // Update Store History
1388  if (sec.usedOrder_ < sec.maxOrder_)
1389  {
1390  *(ds.stoHistory[sec.usedOrder_+1]) = *ds.stoNewtonCorrectionPtr;
1391  *(ds.stoLeadCurrQCompHistory[sec.usedOrder_+1]) = *ds.stoLeadCurrQCompNewtonCorrectionPtr;
1392  }
1393  // Update history arrays
1394  (ds.stoHistory[sec.usedOrder_])->linearCombo(1.0,*(ds.stoHistory[sec.usedOrder_]),1.0,*ds.stoNewtonCorrectionPtr);
1395  (ds.stoLeadCurrQCompHistory[sec.usedOrder_])->
1396  linearCombo(1.0,*(ds.stoLeadCurrQCompHistory[sec.usedOrder_]),1.0,*ds.stoLeadCurrQCompNewtonCorrectionPtr);
1397  for (int j=sec.usedOrder_-1;j>=0;j--)
1398  {
1399  (ds.stoHistory[j])->linearCombo(1.0,*(ds.stoHistory[j]),1.0,*(ds.stoHistory[j+1]));
1400  (ds.stoLeadCurrQCompHistory[j])->
1401  linearCombo(1.0,*(ds.stoLeadCurrQCompHistory[j]),1.0,*(ds.stoLeadCurrQCompHistory[j+1]));
1402  }
1403 
1404 #ifdef Xyce_DEBUG_TIME
1405  if (tiaParams.debugLevel > 1)
1406  {
1407  Xyce::dout() << "\n After updates \n" << endl;
1408  Xyce::dout() << "\n newtonCorrectionPtr: " << endl;
1409  ds.newtonCorrectionPtr->printPetraObject(Xyce::dout());
1410  Xyce::dout() << "\n qnewtonCorrectionPtr: " << endl;
1411  ds.qNewtonCorrectionPtr->printPetraObject(Xyce::dout());
1412  for (int i=0; i<=sec.maxOrder_ ; ++i)
1413  {
1414  Xyce::dout() << "\n xHistory["<< i << "]: \n" << endl;
1415  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1416  Xyce::dout() << endl;
1417  }
1418  for (int i=0; i<=sec.maxOrder_ ; ++i)
1419  {
1420  Xyce::dout() << "\n qHistory["<< i << "]: \n" << endl;
1421  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1422  Xyce::dout() << endl;
1423  }
1424  Xyce::dout() << "\n sNewtonCorrectionPtr: " << endl;
1425  ds.sNewtonCorrectionPtr->printPetraObject(Xyce::dout());
1426  Xyce::dout() << endl;
1427  Xyce::dout() << "\n nextStatePtr: " << endl;
1428  ds.nextStatePtr->printPetraObject(Xyce::dout());
1429  Xyce::dout() << endl;
1430  for (int i=0; i<=sec.maxOrder_ ; ++i)
1431  {
1432  Xyce::dout() << "\n sHistory["<< i << "]: \n" << endl;
1433  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1434  Xyce::dout() << endl;
1435  }
1436  Xyce::dout() << Xyce::section_divider << std::endl;
1437  }
1438 #endif // Xyce_DEBUG_TIME
1439 }
1440 
1441 //-----------------------------------------------------------------------------
1442 // Function : N_TIA_BackwardDifferentiation15::restoreHistory
1443 // Purpose : Restore history array after a failed step
1444 // Special Notes :
1445 // Scope : public
1446 // Creator : Todd Coffey, SNL
1447 // Creation Date : 03/08/04
1448 //-----------------------------------------------------------------------------
1450 {
1451 
1452  // undo preparation of history array for prediction
1453  for (int i=sec.nscsco_;i<=sec.currentOrder_;++i)
1454  {
1455  (ds.xHistory[i])->scale(1/sec.beta_[i]);
1456  (ds.qHistory[i])->scale(1/sec.beta_[i]);
1457  (ds.sHistory[i])->scale(1/sec.beta_[i]);
1458  (ds.stoHistory[i])->scale(1/sec.beta_[i]);
1459  }
1460  for (int i=1;i<=sec.currentOrder_;++i)
1461  {
1462  sec.psi_[i-1] = sec.psi_[i] - (sec.currentTimeStep);
1463  }
1464 #ifdef Xyce_DEBUG_TIME
1465  if (tiaParams.debugLevel > 1)
1466  {
1467  Xyce::dout() << std::endl;
1468  Xyce::dout() << Xyce::section_divider << std::endl;
1469  Xyce::dout() <<
1470  " N_TIA_BackwardDifferentiation15::restoreHistory" << std::endl;
1471  for (int i=1;i<=sec.currentOrder_;++i)
1472  Xyce::dout() << "\n sec.psi_[i] = " << sec.psi_[i] << endl;
1473  for (int i=0; i<=sec.maxOrder_ ; ++i)
1474  {
1475  Xyce::dout() << "\n xHistory["<< i << "]: \n" << endl;
1476  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1477  Xyce::dout() << endl;
1478  }
1479  for (int i=0; i<=sec.maxOrder_ ; ++i)
1480  {
1481  Xyce::dout() << "\n qHistory["<< i << "]: \n" << endl;
1482  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1483  Xyce::dout() << endl;
1484  }
1485  for (int i=0; i<=sec.maxOrder_ ; ++i)
1486  {
1487  Xyce::dout() << "\n sHistory["<< i << "]: \n" << endl;
1488  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1489  Xyce::dout() << endl;
1490  }
1491  Xyce::dout() << Xyce::section_divider << std::endl;
1492  }
1493 #endif // Xyce_DEBUG_TIME
1494 }
1495 
1496 //-----------------------------------------------------------------------------
1497 // Function : N_TIA_BackwardDifferentiation15::updateCoeffs
1498 // Purpose : Update method coefficients
1499 // Special Notes :
1500 // Scope : public
1501 // Creator : Todd Coffey, SNL
1502 // Creation Date : 03/08/04
1503 //-----------------------------------------------------------------------------
1505 {
1506  // synchronize with Step Error Control
1507 // sec.psi_[0] = sec.currentTimeStep;
1508 #ifdef Xyce_DEBUG_TIME
1509  if (tiaParams.debugLevel > 0)
1510  {
1511  Xyce::dout() << std::endl;
1512  Xyce::dout() << Xyce::section_divider << std::endl;
1513 
1514  Xyce::dout() <<
1515  " N_TIA_BackwardDifferentiation15::updateCoeffs" << std::endl;
1516  Xyce::dout() <<
1517  " currentTimeStep = " << sec.currentTimeStep << std::endl;
1518  Xyce::dout() <<
1519  " numberOfSteps_ = " << sec.numberOfSteps_ << std::endl;
1520  Xyce::dout() <<
1521  " currentOrder_ = " << sec.currentOrder_ << std::endl;
1522  Xyce::dout() <<
1523  " nscsco_ = " << sec.nscsco_ << std::endl;
1524  Xyce::dout() <<
1525  " psi_[0] = " << sec.psi_[0] << std::endl;
1526  }
1527 #endif
1528  // If the number of steps taken with constant order and constant stepsize is
1529  // more than the current order + 1 then we don't bother to update the
1530  // coefficients because we've reached a constant step-size formula. When
1531  // this is is not true, then we update the coefficients for the variable
1532  // step-sizes.
1533  if ((sec.currentTimeStep != sec.usedStep_) || (sec.currentOrder_ != sec.usedOrder_))
1534  sec.nscsco_ = 0;
1535  sec.nscsco_ = min(sec.nscsco_+1,sec.usedOrder_+2);
1536  if (sec.currentOrder_+1 >= sec.nscsco_)
1537  {
1538  sec.beta_[0] = 1.0;
1539  sec.alpha_[0] = 1.0;
1540  double temp1 = sec.currentTimeStep;
1541  sec.sigma_[0] = 1.0;
1542  sec.gamma_[0] = 0.0;
1543  for (int i=1;i<=sec.currentOrder_;++i)
1544  {
1545  double temp2 = sec.psi_[i-1];
1546  sec.psi_[i-1] = temp1;
1547  sec.beta_[i] = sec.beta_[i-1]*sec.psi_[i-1]/temp2;
1548  temp1 = temp2 + sec.currentTimeStep;
1549  sec.alpha_[i] = (sec.currentTimeStep)/temp1;
1550  sec.sigma_[i] = (i+1)*sec.sigma_[i-1]*sec.alpha_[i];
1551  sec.gamma_[i] = sec.gamma_[i-1]+sec.alpha_[i-1]/(sec.currentTimeStep);
1552  }
1553  sec.psi_[sec.currentOrder_] = temp1;
1554  sec.alphas_ = 0.0;
1555  sec.alpha0_ = 0.0;
1556  for (int i=0;i<sec.currentOrder_;++i)
1557  {
1558  sec.alphas_ = sec.alphas_ - 1.0/(i+1.0);
1559  sec.alpha0_ = sec.alpha0_ - sec.alpha_[i];
1560  }
1561  sec.cj_ = -sec.alphas_/(sec.currentTimeStep);
1562  sec.ck_ = abs(sec.alpha_[sec.currentOrder_]+sec.alphas_-sec.alpha0_);
1563  sec.ck_ = max(sec.ck_,sec.alpha_[sec.currentOrder_]);
1564  }
1565 #ifdef Xyce_DEBUG_TIME
1566  if (tiaParams.debugLevel > 0)
1567  {
1568  Xyce::dout() <<
1569  " nscsco_ = " << sec.nscsco_ << std::endl;
1570  Xyce::dout() <<
1571  " beta_[0] = " << sec.beta_[0] << std::endl;
1572  Xyce::dout() <<
1573  " beta_[1] = " << sec.beta_[1] << std::endl;
1574  Xyce::dout() <<
1575  " beta_[2] = " << sec.beta_[2] << std::endl;
1576  Xyce::dout() <<
1577  " beta_[3] = " << sec.beta_[3] << std::endl;
1578  Xyce::dout() <<
1579  " beta_[4] = " << sec.beta_[4] << std::endl;
1580  Xyce::dout() <<
1581  " alpha_[0] = " << sec.alpha_[0] << std::endl;
1582  Xyce::dout() <<
1583  " alpha_[1] = " << sec.alpha_[1] << std::endl;
1584  Xyce::dout() <<
1585  " alpha_[2] = " << sec.alpha_[2] << std::endl;
1586  Xyce::dout() <<
1587  " alpha_[3] = " << sec.alpha_[3] << std::endl;
1588  Xyce::dout() <<
1589  " alpha_[4] = " << sec.alpha_[4] << std::endl;
1590  Xyce::dout() <<
1591  " alphas_ = " << sec.alphas_ << std::endl;
1592  Xyce::dout() <<
1593  " alpha0_ = " << sec.alpha0_ << std::endl;
1594  Xyce::dout() <<
1595  " gamma_[0] = " << sec.gamma_[0] << std::endl;
1596  Xyce::dout() <<
1597  " gamma_[1] = " << sec.gamma_[1] << std::endl;
1598  Xyce::dout() <<
1599  " gamma_[2] = " << sec.gamma_[2] << std::endl;
1600  Xyce::dout() <<
1601  " gamma_[3] = " << sec.gamma_[3] << std::endl;
1602  Xyce::dout() <<
1603  " gamma_[4] = " << sec.gamma_[4] << std::endl;
1604  Xyce::dout() <<
1605  " psi_[0] = " << sec.psi_[0] << std::endl;
1606  Xyce::dout() <<
1607  " psi_[1] = " << sec.psi_[1] << std::endl;
1608  Xyce::dout() <<
1609  " psi_[2] = " << sec.psi_[2] << std::endl;
1610  Xyce::dout() <<
1611  " psi_[3] = " << sec.psi_[3] << std::endl;
1612  Xyce::dout() <<
1613  " psi_[4] = " << sec.psi_[4] << std::endl;
1614  Xyce::dout() <<
1615  " sigma_[0] = " << sec.sigma_[0] << std::endl;
1616  Xyce::dout() <<
1617  " sigma_[1] = " << sec.sigma_[1] << std::endl;
1618  Xyce::dout() <<
1619  " sigma_[2] = " << sec.sigma_[2] << std::endl;
1620  Xyce::dout() <<
1621  " sigma_[3] = " << sec.sigma_[3] << std::endl;
1622  Xyce::dout() <<
1623  " sigma_[4] = " << sec.sigma_[4] << std::endl;
1624  Xyce::dout() <<
1625  " ck_ = " << sec.ck_ << std::endl;
1626  Xyce::dout() << Xyce::section_divider << std::endl;
1627  }
1628 #endif // Xyce_DEBUG_TIME
1629 }
1630 
1631 //-----------------------------------------------------------------------------
1632 // Function : N_TIA_BackwardDifferentiation15::initialize
1633 // Purpose : Initialize method with initial solution & step-size
1634 // Special Notes :
1635 // Scope : public
1636 // Creator : Todd Coffey, SNL
1637 // Creation Date : 3/09/04
1638 //-----------------------------------------------------------------------------
1640 {
1641 
1642  // we assume the solution vector is available here
1643  // Note that I'm using currSolutionPtr instead of
1644  // nextSolutionPtr because this is the first step.
1645 
1646  // Update next stop time from StepErrorControl:
1647  // ERK. Commenting this out, as it is already called from N_ANP_AnalysisManager,
1648  // right before this initialize call. It should not be called 2x, as
1649  // it is history dependent (unfortunately), so calling it 2x in a row changes
1650  // the stop time to a different number.
1651  // sec.updateStopTime();
1652 
1653  // Choose initial step-size
1654  double time_to_stop = sec.stopTime - sec.currentTime;
1655  double currentTimeStep;
1656  if (tiaParams.constantStepSize)
1657  {
1658  currentTimeStep = 0.1 * time_to_stop;
1659  currentTimeStep = Xycemin(sec.startingTimeStep, currentTimeStep);
1660  sec.currentTimeStep = currentTimeStep;
1661  }
1662  else
1663  {
1664  // compute an initial step-size based on rate of change in the
1665  // solution initially
1666 #ifdef Xyce_INCOMPLETE_2LEVEL_NORMS
1667  double dnorm_q = 0.0;
1668  (ds.qHistory[1])->wRMSNorm(*ds.qErrWtVecPtr, &dnorm_q);
1669 #else
1670  double dnorm_q = ds.delta_x_errorNorm_q1();
1671 #endif
1672  if (dnorm_q > 0.0) // time-dependent DAE
1673  {
1674  currentTimeStep = Xycemin(sec.h0_max_factor_*abs(time_to_stop),sqrt(2.0)/(sec.h0_safety_*dnorm_q));
1675  }
1676  else // non-time-dependent DAE
1677  {
1678  currentTimeStep = sec.h0_max_factor_*abs(time_to_stop);
1679  }
1680  // choose min of user specified value and our value:
1681  if (sec.startingTimeStep > 0.0)
1682  currentTimeStep = Xycemin(sec.startingTimeStep, currentTimeStep);
1683  // check for maximum step-size:
1684  double rh = abs(currentTimeStep)*sec.h_max_inv_;
1685  if (rh>1.0) currentTimeStep = currentTimeStep/rh;
1686 
1687 
1688  // Apply this new stepsize only if it is smaller than the one preceding
1689  // the breakpoint, but only do this if this is a non-DCOP breakpoint.
1690  if (sec.currentTime != sec.initialTime) // if not DCOP:
1691  {
1692  sec.currentTimeStep = Xycemin(sec.lastTimeStep, currentTimeStep);
1693  }
1694  else // else if DCOP:
1695  {
1696  sec.currentTimeStep = currentTimeStep;
1697  }
1698  }
1699 
1700  sec.currentTimeStepRatio = 1.0;
1701  sec.currentTimeStepSum = 2.0*sec.currentTimeStep;
1702 
1703  sec.lastTimeStep = sec.currentTimeStep;
1704  sec.lastTimeStepRatio = sec.currentTimeStepRatio;
1705  sec.lastTimeStepSum = sec.currentTimeStepSum;
1706 
1707  sec.numberSuccessiveFailures = 0;
1708  sec.stepAttemptStatus = true;
1709 
1710 // sec.tolAimFac_ = 0.5;
1711 
1712  sec.nextTime = sec.currentTime + sec.currentTimeStep;
1713 
1714  // x history
1715  *(ds.xHistory[0]) = *(ds.currSolutionPtr);
1716  (ds.xHistory[1])->putScalar(0.0); // no need to multiply by dt here
1717 
1718  // q history
1719  *(ds.qHistory[0]) = *(ds.daeQVectorPtr);
1720  *(ds.qHistory[1]) = *(ds.daeFVectorPtr);
1721  (ds.qHistory[1])->scale(-sec.currentTimeStep);
1722 
1723  // state history
1724  *(ds.sHistory[0]) = *(ds.currStatePtr);
1725  (ds.sHistory[1])->putScalar(0.0);
1726 
1727  // store history
1728  *(ds.stoHistory[0]) = *(ds.currStorePtr);
1729  (ds.stoHistory[1])->putScalar(0.0);
1730 
1731  // lead current Q compontent history
1732  *(ds.stoLeadCurrQCompHistory[0]) = *(ds.currStoreLeadCurrQCompPtr);
1733  (ds.stoLeadCurrQCompHistory[1])->putScalar(0.0);
1734 
1735  // Coefficient initialization
1736  sec.numberOfSteps_ = 0; // number of total time integration steps taken
1737  sec.currentOrder_ = 1;
1738  sec.usedOrder_ = 1;
1739  sec.psi_[0] = sec.currentTimeStep;
1740  sec.cj_ = 1/sec.psi_[0];
1741  sec.nscsco_ = 0;
1742 #ifdef Xyce_DEBUG_TIME
1743  Xyce::dout() << std::endl;
1744  Xyce::dout() << Xyce::section_divider << std::endl;
1745  Xyce::dout() <<
1746  " N_TIA_BackwardDifferentiation15::initialize" << std::endl;
1747  if (tiaParams.debugLevel > 1)
1748  {
1749  Xyce::dout() << "\n xHistory: \n" << endl;
1750  (ds.xHistory[0])->printPetraObject(Xyce::dout());
1751  Xyce::dout() << endl;
1752  (ds.xHistory[1])->printPetraObject(Xyce::dout());
1753  Xyce::dout() << endl;
1754  Xyce::dout() << "\n qHistory: \n" << endl;
1755  (ds.qHistory[0])->printPetraObject(Xyce::dout());
1756  Xyce::dout() << endl;
1757  (ds.qHistory[1])->printPetraObject(Xyce::dout());
1758  Xyce::dout() << endl;
1759  Xyce::dout() << "\n sHistory: \n" << endl;
1760  (ds.sHistory[0])->printPetraObject(Xyce::dout());
1761  Xyce::dout() << endl;
1762  (ds.sHistory[1])->printPetraObject(Xyce::dout());
1763  Xyce::dout() << endl;
1764  Xyce::dout() << "\n" << "currentTimeStep = " << currentTimeStep << "\n" << endl;
1765  Xyce::dout() << "\n" << "time_to_stop = " << time_to_stop << "\n" << endl;
1766  }
1767  Xyce::dout() << Xyce::section_divider << std::endl;
1768 #endif // Xyce_DEBUG_TIME
1769 }
1770 
1771 //-----------------------------------------------------------------------------
1772 // Function : N_TIA_BackwardDifferentiation15::setTwoLevelTimeInfo
1773 // Purpose :
1774 // Special Notes :
1775 // Scope : public
1776 // Creator : Eric Keiter, SNL
1777 // Creation Date : 03/01/07
1778 //-----------------------------------------------------------------------------
1780  (const N_TIA_TimeIntInfo & tiInfo)
1781 {
1782  // set initial step-size
1783  double time_to_stop = sec.stopTime - sec.currentTime;
1784 
1785 
1786  // x history
1787  *(ds.xHistory[0]) = *(ds.currSolutionPtr);
1788  (ds.xHistory[1])->putScalar(0.0); // no need to multiply by dt here
1789 
1790  // q history
1791  *(ds.qHistory[0]) = *(ds.daeQVectorPtr);
1792  *(ds.qHistory[1]) = *(ds.daeFVectorPtr);
1793  (ds.qHistory[1])->scale(-sec.currentTimeStep);
1794 
1795  // state history
1796  *(ds.sHistory[0]) = *(ds.nextStatePtr);
1797  (ds.sHistory[1])->putScalar(0.0);
1798 
1799  // store history
1800  *(ds.stoHistory[0]) = *(ds.nextStatePtr);
1801  (ds.stoHistory[1])->putScalar(0.0);
1802 
1803  // lead current Q compontent history
1804  *(ds.stoLeadCurrQCompHistory[0]) = *(ds.nextStoreLeadCurrQCompPtr);
1805  (ds.stoLeadCurrQCompHistory[1])->putScalar(0.0);
1806 
1807  // Coefficient initialization
1808  sec.numberOfSteps_ = 0; // number of total time integration steps taken
1809  sec.usedOrder_ = 1;
1810  sec.psi_[0] = sec.currentTimeStep;
1811  sec.cj_ = 1/sec.psi_[0];
1812  sec.nscsco_ = 0;
1813 
1814 }
1815 
1816 
1817 //-----------------------------------------------------------------------------
1818 // Function : N_TIA_BackwardDifferentiation15::checkReduceOrder()
1819 // Purpose : check whether to reduce order independent of local error test
1820 // Special Notes :
1821 // Scope : public
1822 // Creator : Todd Coffey, SNL
1823 // Creation Date : 06/08/04
1824 //-----------------------------------------------------------------------------
1826 {
1827 
1828 // This routine puts its output in sec.newOrder_
1829 
1830 // This routine changes the following variables:
1831 // sec.Ek_, sec.Tk_, sec.Est_, sec.newOrder_, ds.delta_x, ds.delta_q,
1832 // sec.Ekm1_, sec.Tkm1_, sec.Ekm2_, sec.Tkm2_
1833 
1834 // This routine reads but does not change the following variables:
1835 // sec.currentOrder_, sec.sigma_, ds.newtonCorrectionPtr, ds.qNewtonCorrectionPtr,
1836 // ds.errWtVecPtr, ds.qErrWtVecPtr, ds.xHistory, ds.qHistory
1837 
1838 #ifdef Xyce_DEBUG_TIME
1839  if (tiaParams.debugLevel > 0)
1840  {
1841  Xyce::dout() << std::endl;
1842  Xyce::dout() << Xyce::section_divider << std::endl;
1843  Xyce::dout() <<
1844  " N_TIA_BackwardDifferentiation15::checkReduceOrder" << std::endl;
1845  }
1846 #endif // Xyce_DEBUG_TIME
1847 
1848  // 03/11/04 tscoffe: I only want to run this block after a step has been
1849  // attempted, but I want to do this regardless of the status from the local
1850  // error test.
1851  // 03/10/04 tscoffe: Decide whether to reduce the order before considering
1852  // the local error test result.
1853 #ifndef Xyce_USE_Q_NORM
1854  //double dnorm_x = 0.0;
1855  //ds.newtonCorrectionPtr->wRMSNorm(&dnorm_x); // delta = newtonCorrection
1856  //double dnorm_x *= sec.ck_;
1857  //double dnorm = dnorm_x;
1858  double dnorm_x = sec.estOverTol_;
1859  double dnorm = dnorm_x;
1860 #else
1861  double dnorm_x = 0.0, dnorm_q = 0.0;
1862  ds.newtonCorrectionPtr->wRMSNorm(*ds.errWtVecPtr, &dnorm_x); // delta = newtonCorrection
1863  ds.qNewtonCorrectionPtr->wRMSNorm(*ds.qErrWtVecPtr, &dnorm_q); // dnorm = norm of delta
1864  double dnorm = sqrt(0.5*dnorm_x*dnorm_x+0.5*dnorm_q*dnorm_q);
1865 #endif
1866 
1867  sec.Ek_ = sec.sigma_[sec.currentOrder_]*dnorm;
1868  sec.Tk_ = (sec.currentOrder_+1)*sec.Ek_;
1869  sec.Est_ = sec.Ek_;
1870  sec.newOrder_ = sec.currentOrder_;
1871 #ifdef Xyce_DEBUG_TIME
1872  if (tiaParams.debugLevel > 0)
1873  {
1874  Xyce::dout() <<
1875  " Est_= " << sec.Est_ << std::endl;
1876  Xyce::dout() <<
1877  " Ek_= " << sec.Ek_ << std::endl;
1878  Xyce::dout() <<
1879  " dnorm = " << dnorm << std::endl;
1880  Xyce::dout() <<
1881  " sigma[order] = " << sec.sigma_[sec.currentOrder_] << std::endl;
1882  Xyce::dout() <<
1883  " Tk_= " << sec.Tk_ << std::endl;
1884  }
1885 #endif // Xyce_DEBUG_TIME
1886 
1887 
1888  if (sec.currentOrder_>1)
1889  {
1890 
1891 #ifndef Xyce_USE_Q_NORM
1892  ds.delta_x->linearCombo(1.0,*(ds.xHistory[sec.currentOrder_]),1.0,*ds.newtonCorrectionPtr);
1893 #ifdef Xyce_INCOMPLETE_2LEVEL_NORMS
1894  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
1895  dnorm_x *= sec.ck_;
1896 #else
1897  dnorm_x = sec.ck_ * ds.delta_x_errorNorm_m1();
1898 #endif
1899  dnorm = dnorm_x;
1900 #else
1901  ds.delta_x->linearCombo(1.0,*(ds.xHistory[sec.currentOrder_]),1.0,*ds.newtonCorrectionPtr);
1902  ds.delta_q->linearCombo(1.0,*(ds.qHistory[sec.currentOrder_]),1.0,*ds.qNewtonCorrectionPtr);
1903  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
1904  ds.delta_q->wRMSNorm(*ds.qErrWtVecPtr, &dnorm_q);
1905  dnorm = sqrt(0.5*dnorm_x*dnorm_x+0.5*dnorm_q*dnorm_q);
1906 #endif
1907 
1908  sec.Ekm1_ = sec.sigma_[sec.currentOrder_-1]*dnorm;
1909  sec.Tkm1_ = sec.currentOrder_*sec.Ekm1_;
1910 #ifdef Xyce_DEBUG_TIME
1911  if (tiaParams.debugLevel > 0)
1912  {
1913  Xyce::dout() <<
1914  " Ekm1_= " << sec.Ekm1_ << std::endl;
1915  Xyce::dout() <<
1916  " Tkm1_= " << sec.Tkm1_ << std::endl;
1917  }
1918 #endif // Xyce_DEBUG_TIME
1919 
1920  if (sec.currentOrder_>2)
1921  {
1922 #ifndef Xyce_USE_Q_NORM
1923  ds.delta_x->linearCombo(1.0,*(ds.xHistory[sec.currentOrder_-1]),1.0,*ds.delta_x);
1924 #ifdef Xyce_INCOMPLETE_2LEVEL_NORMS
1925  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
1926  dnorm_x *= sec.ck_;
1927 #else
1928  dnorm_x = sec.ck_ * ds.delta_x_errorNorm_m2();
1929 #endif
1930  dnorm = dnorm_x;
1931 #else
1932  ds.delta_x->linearCombo(1.0,*(ds.xHistory[sec.currentOrder_-1]),1.0,*ds.delta_x);
1933  ds.delta_q->linearCombo(1.0,*(ds.qHistory[sec.currentOrder_-1]),1.0,*ds.delta_q);
1934  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
1935  ds.delta_q->wRMSNorm(*ds.qErrWtVecPtr, &dnorm_q);
1936  dnorm = sqrt(0.5*dnorm_x*dnorm_x+0.5*dnorm_q*dnorm_q);
1937 #endif
1938 
1939  sec.Ekm2_ = sec.sigma_[sec.currentOrder_-2]*dnorm;
1940  sec.Tkm2_ = (sec.currentOrder_-1)*sec.Ekm2_;
1941  if (Xycemax(sec.Tkm1_,sec.Tkm2_)<=sec.Tk_)
1942  {
1943  sec.newOrder_--;
1944  sec.Est_ = sec.Ekm1_;
1945  }
1946  }
1947  else if (sec.Tkm1_ <= sec.Tkm1_Tk_safety_ * sec.Tk_)
1948  {
1949 #ifdef Xyce_DEBUG_TIME
1950  if (tiaParams.debugLevel > 0)
1951  {
1952  Xyce::dout() <<
1953  " Tkm1_Tk_safety= " << sec.Tkm1_Tk_safety_ << std::endl;
1954  Xyce::dout() <<
1955  " Tkm1_= " << sec.Tkm1_ << std::endl;
1956  Xyce::dout() <<
1957  " Tk_= " << sec.Tk_ << std::endl;
1958  Xyce::dout() <<
1959  " Tk_*safety= " << sec.Tk_*sec.Tkm1_Tk_safety_ << std::endl;
1960  }
1961 #endif // Xyce_DEBUG_TIME
1962 
1963  sec.newOrder_--;
1964  sec.Est_ = sec.Ekm1_;
1965  }
1966  }
1967 #ifdef Xyce_DEBUG_TIME
1968  if (tiaParams.debugLevel > 0)
1969  {
1970  Xyce::dout() <<
1971  " newOrder = " << sec.newOrder_ << std::endl;
1972  Xyce::dout() << Xyce::section_divider << std::endl;
1973  }
1974 #endif
1975 }
1976 
1977 //-----------------------------------------------------------------------------
1978 // Function : N_TIA_BackwardDifferentiation15::rejectStep()
1979 // Purpose : code to restore history, choose new order/step-size
1980 // Special Notes :
1981 // Scope : public
1982 // Creator : Todd Coffey, SNL
1983 // Creation Date : 06/07/04
1984 //-----------------------------------------------------------------------------
1986 {
1987 
1988 // This routine puts its output in newTimeStep_ and sec.newOrder_
1989 
1990 // This routine changes the following variables:
1991 // lastAttemptedTimeStep, sec.initialPhase_, sec.nef_, sec.psi_, newTimeStep_,
1992 // sec.newOrder_, sec.currentOrder_, currentTimeStep_, ds.xHistory,
1993 // ds.qHistory, nextTimePt, nextTime, currentTimeStepRatio,
1994 // currentTimeStepSum, nextTimePt
1995 
1996 // This routine reades but does not change the following variables:
1997 // stepAttemptStatus, sec.r_factor_, sec.r_safety_, sec.Est_, sec.r_fudge_, sec.r_min_, sec.r_max_,
1998 // minTimeStep, maxTimeStep, currentTime, stopTime, lastTimeStep
1999 
2000 
2001  // First we decide if we'll reduce the order independent of the local error test:
2002  checkReduceOrder();
2003 
2004 #ifdef Xyce_DEBUG_TIME
2005 
2006  if (tiaParams.debugLevel > 0)
2007  {
2008  Xyce::dout() << std::endl;
2009  Xyce::dout() << Xyce::section_divider << std::endl;
2010 
2011  Xyce::dout() <<
2012  " N_TIA_BackwardDifferentiation15::rejectStep" << std::endl;
2013  }
2014 #endif
2015 
2016  // Only update the time step if we are NOT running constant stepsize.
2017  bool adjustStep = (!(tiaParams.constantStepSize) );
2018 
2019  sec.lastAttemptedTimeStep = sec.currentTimeStep;
2020 
2021 
2022  double newTimeStep_ = sec.currentTimeStep;
2023  double rr = 1.0; // step size ratio = new step / old step
2024  if ((sec.stepAttemptStatus == false) && (adjustStep))
2025  {
2026  sec.initialPhase_ = false;
2027  sec.nef_++;
2028  restoreHistory();
2029  // restore sec.psi_
2030 // for (int i=1;i<=sec.currentOrder_;++i)
2031 // sec.psi_[i-1] = sec.psi_[i] - sec.currentTimeStep;
2032 
2033 
2034 
2035  // erkeite: 11/13/2007. Commenting this max failure error out. The
2036  // Code already checks against a minimum time step, based on machine-precision.
2037  // The machine-precision limit is a better test.
2038 #if 0
2039  if (sec.nef_ >= sec.max_LET_fail_)
2040  {
2041  std::string msg = "N_TIA_BackwardDifferentiation15::rejectStep: ";
2042  msg += " Maximum number of local error test failures. ";
2043  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
2044  }
2045 #endif
2046 
2047  if ((sec.newtonConvergenceStatus <= 0))
2048  {
2049  /// 11/11/05 erkeite: If the Newton solver fails, don't
2050  // rely on the error estimate - it may be full of Nan's.
2051  rr = sec.r_min_;
2052  newTimeStep_ = rr * sec.currentTimeStep;
2053 
2054  if (sec.nef_ > 2) sec.newOrder_ = 1;//consistent with block below.
2055 #ifdef Xyce_DEBUG_TIME
2056  Xyce::dout() << "rejectStep 1" << std::endl;
2057 #endif
2058  }
2059  else
2060  {
2061  // 03/11/04 tscoffe: Here is the block for choosing order &
2062  // step-size when the local error test FAILS (but Newton
2063  // succeeded).
2064  if (sec.nef_ == 1) // first local error test failure
2065  {
2066 #ifndef Xyce_USE_Q_NORM
2067  rr = sec.r_factor_*pow(sec.r_safety_*(sec.Est_+sec.r_fudge_),-1.0/(sec.newOrder_+1.0));
2068  rr = Xycemax(sec.r_min_,Xycemin(sec.r_max_,rr));
2069 #else
2070  rr = sec.r_factor_*pow(sec.r_safety_*sec.Est_+sec.r_fudge_,-1.0/(sec.newOrder_+1.0));
2071  rr = Xycemax(sec.r_min_,Xycemin(sec.r_max_,rr));
2072 #endif
2073  newTimeStep_ = rr * sec.currentTimeStep;
2074 #ifdef Xyce_DEBUG_TIME
2075  Xyce::dout() << "rejectStep 2" << std::endl;
2076 #endif
2077  }
2078  else if (sec.nef_ == 2) // second Dae failure
2079  {
2080  rr = sec.r_min_;
2081  newTimeStep_ = rr * sec.currentTimeStep;
2082 #ifdef Xyce_DEBUG_TIME
2083  Xyce::dout() << "rejectStep 3" << std::endl;
2084 #endif
2085  }
2086  else if (sec.nef_ > 2) // third and later failures
2087  {
2088  sec.newOrder_ = 1;
2089  rr = sec.r_min_;
2090  newTimeStep_ = rr * sec.currentTimeStep;
2091 #ifdef Xyce_DEBUG_TIME
2092  Xyce::dout() << "rejectStep 4" << std::endl;
2093 #endif
2094  }
2095  }
2096  if (sec.newOrder_ >= sec.minOrder_)
2097  {
2098  sec.currentOrder_ = sec.newOrder_;
2099 #ifdef Xyce_DEBUG_TIME
2100  Xyce::dout() << "rejectStep 5" << std::endl;
2101 #endif
2102  }
2103  if (sec.numberOfSteps_ == 0) // still first step
2104  {
2105  sec.psi_[0] = newTimeStep_;
2106  (ds.xHistory[1])->scale(rr);
2107  (ds.qHistory[1])->scale(rr);
2108 #ifdef Xyce_DEBUG_TIME
2109  Xyce::dout() << "rejectStep 6" << std::endl;
2110 #endif
2111  }
2112 #ifdef Xyce_DEBUG_TIME
2113  if (tiaParams.debugLevel > 0)
2114  {
2115  Xyce::dout() <<
2116  " currentTimeStep = " << sec.currentTimeStep << std::endl;
2117  Xyce::dout() <<
2118  " numberOfSteps_ = " << sec.numberOfSteps_ << std::endl;
2119  Xyce::dout() <<
2120  " currentOrder_ = " << sec.currentOrder_ << std::endl;
2121  Xyce::dout() <<
2122  " nscsco_ = " << sec.nscsco_ << std::endl;
2123  Xyce::dout() <<
2124  " alpha_[0] = " << sec.alpha_[0] << std::endl;
2125  Xyce::dout() <<
2126  " alpha_[1] = " << sec.alpha_[1] << std::endl;
2127  Xyce::dout() <<
2128  " alpha_[2] = " << sec.alpha_[2] << std::endl;
2129  Xyce::dout() <<
2130  " alpha_[3] = " << sec.alpha_[3] << std::endl;
2131  Xyce::dout() <<
2132  " alpha_[4] = " << sec.alpha_[4] << std::endl;
2133  Xyce::dout() <<
2134  " psi_[0] = " << sec.psi_[0] << std::endl;
2135  Xyce::dout() <<
2136  " psi_[1] = " << sec.psi_[1] << std::endl;
2137  Xyce::dout() <<
2138  " psi_[2] = " << sec.psi_[2] << std::endl;
2139  Xyce::dout() <<
2140  " psi_[3] = " << sec.psi_[3] << std::endl;
2141  Xyce::dout() <<
2142  " psi_[4] = " << sec.psi_[4] << std::endl;
2143  Xyce::dout() <<
2144  " sigma_[0] = " << sec.sigma_[0] << std::endl;
2145  Xyce::dout() <<
2146  " sigma_[1] = " << sec.sigma_[1] << std::endl;
2147  Xyce::dout() <<
2148  " sigma_[2] = " << sec.sigma_[2] << std::endl;
2149  Xyce::dout() <<
2150  " sigma_[3] = " << sec.sigma_[3] << std::endl;
2151  Xyce::dout() <<
2152  " sigma_[4] = " << sec.sigma_[4] << std::endl;
2153  Xyce::dout() <<
2154  " rr = " << rr << std::endl;
2155  Xyce::dout() <<
2156  " r_factor_ = " << sec.r_factor_ << std::endl;
2157  Xyce::dout() <<
2158  " r_safety_ = " << sec.r_safety_ << std::endl;
2159  Xyce::dout() <<
2160  " Est_ = " << sec.Est_ << std::endl;
2161  Xyce::dout() <<
2162  " r_fudge_ = " << sec.r_fudge_ << std::endl;
2163  Xyce::dout() <<
2164  " newOrder_ = " << sec.newOrder_ << std::endl;
2165 
2166  Xyce::dout() <<
2167  " currentTimeStep = " << sec.currentTimeStep << std::endl;
2168  Xyce::dout() <<
2169  " newTimeStep_ = " << newTimeStep_ << std::endl;
2170  }
2171 #endif // Xyce_DEBUG_TIME
2172  }
2173  else if ((sec.stepAttemptStatus == false) & (!adjustStep))
2174  {
2175  std::string tmp = " BackwardDifferentiation15:rejectStep: Warning: Local error test failed with constant step-size.\n";
2176  Xyce::dout() << tmp << std::endl;
2177  }
2178 
2179  // If the step needs to be adjusted:
2180  if (adjustStep)
2181  {
2182  newTimeStep_ = Xycemax(newTimeStep_, sec.minTimeStep);
2183  newTimeStep_ = Xycemin(newTimeStep_, sec.maxTimeStep);
2184 
2185  double nextTimePt = sec.currentTime + newTimeStep_;
2186 
2187  if (nextTimePt > sec.stopTime)
2188  {
2189  nextTimePt = sec.stopTime;
2190  newTimeStep_ = sec.stopTime - sec.currentTime;
2191  }
2192 
2193  sec.nextTime = nextTimePt;
2194 
2195  sec.currentTimeStepRatio = newTimeStep_/sec.lastTimeStep;
2196  sec.currentTimeStepSum = newTimeStep_ + sec.lastTimeStep;
2197 
2198 #ifdef Xyce_DEBUG_TIME
2199  if (tiaParams.debugLevel >0)
2200  {
2201  Xyce::dout() <<
2202  " newTimeStep_ = " << newTimeStep_ << std::endl;
2203  Xyce::dout() <<
2204  " nextTime = " << sec.nextTime << std::endl;
2205  }
2206 #endif // Xyce_DEBUG_TIME
2207 
2208  sec.currentTimeStep = newTimeStep_;
2209  }
2210  else // if time step is constant for this step:
2211  {
2212  double nextTimePt = sec.currentTime + sec.currentTimeStep;
2213 
2214  if (nextTimePt > sec.stopTime)
2215  {
2216  nextTimePt = sec.stopTime;
2217  sec.currentTimeStep = sec.stopTime - sec.currentTime;
2218  }
2219 
2220  sec.currentTimeStepRatio = sec.currentTimeStep / sec.lastTimeStep;
2221  sec.currentTimeStepSum = sec.currentTimeStep + sec.lastTimeStep;
2222 
2223  sec.nextTime = nextTimePt;
2224  }
2225 #ifdef Xyce_DEBUG_TIME
2226  if (tiaParams.debugLevel >0)
2227  {
2228  Xyce::dout() << Xyce::section_divider << std::endl;
2229  }
2230 #endif // Xyce_DEBUG_TIME
2231 }
2232 
2233 //-----------------------------------------------------------------------------
2234 // Function : N_TIA_BackwardDifferentiation15::rejectStepForHabanero
2235 // Purpose : step rejection, but from an outside program (Habanero API)
2236 // Special Notes :
2237 // Scope : public
2238 // Creator : Eric Keiter, SNL
2239 // Creation Date : 08/11/09
2240 //-----------------------------------------------------------------------------
2242 {
2243  restoreHistory();
2244  sec.setTimeStep(sec.currentTimeStep);
2245 }
2246 
2247 //-----------------------------------------------------------------------------
2248 // Function : N_TIA_BackwardDifferentiation15::completeStep()
2249 // Purpose : code to update history, choose new order/step-size
2250 // Special Notes :
2251 // Scope : public
2252 // Creator : Todd Coffey, SNL
2253 // Creation Date : 06/07/04
2254 //-----------------------------------------------------------------------------
2256 {
2257 
2258  sec.numberOfSteps_ ++;
2259  sec.nef_ = 0;
2260  sec.lastTime = sec.currentTime;
2261  sec.currentTime = sec.nextTime;
2262  // First we decide if we'll reduce the order independent of the local error test:
2263  checkReduceOrder();
2264 
2265 
2266 #ifdef Xyce_DEBUG_TIME
2267 
2268  if (tiaParams.debugLevel > 0)
2269  {
2270  Xyce::dout() << std::endl;
2271  Xyce::dout() << Xyce::section_divider << std::endl;
2272 
2273  Xyce::dout() <<
2274  " N_TIA_BackwardDifferentiation15::completeStep" << std::endl;
2275  }
2276 #endif
2277 
2278  // Only update the time step if we are NOT running constant stepsize.
2279  bool adjustStep = (!(tiaParams.constantStepSize) );
2280 
2281  sec.lastAttemptedTimeStep = sec.currentTimeStep;
2282 
2283  double newTimeStep_ = sec.currentTimeStep;
2284  double rr = 1.0; // step size ratio = new step / old step
2285  // 03/11/04 tscoffe: Here is the block for choosing order & step-size when
2286  // the local error test PASSES (and Newton succeeded).
2287  sec.lastTimeStep = sec.currentTimeStep;
2288  sec.lastTimeStepRatio = sec.currentTimeStepRatio; // copied from calcTStep1
2289  sec.lastTimeStepSum = sec.currentTimeStepSum; // copied from calcTStep1
2290  int orderDiff = sec.currentOrder_ - sec.usedOrder_;
2291  sec.usedOrder_ = sec.currentOrder_;
2292  sec.usedStep_ = sec.currentTimeStep;
2293  if ((sec.newOrder_ == sec.currentOrder_-1) || (sec.currentOrder_ == sec.maxOrder_))
2294  {
2295  // If we reduced our order or reached max order then move to the next phase
2296  // of integration where we don't automatically double the step-size and
2297  // increase the order.
2298  sec.initialPhase_ = false;
2299  }
2300  if (sec.initialPhase_)
2301  {
2302  sec.currentOrder_++;
2303  newTimeStep_ = sec.h_phase0_incr_ * sec.currentTimeStep;
2304  }
2305  else // not in the initial phase of integration
2306  {
2307  int action = TIAAction_UNSET;
2308  if (sec.newOrder_ == sec.currentOrder_-1)
2309  action = TIAAction_LOWER;
2310  else if (sec.newOrder_ == sec.maxOrder_)
2311  action = TIAAction_MAINTAIN;
2312  else if ((sec.currentOrder_+1>=sec.nscsco_) || (orderDiff == 1))
2313  {
2314  // If we just raised the order last time then we won't raise it again
2315  // until we've taken sec.currentOrder_+1 steps at order sec.currentOrder_.
2316  action = TIAAction_MAINTAIN;
2317  }
2318  else // consider changing the order
2319  {
2320 
2321 #ifndef Xyce_USE_Q_NORM
2322  ds.delta_x->linearCombo(1.0,*ds.newtonCorrectionPtr,-1.0,*(ds.xHistory[sec.currentOrder_+1]));
2323 #ifdef Xyce_INCOMPLETE_2LEVEL_NORMS
2324  double dnorm_x = 0.0;
2325  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
2326  dnorm_x *= sec.ck_;
2327 #else
2328  double dnorm_x = sec.ck_ * ds.delta_x_errorNorm_p1();
2329 #endif
2330  double dnorm = dnorm_x;
2331 #else
2332  ds.delta_x->linearCombo(1.0,*ds.newtonCorrectionPtr,-1.0,*(ds.xHistory[sec.currentOrder_+1]));
2333  ds.delta_q->linearCombo(1.0,*ds.qNewtonCorrectionPtr,-1.0,*(ds.qHistory[sec.currentOrder_+1]));
2334  double dnorm_x = 0.0, dnorm_q = 0.0;
2335  ds.delta_x->wRMSNorm(*ds.errWtVecPtr, &dnorm_x);
2336  ds.delta_q->wRMSNorm(*ds.qErrWtVecPtr, &dnorm_q);
2337  double dnorm = sqrt(0.5*dnorm_x*dnorm_x+0.5*dnorm_q*dnorm_q);
2338 #endif
2339 
2340  sec.Tkp1_ = dnorm;
2341  sec.Ekp1_ = sec.Tkp1_/(sec.currentOrder_+2);
2342  if (sec.currentOrder_ == 1)
2343  {
2344  if (sec.Tkp1_ >= sec.Tkp1_Tk_safety_ * sec.Tk_)
2345  action = TIAAction_MAINTAIN;
2346  else
2347  action = TIAAction_RAISE;
2348  }
2349  else
2350  {
2351  if (sec.Tkm1_ <= Xycemin(sec.Tk_,sec.Tkp1_))
2352  action = TIAAction_LOWER;
2353  else if (sec.Tkp1_ >= sec.Tk_)
2354  action = TIAAction_MAINTAIN;
2355  else
2356  action = TIAAction_RAISE;
2357  }
2358  }
2359  if (sec.currentOrder_ < sec.minOrder_)
2360  {
2361  action = TIAAction_RAISE;
2362  }
2363  else if ((sec.currentOrder_ == sec.minOrder_) && (action == TIAAction_LOWER))
2364  {
2365  action = TIAAction_MAINTAIN;
2366  }
2367  if (action == TIAAction_RAISE)
2368  {
2369  sec.currentOrder_++;
2370  sec.Est_ = sec.Ekp1_;
2371  }
2372  else if (action == TIAAction_LOWER)
2373  {
2374  sec.currentOrder_--;
2375  sec.Est_ = sec.Ekm1_;
2376  }
2377  newTimeStep_ = sec.currentTimeStep;
2378 
2379  // ERK: if errorAnalysisOption==1, that means that we're not using LTE to determine the
2380  // new step size. We're only considering whether or not the Newton solve succeeded.
2381  // If we are in this function, then it succeeded, as otherwise we'd be in the "rejectStep"
2382  // function.
2383  if (tiaParams.errorAnalysisOption == 1)
2384  {
2385  rr = 0.4/(sec.r_min_);
2386  newTimeStep_ = rr*sec.currentTimeStep;
2387  }
2388  else
2389  {
2390 #ifndef Xyce_USE_Q_NORM
2391  rr = pow(sec.r_safety_*(sec.Est_+sec.r_fudge_),-1.0/(sec.currentOrder_+1.0));
2392 #else
2393  rr = pow(sec.r_safety_*sec.Est_+sec.r_fudge_,-1.0/(sec.currentOrder_+1.0));
2394 #endif
2395 
2396 #ifdef Xyce_DEBUG_TIME
2397  if (tiaParams.debugLevel > 0)
2398  {
2399  Xyce::dout() <<
2400  " currentOrder_ = " << sec.currentOrder_ << std::endl;
2401  Xyce::dout() <<
2402  " r_safety = " << sec.r_safety_ << std::endl;
2403  Xyce::dout() <<
2404  " r_fudge_ = " << sec.r_fudge_ << std::endl;
2405  Xyce::dout() <<
2406  " r_hincr_ = " << sec.r_hincr_ << std::endl;
2407  Xyce::dout() <<
2408  " r_hincr_test_ = " << sec.r_hincr_test_ << std::endl;
2409  Xyce::dout() <<
2410  " Est = " << sec.Est_ << std::endl;
2411  Xyce::dout() <<
2412  " Ekp1_ = " << sec.Ekp1_ << std::endl;
2413  Xyce::dout() <<
2414  " Ekm1_ = " << sec.Ekm1_ << std::endl;
2415  Xyce::dout() <<
2416  " Tkp1_ = " << sec.Tkp1_ << std::endl;
2417  Xyce::dout() <<
2418  " raw rr = " << rr << std::endl;
2419  }
2420 #endif
2421  if (rr >= sec.r_hincr_test_)
2422  {
2423  rr = sec.r_hincr_;
2424  newTimeStep_ = rr*sec.currentTimeStep;
2425  }
2426  else if (rr <= 1)
2427  {
2428  rr = Xycemax(sec.r_min_,Xycemin(sec.r_max_,rr));
2429  newTimeStep_ = rr*sec.currentTimeStep;
2430  }
2431  }
2432  }
2433 #ifdef Xyce_DEBUG_TIME
2434  if (tiaParams.debugLevel > 0)
2435  {
2436  Xyce::dout() <<
2437  " initialPhase_ = " << sec.initialPhase_ << std::endl;
2438  Xyce::dout() <<
2439  " rr = " << rr << std::endl;
2440  Xyce::dout() <<
2441  " currentTimeStep = " << sec.currentTimeStep << std::endl;
2442  Xyce::dout() <<
2443  " currentTime = " << sec.currentTime << std::endl;
2444  Xyce::dout() <<
2445  " nextTime = " << sec.nextTime << std::endl;
2446  Xyce::dout() <<
2447  " newTimeStep_ = " << newTimeStep_ << std::endl;
2448  Xyce::dout() <<
2449  " minTimeStep = " << sec.minTimeStep << std::endl;
2450  Xyce::dout() <<
2451  " maxTimeStep = " << sec.maxTimeStep << std::endl;
2452  }
2453 #endif
2454  // 03/22/04 tscoffe: Note that updating the history has nothing to do with
2455  // the step-size and everything to do with the newton correction vectors.
2456  updateHistory();
2457 
2458 
2459  // 12/01/05 tscoffe: This is necessary to avoid currentTimeStep == 0 right
2460  // before a breakpoint. So I'm checking to see if currentTime is identically
2461  // equal to stopTime, in which case we are right before a breakpoint and we
2462  // should not adjust currentStepSize because that would result in
2463  // currentStepSize == 0.
2464  if (sec.currentTime < sec.stopTime)
2465  {
2466  // If the step needs to be adjusted:
2467  if (adjustStep)
2468  {
2469  newTimeStep_ = Xycemax(newTimeStep_, sec.minTimeStep);
2470  newTimeStep_ = Xycemin(newTimeStep_, sec.maxTimeStep);
2471 
2472  double nextTimePt = sec.currentTime + newTimeStep_;
2473 
2474  if (nextTimePt > sec.stopTime)
2475  {
2476  nextTimePt = sec.stopTime;
2477  newTimeStep_ = sec.stopTime - sec.currentTime;
2478  }
2479 
2480  sec.nextTime = nextTimePt;
2481 
2482  sec.currentTimeStepRatio = newTimeStep_/sec.lastTimeStep;
2483  sec.currentTimeStepSum = newTimeStep_ + sec.lastTimeStep;
2484 
2485 #ifdef Xyce_DEBUG_TIME
2486  if (tiaParams.debugLevel >0)
2487  {
2488  Xyce::dout() << " nextTime = " << sec.nextTime << std::endl;
2489  Xyce::dout() << " newTimeStep_ = " << newTimeStep_ << std::endl;
2490  }
2491 #endif
2492 
2493  sec.currentTimeStep = newTimeStep_;
2494  }
2495  else // if time step is constant for this step:
2496  {
2497  double nextTimePt = sec.currentTime + sec.currentTimeStep;
2498 
2499  if (nextTimePt > sec.stopTime)
2500  {
2501  nextTimePt = sec.stopTime;
2502  sec.currentTimeStep = sec.stopTime - sec.currentTime;
2503  }
2504 
2505  sec.currentTimeStepRatio = sec.currentTimeStep / sec.lastTimeStep;
2506  sec.currentTimeStepSum = sec.currentTimeStep + sec.lastTimeStep;
2507 
2508  sec.nextTime = nextTimePt;
2509  }
2510  }
2511 #ifdef Xyce_DEBUG_TIME
2512  if (tiaParams.debugLevel >0)
2513  {
2514  Xyce::dout() << Xyce::section_divider << std::endl;
2515  }
2516 #endif
2517 
2518 // 11/02/04 tscoffe: This should be done at the beginning of an integration
2519 // stop rather than at the end, so its been moved into
2520 // ControlAlgorithm::transientLoop_
2521  // Update next stop time in StepErrorControl:
2522  // sec.updateStopTime();
2523 }
2524 
2525 //-----------------------------------------------------------------------------
2526 // Function : N_TIA_BackwardDifferentiation15::updateStateDeriv
2527 // Purpose :
2528 // Special Notes :
2529 // Scope : public
2530 // Creator : Todd Coffey, SNL
2531 // Creation Date : 11/17/05
2532 //-----------------------------------------------------------------------------
2534 {
2535  // dS/dt = spn0 - (sec.alpha_/hn)(S(x)-sn0)
2536  ds.nextStateDerivPtr->linearCombo(1.0,*ds.nextStatePtr,-1.0,*ds.sn0Ptr);
2537  ds.nextStateDerivPtr->linearCombo(1.0,*ds.spn0Ptr,-sec.alphas_/sec.currentTimeStep,*ds.nextStateDerivPtr);
2538 }
2539 
2540 
2541 //-----------------------------------------------------------------------------
2542 // Function : N_TIA_BackwardDifferentiation15::updateLeadCurrent
2543 // Purpose : calculates lead currents in store vector with
2544 // the storeLeadCurrQCompVec.
2545 // Special Notes :
2546 // Scope : public
2547 // Creator : Richard Schiek, Electrical Systems Modeling, SNL
2548 // Creation Date : 03/22/2013
2549 //-----------------------------------------------------------------------------
2551 {
2552  // dStoreQ/dt = spn0 - (sec.alpha_/hn)(S(x)-sn0)
2553  ds.nextStoreLeadCurrQCompDerivPtr->
2554  linearCombo(1.0,*ds.nextStoreLeadCurrQCompPtr,-1.0,*ds.stoQCn0Ptr);
2555  ds.nextStoreLeadCurrQCompDerivPtr->
2556  linearCombo(1.0,*ds.stoQCpn0Ptr,-sec.alphas_/sec.currentTimeStep,*ds.nextStoreLeadCurrQCompDerivPtr);
2557  ds.nextStorePtr->linearCombo(1.0,*ds.nextStorePtr,1.0,*ds.nextStoreLeadCurrQCompDerivPtr);
2558 
2559 }
2560 
2561 
2562 
2563 //-----------------------------------------------------------------------------
2564 // Function : N_TIA_BackwardDifferentiation15::getInitialQnorm
2565 // Purpose : Needed by 2-level solves.
2566 // Special Notes :
2567 // Scope : public
2568 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2569 // Creation Date : 03/18/07
2570 //-----------------------------------------------------------------------------
2572 {
2573  tle.q1HistorySum = ds.partialSum_q1();
2574 }
2575 
2576 //-----------------------------------------------------------------------------
2577 // Function : N_TIA_BackwardDifferentiation15::setupTwoLevelError
2578 // Purpose : Needed by 2-level solves.
2579 // Special Notes :
2580 // Scope : public
2581 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2582 // Creation Date : 03/15/07
2583 //-----------------------------------------------------------------------------
2585 {
2586  tle.xErrorSum = ds.partialErrorNormSum ();
2587  tle.qErrorSum = ds.partialQErrorNormSum ();
2588  tle.xErrorSum_m1 = ds.partialSum_m1 (sec.currentOrder_);
2589  tle.xErrorSum_m2 = ds.partialSum_m2 (sec.currentOrder_);
2590  tle.xErrorSum_p1 = ds.partialSum_p1 (sec.currentOrder_, sec.maxOrder_);
2591  tle.innerSize = ds.globalLength ();
2592 
2593 #ifdef Xyce_DEBUG_TIME
2594  Xyce::dout() << tle;
2595 #endif
2596 }
2597