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