Xyce  6.1
N_TIA_OneStep.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_TIA_OneStep.C,v $
27 //
28 // Purpose : This file contains the functions which define the
29 // Trap method, order 1-2, class.
30 //
31 // Special Notes :
32 //
33 // Creator : Ting Mei
34 //
35 // Creation Date : 2/16/04
36 //
37 // Revision Information:
38 // ---------------------
39 //
40 // Revision Number: $Revision: 1.108 $
41 //
42 // Revision Date : $Date: 2015/09/03 22:11:40 $
43 //
44 // Current Owner : $Author: rlschie $
45 //-----------------------------------------------------------------------------
46 
47 #include <Xyce_config.h>
48 
49 // ---------- Standard Includes ----------
50 #include <iostream>
51 
52 // ---------- Xyce Includes ----------
53 #include <N_TIA_OneStep.h>
54 
55 #include <N_ANP_OutputMgrAdapter.h>
56 #include <N_ERH_ErrorMgr.h>
57 #include <N_IO_InitialConditions.h>
58 #include <N_LAS_BlockVector.h>
59 #include <N_LAS_Matrix.h>
60 #include <N_LAS_System.h>
61 #include <N_LAS_Vector.h>
62 #include <N_PDS_Comm.h>
63 #include <N_PDS_Manager.h>
64 #include <N_TIA_DataStore.h>
65 #include <N_TIA_StepErrorControl.h>
66 #include <N_TIA_TIAParams.h>
68 #include <N_UTL_Diagnostic.h>
69 #include <N_UTL_FeatureTest.h>
70 #include <N_UTL_MachDepParams.h>
71 
72 using std::min;
73 using std::max;
74 using std::abs;
75 
76 namespace Xyce {
77 namespace TimeIntg {
78 
79 const char *
80 OneStep::name = "Onestep: Trapezoidal";
81 
82 //-----------------------------------------------------------------------------
83 // Function : OneStep::factory
84 // Purpose :
85 // Special Notes :
86 // Scope : public
87 // Creator : Ting Mei, SNL
88 // Creation Date : 10/31/07
89 //-----------------------------------------------------------------------------
90 TimeIntegrationMethod *
92  const TIAParams & tia_params,
93  StepErrorControl & step_error_control,
94  DataStore & data_store)
95 {
96  return new OneStep(tia_params, step_error_control, data_store);
97 }
98 
99 
100 //-----------------------------------------------------------------------------
101 // Function : OneStep::OneStep
102 // Purpose : constructor
103 // Special Notes :
104 // Scope : public
105 // Creator : Ting Mei, SNL
106 // Creation Date : 11/16/07
107 //-----------------------------------------------------------------------------
109  const TIAParams & tia_params,
110  StepErrorControl & secTmp,
111  DataStore & dsTmp)
113  leadingCoeff(1.0),
114  sec(secTmp),
115  ds(dsTmp),
116  timeStepForHistory2_(0.0)
117 {
118  leadingCoeff = 1;
119  sec.maxOrder_=(std::min(2,tia_params.maxOrder));
120  sec.minOrder_=(std::max(1,tia_params.minOrder));
121 
122  if (sec.minOrder_ > sec.maxOrder_)
123  {
125  }
126  // sec.maxOrder_ = 2;
127  timept_ = -1.0;
128  return ;
129 }
130 
131 //-----------------------------------------------------------------------------
132 // Function : OneStep::obtainPredictor
133 // Purpose : Calculate predictor
134 // Special Notes : stored in ds.xn0Ptr,qn0Ptr,qpn0Ptr
135 // Scope : public
136 // Creator : Ting Mei, SNL
137 // Creation Date : 11/16/07
138 //-----------------------------------------------------------------------------
140 {
141  // evaluate predictor
142  *ds.xn0Ptr = *(ds.xHistory[0]);
143  *ds.qn0Ptr = *(ds.qHistory[0]);
144  *ds.sn0Ptr = *(ds.sHistory[0]);
145  *ds.ston0Ptr = *(ds.stoHistory[0]);
147 
150 
151  ds.spn0Ptr->putScalar(0.0);
152  ds.stopn0Ptr->putScalar(0.0); // need to verify that these are needed
153  ds.stoQpn0Ptr->putScalar(0.0); // need to verify that these are needed
154  ds.leadCurrentpn0Ptr->putScalar(0.0);
155  ds.leadCurrentQpn0Ptr->putScalar(0.0);
156 
157  for (int i=1;i<=sec.currentOrder_;++i)
158  {
159  ds.xn0Ptr->linearCombo(sec.beta_[i],*(ds.xHistory[i]),1.0,*ds.xn0Ptr);
160  }
161 
162  if (DEBUG_TIME && isActive(Diag::TIME_PREDICTOR))
163  {
164  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
165  Xyce::dout() << std::endl;
166  Xyce::dout() << Xyce::section_divider << std::endl;
167  Xyce::dout() <<
168  " OneStep::obtainPredictor" << std::endl;
169  Xyce::dout() << "\n currentOrder = " << sec.currentOrder_ << std::endl;
170  Xyce::dout() << "\n sec.nscsco_: " << sec.nscsco_ << std::endl;
171  for (int i=0; i<=sec.currentOrder_ ; ++i)
172  Xyce::dout() << "\n sec.beta_[" << i << "] = " << sec.beta_[i] << "\n" << std::endl;
173  for (int i=0; i<=sec.currentOrder_ ; ++i)
174  {
175  Xyce::dout() << "\n xHistory["<< i << "]: \n" << std::endl;
176  (ds.xHistory[i])->printPetraObject(Xyce::dout());
177  Xyce::dout() << std::endl;
178  }
179  for (int i=0; i<=sec.currentOrder_ ; ++i)
180  {
181  Xyce::dout() << "\n qHistory["<< i << "]: \n" << std::endl;
182  (ds.qHistory[i])->printPetraObject(Xyce::dout());
183  Xyce::dout() << std::endl;
184  }
185  for (int i=0; i<=sec.currentOrder_ ; ++i)
186  {
187  Xyce::dout() << "\n sHistory["<< i << "]: \n" << std::endl;
188  (ds.sHistory[i])->printPetraObject(Xyce::dout());
189  Xyce::dout() << std::endl;
190  }
191  for (int i=0; i<=sec.currentOrder_ ; ++i)
192  {
193  Xyce::dout() << "\n stoHistory["<< i << "]: \n" << std::endl;
194  (ds.stoHistory[i])->printPetraObject(Xyce::dout());
195  Xyce::dout() << std::endl;
196  }
197  for (int i=0; i<=sec.currentOrder_ ; ++i)
198  {
199  Xyce::dout() << "\n stoLeadCurrQHistory["<< i << "]: \n" << std::endl;
200  (ds.stoLeadCurrQHistory[i])->printPetraObject(Xyce::dout());
201  Xyce::dout() << std::endl;
202  }
203  Xyce::dout() << "\n xn0: \n" << std::endl;
204  ds.xn0Ptr->printPetraObject(Xyce::dout());
205  Xyce::dout() << std::endl;
206  Xyce::dout() << "\n qn0: \n" << std::endl;
207  ds.qn0Ptr->printPetraObject(Xyce::dout());
208  Xyce::dout() << std::endl;
209  Xyce::dout() << "\n qpn0: \n" << std::endl;
210  ds.qpn0Ptr->printPetraObject(Xyce::dout());
211  Xyce::dout() << std::endl;
212  Xyce::dout() << "\n sn0: \n" << std::endl;
213  ds.sn0Ptr->printPetraObject(Xyce::dout());
214  Xyce::dout() << std::endl;
215  Xyce::dout() << "\n spn0: \n" << std::endl;
216  ds.spn0Ptr->printPetraObject(Xyce::dout());
217  Xyce::dout() << std::endl;
218  Xyce::dout() << "\n stoQn0Ptr: \n" << std::endl;
219  ds.stoQn0Ptr->printPetraObject(Xyce::dout());
220  Xyce::dout() << std::endl;
221  Xyce::dout() << "\n stoQpn0Ptr: \n" << std::endl;
222  ds.stoQpn0Ptr->printPetraObject(Xyce::dout());
223  Xyce::dout() << std::endl;
224  Xyce::dout() << Xyce::section_divider << std::endl;
225  }
226 
227  // copy the prediction into the next solution:
228  *(ds.nextSolutionPtr) = *(ds.xn0Ptr);
229 
231 
232  return;
233 }
234 
235 //-----------------------------------------------------------------------------
236 // Function : OneStep::obtainSensitivityPredictors
237 // Purpose : Calculate predictor
238 // Special Notes :
239 // Scope : public
240 // Creator : Eric Keiter, SNL
241 // Creation Date :
242 //-----------------------------------------------------------------------------
244 {
245 
246  return;
247 }
248 
249 //-----------------------------------------------------------------------------
250 // Function : OneStep::obtainResidual
251 // Purpose : Calculate Residual
252 // Special Notes :
253 // Scope : public
254 // Creator : Ting Mei, SNL
255 // Creation Date : 11/16/07
256 //-----------------------------------------------------------------------------
258 {
259  // output: ds.RHSVectorPtr
260  // Note: ds.nextSolutionPtr is used to get Q,F,B in Analysis::AnalysisManager::loadRHS.
261  ds.RHSVectorPtr->linearCombo(1.0,*ds.daeQVectorPtr,-1.0,*ds.qn0Ptr);
262 
263  if (DEBUG_TIME && isActive(Diag::TIME_RESIDUAL))
264  {
265  Xyce::dout() << std::endl;
266  Xyce::dout() << Xyce::section_divider << std::endl;
267  Xyce::dout() <<
268  " OneStep::obtainResidual" << std::endl;
269  Xyce::dout() << "\n t = " << sec.nextTime << "\n" << std::endl;
270  Xyce::dout() << "\n solution: \n" << std::endl;
271  ds.nextSolutionPtr->printPetraObject(Xyce::dout());
272  Xyce::dout() << "\n daeQVector: \n" << std::endl;
273  ds.daeQVectorPtr->printPetraObject(Xyce::dout());
274  Xyce::dout() << "\n qn0: \n" << std::endl;
275  ds.qn0Ptr->printPetraObject(Xyce::dout());
276  Xyce::dout() << "\n qpn0: \n" << std::endl;
277  ds.qpn0Ptr->printPetraObject(Xyce::dout());
278  Xyce::dout() << "\n sec.alphas_/hn: " << sec.alphas_/sec.currentTimeStep << "\n" << std::endl;
279  Xyce::dout() << "\n daeFVector: \n" << std::endl;
280  ds.daeFVectorPtr->printPetraObject(Xyce::dout());
281 
282  Xyce::dout() << "\n dQdt-vector: \n" << std::endl;
283  ds.RHSVectorPtr->printPetraObject(Xyce::dout());
284  Xyce::dout() << std::endl;
285  }
286 
287  if (sec.currentOrder_ == 2)
288  {
289  ds.RHSVectorPtr->linearCombo(1.0/sec.currentTimeStep,*ds.RHSVectorPtr,+1.0/2.0,*ds.daeFVectorPtr);
290  ds.RHSVectorPtr->linearCombo(1.0,*ds.RHSVectorPtr,-1.0/2.0,*ds.daeBVectorPtr);
291  ds.RHSVectorPtr->linearCombo(1.0,*ds.RHSVectorPtr,+1.0/2.0,*ds.qHistory[2]);
292  }
293  else
294  {
296  ds.RHSVectorPtr->linearCombo(1.0,*ds.RHSVectorPtr,-1.0,*ds.daeBVectorPtr);
297  }
298  // since the nonlinear solver is expecting a -f, scale by -1.0:
299  ds.RHSVectorPtr->scale(-1.0);
300 
301  // if voltage limiting is on, add it in:
302  if (ds.limiterFlag)
303  {
305 
306  (ds.RHSVectorPtr)->daxpy(
307  *(ds.RHSVectorPtr), +1.0, *(ds.dQdxdVpVectorPtr));
308 
309  double fscalar(1.0);
310 
311  if (sec.currentOrder_ == 2)
312  fscalar =1.0/2.0;
313 
314  (ds.RHSVectorPtr)->daxpy(
315  *(ds.RHSVectorPtr), fscalar, *(ds.dFdxdVpVectorPtr));
316  }
317 
318  if (DEBUG_TIME && isActive(Diag::TIME_RESIDUAL))
319  {
320  Xyce::dout() << "\n Residual-vector: \n" << std::endl;
321  Xyce::dout() << "-(qpn0-(sec.alpha_s/h)*(Q-qn0)+F-B) \n" << std::endl;
322  ds.RHSVectorPtr->printPetraObject(Xyce::dout());
323  Xyce::dout() << Xyce::section_divider << std::endl;
324  Xyce::dout() << std::endl;
325  }
326 }
327 
328 //-----------------------------------------------------------------------------
329 // Function : OneStep::obtainSensitivityResiduals
330 // Purpose : Calculate Sensitivity Residual
331 // Special Notes :
332 // Scope : public
333 // Creator : Eric Keiter, SNL
334 // Creation Date : 09/02/2014
335 //-----------------------------------------------------------------------------
337 {
338  int numParams = ds.sensRHSPtrVector.size();
339  for (int ip=0; ip<numParams;++ip)
340  {
341  Linear::Vector & RHSVec = *(ds.sensRHSPtrVector[ip]);
342  Linear::Vector & dfdpVec = *(ds.nextDfdpPtrVector[ip]);
343  Linear::Vector & dqdpVec = *(ds.nextDqdpPtrVector[ip]);
344  Linear::Vector & dbdpVec = *(ds.nextDbdpPtrVector[ip]);
345 
346  Linear::Vector & currDXdpVec = *(ds.currDXdpPtrVector[ip]);
347 
348  //Linear::Vector & dqdpn0Vec = *(ds.dqdpn0PtrVector[ip]);
349  std::vector<Linear::Vector*> & dqdpHistory = ds.dqdpHistory[ip];
350 
351  Linear::Vector & currDQdxDXdpVec = *(ds.currDQdxDXdpPtrVector[ip]);
352 
353  Linear::Vector & nextDQdxDXdpDerivVec = *(ds.nextDQdxDXdpDerivPtrVector[ip]);
354  Linear::Vector & currDQdxDXdpDerivVec = *(ds.currDQdxDXdpDerivPtrVector[ip]);
355 
356  Linear::Vector & nextDqdpDerivVec = *(ds.nextDqdpDerivPtrVector[ip]);
357  Linear::Vector & currDqdpDerivVec = *(ds.currDqdpDerivPtrVector[ip]);
358 
359 
360  if (sec.currentOrder_ == 2)
361  {
362  //nextDqdpDerivVec.linearCombo(1.0,dqdpVec,-1.0, dqdpn0Vec);
363  nextDqdpDerivVec.linearCombo(1.0,dqdpVec,-1.0, *(dqdpHistory[0]));
364  nextDqdpDerivVec.scale(2.0/sec.currentTimeStep);
365  nextDqdpDerivVec.linearCombo(-1.0,currDqdpDerivVec,1.0,nextDqdpDerivVec);
366 
367  RHSVec.linearCombo(0.5,nextDqdpDerivVec,+0.5,dfdpVec);
368  RHSVec.linearCombo(1.0,RHSVec,-0.5,dbdpVec);
369  }
370  else
371  {
372  //nextDqdpDerivVec.linearCombo(1.0,dqdpVec,-1.0, dqdpn0Vec);
373  nextDqdpDerivVec.linearCombo(1.0,dqdpVec,-1.0, *(dqdpHistory[0]));
374  nextDqdpDerivVec.scale(1.0/sec.currentTimeStep);
375 
376  RHSVec.linearCombo(1.0,nextDqdpDerivVec,+1.0,dfdpVec);
377  RHSVec.linearCombo(1.0,RHSVec,-1.0,dbdpVec);
378  }
379 
380  // since the nonlinear solver is expecting a -dFdp, scale by -1.0:
381  RHSVec.scale(-1.0);
382 
383  // correction terms
384  double qscalar(-sec.alphas_/sec.currentTimeStep);
385  RHSVec.linearCombo(1.0,RHSVec, qscalar, currDQdxDXdpVec);
386 
387  // second order "correction" term
388  if (sec.currentOrder_ == 2)
389  {
390  RHSVec.linearCombo(1.0,RHSVec, 0.5, currDQdxDXdpDerivVec);
391  }
392 
393 #ifdef DEBUG_SENS
394  Xyce::dout() << "obtainSensitivityResiduals: RHS Vector, ip = " << ip << ":\n";
395  RHSVec.printPetraObject(Xyce::dout());
396 #endif
397  }
398 }
399 
400 //-----------------------------------------------------------------------------
401 // Function : OneStep::loadFinalSensitivityDerivatives
402 // Purpose : obtain final derivatives w.r.t. time for transient
403 // sensitivity analysis
404 // Special Notes :
405 // Scope : public
406 // Creator : Eric Keiter, SNL
407 // Creation Date : 09/02/2014
408 //-----------------------------------------------------------------------------
410 {
411  int numParams = ds.sensRHSPtrVector.size();
412  for (int ip=0; ip<numParams;++ip)
413  {
414  Linear::Vector & nextDQdxDXdpVec = *(ds.nextDQdxDXdpPtrVector[ip]);
415  Linear::Vector & currDQdxDXdpVec = *(ds.currDQdxDXdpPtrVector[ip]);
416 
417  Linear::Vector & nextDQdxDXdpDerivVec = *(ds.nextDQdxDXdpDerivPtrVector[ip]);
418  Linear::Vector & currDQdxDXdpDerivVec = *(ds.currDQdxDXdpDerivPtrVector[ip]);
419 
420  double dt = sec.currentTimeStep;
421  if (sec.currentOrder_ == 2)
422  {
423  nextDQdxDXdpDerivVec.putScalar(0.0);
424  nextDQdxDXdpDerivVec.linearCombo(2.0,nextDQdxDXdpVec,-2.0,currDQdxDXdpVec);
425  nextDQdxDXdpDerivVec.scale(1.0/dt);
426  nextDQdxDXdpDerivVec.linearCombo(-1.0,currDQdxDXdpDerivVec,1.0,nextDQdxDXdpDerivVec);
427  }
428  else
429  {
430  nextDQdxDXdpDerivVec.putScalar(0.0);
431  nextDQdxDXdpDerivVec.linearCombo(1.0,nextDQdxDXdpVec,-1.0,currDQdxDXdpVec);
432  nextDQdxDXdpDerivVec.scale(1.0/dt);
433  }
434  }
435 }
436 
437 //-----------------------------------------------------------------------------
438 // Function : OneStep::obtainJacobian
439 // Purpose : Calculate Jacobian
440 // Special Notes :
441 // Scope : public
442 // Creator : Ting Mei, SNL
443 // Creation Date : 11/16/07
444 //-----------------------------------------------------------------------------
446 {
447  if (DEBUG_TIME && isActive(Diag::TIME_JACOBIAN))
448  {
449  Xyce::dout() << std::endl;
450  Xyce::dout() << Xyce::section_divider << std::endl;
451  Xyce::dout() <<
452  " OneStep::obtainJacobian" << std::endl;
453  }
454 
455  // output: ds.JMatrixPtr
456 
457  // This function returns the following matrix:
458  // $-(sec.alphas_/hn)dQdx(x)+dFdx$
459 
460  // Note: ds.nextSolutionPtr is used to get dQdx,dFdx in Analysis::AnalysisManager::loadJacobian.
461 
462  Linear::Matrix & dQdx = *(ds.dQdxMatrixPtr);
463  Linear::Matrix & dFdx = *(ds.dFdxMatrixPtr);
464  Linear::Matrix & Jac = *(ds.JMatrixPtr);
465 
466  double qscalar(-sec.alphas_/sec.currentTimeStep);
467  double fscalar(1.0);
468  if (sec.currentOrder_ == 2)
469  fscalar =1.0/2.0;
470 
471  Jac.linearCombo( qscalar, dQdx, fscalar, dFdx );
472 
473  if (DEBUG_TIME && isActive(Diag::TIME_JACOBIAN))
474  {
475  Xyce::dout() << "fscalar = " << fscalar << " qscalar = " << qscalar << std::endl;
476 
477  Xyce::dout() << "\n dFdx:" <<std::endl;
478  dFdx.printPetraObject(Xyce::dout());
479  Xyce::dout() << "\n dQdx:" <<std::endl;
480  dQdx.printPetraObject(Xyce::dout());
481  Xyce::dout() << "\n Total Jacobian:" <<std::endl;
482  Jac.printPetraObject(Xyce::dout());
483  // for (int i=0;i<3;++i)
484  // {
485  // printf("[ %25.20g\t%25.20g\t%25.20g ]\n",Jac[i][0],Jac[i][1],Jac[i][2]);
486  // }
487 
488  Xyce::dout() << Xyce::section_divider << std::endl;
489  Xyce::dout() << std::endl;
490  }
491 }
492 
493 //-----------------------------------------------------------------------------
494 // Function : OneStep::interpolateSolution
495 // Purpose : Interpolate solution approximation at prescribed time point.
496 // Scope : public
497 // Creator : Ting Mei, SNL
498 // Creation Date : 11/16/07
499 //-----------------------------------------------------------------------------
500 bool OneStep::interpolateSolution(double timepoint,
501  Linear::Vector * tmpSolVectorPtr, std::vector<Linear::Vector*> & historyVec)
502 {
503  // this is a very course approximation to determine if we are too
504  // close to the actual time step to do an interpolation.
505  // it could use more work.
506  double dtr = timepoint - sec.currentTime; // the delta time requested.
507  *tmpSolVectorPtr = *(historyVec[0]);
508 
509  if( -dtr < 2 * Util::MachineDependentParams::MachinePrecision() )
510  {
511  return false;
512  }
513 
514  if( sec.usedOrder_ <= 2)
515  {
516  // do first order interpolation
517  // X_interp = X + delta_t_requested * delta_X/delta_t[last step]
518  dtr = dtr / sec.lastTimeStep;
519  tmpSolVectorPtr->linearCombo(1.0,*tmpSolVectorPtr,dtr,*(historyVec[1]));
520  }
521 
522  return true;
523 }
524 
525 //-----------------------------------------------------------------------------
526 // Function : OneStep::interpolateMPDESolution
527 // Purpose : Interpolate solution approximation at prescribed time points.
528 // Special Notes : This routine computes the solution at the output
529 // : timepoints by intepolation of the history using the order
530 // : used for the most recent completed step, orderUsed.
531 // : The output is put into provided Linear::Vector pointer.
532 // : The interpolation is as follows:
533 // : tmpSolVectorPtr->block(i) is interpolated at timepoint(i)
534 // : Therefore, if you want them all interpolated at the same time,
535 // : then use timepoint(i) = timepoint(0) forall i
536 // : or use interpolateSolution.
537 // Scope : public
538 // Creator : Ting Mei, Eric Keiter, SNL
539 // Creation Date : 11/28/06
540 //-----------------------------------------------------------------------------
541 bool OneStep::interpolateMPDESolution(std::vector<double>& timepoint,
542  Linear::Vector * tmpSolVectorPtr)
543 {
544  Linear::BlockVector * blockTempSolVectorPtr =
545  dynamic_cast<Linear::BlockVector*>(tmpSolVectorPtr);
546  if (blockTempSolVectorPtr == NULL)
547  {
548  std::string msg = "OneStep::interpolateMPDESolution: ";
549  msg += "Linear::Vector tmpSolVectorPtr is not of type Linear::BlockVector";
550  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
551  return(false);
552  }
553 
554  double tfuzz; // fuzz factor to check for valid output time
555  double tp; // approximately t_{n-1}
556  int numblocks = timepoint.size();
557  int blockCount = blockTempSolVectorPtr->blockCount();
558  if (numblocks > blockCount)
559  {
560  std::string msg = "OneStep::interpolateMPDESolution: ";
561  msg += "Number of time points requested is greater than number of fast time points in MPDE block vector";
562  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
563  return(false);
564  }
565  double delt;
566  double c = 1.0;
567  double gam;
568  int kord; // order of interpolation
569  double tn = sec.currentTime;
570  double hh = sec.currentTimeStep;
571  double hused = sec.usedStep_;
572  int kused = sec.usedOrder_;
573  double uround = 0.0; // unit round-off (set to zero for now)
574 
575  tfuzz = 100 * uround * (tn + hh);
576  tp = tn - hused - tfuzz;
577  for (int i=0; i<numblocks ; ++i)
578  {
579  if ( (timepoint[i] - tp)*hh < 0.0 )
580  return false;
581  }
582 
583  *tmpSolVectorPtr = *(ds.xHistory[0]);
584 
585  Linear::Vector * solVectorPtr;
586  Linear::Vector * xHistoryVectorPtr;
587  // Loop over blocks first so that maximal order can be maintained
588  for (int i=0; i < numblocks ; ++i)
589  {
590  if ((kused == 0) || (timepoint[i] == tn)) { kord = 1; }
591  else { kord = kused; }
592  solVectorPtr = &(blockTempSolVectorPtr->block(i));
593  c = 1.0;
594  delt = timepoint[i] - tn;
595  gam = delt/sec.psi_[0];
596  for (int j=1 ; j <= kord ; ++j)
597  {
598  c = c*gam;
599  gam = (delt + sec.psi_[j-1])/sec.psi_[j];
600  Linear::BlockVector * blockXHistoryVectorPtr =
601  dynamic_cast<Linear::BlockVector*>(ds.xHistory[j]);
602  if (blockXHistoryVectorPtr == NULL)
603  {
604  Xyce::Report::DevelFatal0().in("OneStep::interpolateMPDESolution") << "Linear::Vector ds.xHistory[j] is not of type Linear::BlockVector\n j = " << j;
605  return(false);
606  }
607  xHistoryVectorPtr = &(blockXHistoryVectorPtr->block(i));
608  solVectorPtr->linearCombo(1.0,*solVectorPtr,c,*xHistoryVectorPtr);
609  }
610  }
611  return true;
612 }
613 
614 //-----------------------------------------------------------------------------
615 // Function : OneStep::printMPDEOutputSolution()
616 // Purpose : Print transient output from MPDE simulation
617 // Special Notes : This routine uses interpolateMPDESolution.
618 // Scope : public
619 // Creator : Ting Mei, SNL
620 // Creation Date : 11/28/06
621 //-----------------------------------------------------------------------------
623  Analysis::OutputMgrAdapter & outputManagerAdapter,
624  const double time,
625  Linear::Vector * solnVecPtr,
626  const std::vector<double> & fastTimes )
627 {
628  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
629  {
630  Xyce::dout() << std::endl;
631  Xyce::dout() << Xyce::section_divider << std::endl;
632  Xyce::dout() <<
633  " OneStep::printMPDEOutputSolution" << std::endl;
634  }
635 
636  double timestep = sec.lastAttemptedTimeStep;
637  double lasttime = sec.currentTime - timestep;
638  double tn = sec.currentTime;
639  // Set these values up to read output time intervals. FIXME
640  double beg_of_output_time_interval = lasttime;
641  double end_of_output_time_interval = tn;
642  double start_time = max(lasttime,beg_of_output_time_interval);
643  double stop_time = min(tn,end_of_output_time_interval);
644  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
645  {
646  Xyce::dout() << "timestep = " << timestep << std::endl;
647  Xyce::dout() << "lasttime = " << lasttime << std::endl;
648  Xyce::dout() << "tn = " << tn << std::endl;
649  Xyce::dout() << "beg_of_output_time_interval = " << beg_of_output_time_interval << std::endl;
650  Xyce::dout() << "end_of_output_time_interval = " << end_of_output_time_interval << std::endl;
651  Xyce::dout() << "start_time = " << start_time << std::endl;
652  Xyce::dout() << "stop_time = " << stop_time << std::endl;
653  }
654 
655  Linear::BlockVector * blockTmpSolVectorPtr =
656  dynamic_cast<Linear::BlockVector*>(ds.tmpSolVectorPtr);
657  if (blockTmpSolVectorPtr == NULL)
658  {
659  std::string msg = "OneStep::printMPDEOutputSolution: ";
660  msg += "Linear::Vector ds.tmpSolVectorPtr is not of type Linear::BlockVector";
661  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
662  return(false);
663  }
664  int blockCount = blockTmpSolVectorPtr->blockCount();
665 
666  // Create list of timepoints to interpolate (along characteristic curve)
667  double T2 = fastTimes.back();
668  //double charcross = start_time - floor(start_time/T2)*T2; // (start_time mod T2)
669  double charcross = fmod(start_time,T2); // (start_time mod T2)
670  int s_ind_0 = -1;
671  // find s_ind_0 = first fast time point >= charcross.
672  // This could probably be made faster: FIXME
673  for (int i=0 ; i<=blockCount ; ++i)
674  {
675  if (fastTimes[i] >= charcross)
676  {
677  s_ind_0 = i;
678  break;
679  }
680  }
681  if (s_ind_0 == -1)
682  {
683  std::string msg = "OneStep::printMPDEOutputSolution: ";
684  msg += "Cannot find where characteristic curve crosses fast time slice at start_time";
685  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
686  return(false);
687  }
688  std::vector<double> h2(blockCount,0);
689  for (int j=0 ; j < blockCount ; ++j)
690  {
691  h2[j] = fastTimes[j+1] - fastTimes[j];
692  }
693  std::vector<double> ti;
694  //double first_interp = floor(start_time/T2)*T2 + fastTimes[s_ind_0];
695  double first_interp = start_time - charcross + fastTimes[s_ind_0];
696  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
697  {
698  Xyce::dout() << "first_interp = " << first_interp << std::endl;
699  }
700 
701  if (s_ind_0 == blockCount) { s_ind_0 = 0; };
702  // Don't interpolate the first point
703  double eps = fabs(start_time)*1.0e-6;
704  if ( fabs(first_interp-timept_) <= eps )
705  {
706  first_interp += h2[s_ind_0];
707  s_ind_0++;
708  if (s_ind_0 == blockCount) { s_ind_0 = 0; };
709  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
710  {
711  Xyce::dout() << "Moving first_interp forward to avoid duplicate outputs: " << first_interp << std::endl;
712  }
713  }
714  int sn = s_ind_0;
715  double t = first_interp;
716  while (t <= stop_time)
717  {
718  ti.push_back(t);
719  t += h2[sn];
720  sn++;
721  if (sn >= blockCount) { sn = 0; }
722  }
723  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
724  {
725  Xyce::dout() << "T2 = " << T2 << std::endl;
726  Xyce::dout() << "charcross = " << charcross << std::endl;
727  Xyce::dout() << "s_ind_0 = " << s_ind_0 << std::endl;
728  Xyce::dout() << "Expecting to interpolate the following points:" << std::endl;
729  unsigned int numinterp = ti.size();
730  for (unsigned int i=0 ; i < numinterp ; ++i)
731  {
732  Xyce::dout() << ti[i] << std::endl;
733  }
734  Xyce::dout() << "Total of " << numinterp << " points" << std::endl;
735  }
736 
737  timept_ = start_time; // used later for interpolating stop_time
738  unsigned int tinum = ti.size();
739  int total_interp = 0;
740  std::vector<double> timepoint_vec(blockCount,stop_time);
741  int num_interp_this_cycle = 0;
742  int s_ind = s_ind_0;
743  for (unsigned int i=0; i < tinum ; ++i)
744  {
745  timepoint_vec[s_ind] = ti[i];
746  num_interp_this_cycle++;
747  s_ind++;
748  if (s_ind >= blockCount) { s_ind = 0; };
749  // If we're back to s_ind_0 or out of ti points, then interpolate:
750  if ((s_ind == s_ind_0) || (i == tinum-1))
751  {
753  // Now we print these points out
754  int s = s_ind_0;
755  for (int j=0 ; j < num_interp_this_cycle ; ++j)
756  {
757  timept_ = timepoint_vec[s];
758  outputManagerAdapter.tranOutput(
759  timept_, blockTmpSolVectorPtr->block(s),
763  total_interp++;
764  s++;
765  if (s >= blockCount) { s = 0; }
766  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
767  Xyce::dout() << "Interpolated to t = " << timept_ << std::endl;
768  }
769  num_interp_this_cycle = 0;
770  }
771  }
772  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
773  Xyce::dout() << "Total of " << total_interp << " points" << std::endl;
774 
775  // Now we interpolate stop_time unless its too close to the last timept interpolated.
776  eps = fabs(stop_time)*1.0e-8;
777  // fudge factor for printing, this should come from elsewhere FIXME
778  if (fabs(timept_ - stop_time) >= eps)
779  {
780  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
781  {
782  Xyce::dout() << "Previous timept = " << timept_ << std::endl;
783  Xyce::dout() << "Expecting to interpolate the following point: " << stop_time << std::endl;
784  }
785  Linear::Vector* tmpSolnVecPtr = solnVecPtr;
786  Linear::Vector* tmpVecPtr = ds.tmpXn0APtr;
787  if (stop_time < tn)
788  {
790  tmpSolnVecPtr = ds.tmpXn0BPtr;
791  }
792  Linear::BlockVector * blockTmpSolnVecPtr =
793  dynamic_cast<Linear::BlockVector*>(tmpSolnVecPtr);
794  Linear::BlockVector * blockTmpVecPtr =
795  dynamic_cast<Linear::BlockVector*>(tmpVecPtr);
796  if (blockTmpSolnVecPtr == NULL)
797  {
798  std::string msg = "OneStep::printMPDEOutputSolution: ";
799  msg += "Linear::Vector tmpSolnVecPtr is not of type Linear::BlockVector";
800  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
801  return(false);
802  }
803  if (blockTmpVecPtr == NULL)
804  {
805  std::string msg = "OneStep::printMPDEOutputSolution: ";
806  msg += "Linear::Vector tmpVecPtr is not of type Linear::BlockVector";
807  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
808  return(false);
809  }
810  // Interpolate where the caracteristic crosses stop_time (instead of start_time).
811  //charcross = stop_time - floor(stop_time/T2)*T2;
812  charcross = fmod(stop_time,T2);
813  int s_ind_1 = -1;
814  // Find index just before charcross:
815  if( charcross < fastTimes[0] )
816  {
817  // by periodicity, the one before in this case is the one at the end
818  s_ind_1 = blockCount-1;
819  }
820  else
821  {
822  for (int i=blockCount-1 ; i>=0 ; --i)
823  {
824  if (fastTimes[i] <= charcross)
825  {
826  s_ind_1 = i;
827  break;
828  }
829  }
830  }
831  if (s_ind_1 == -1)
832  {
833  std::string msg = "OneStep::printMPDEOutputSolution: ";
834  msg += "Cannot find where characteristic curve crosses fast time slice at stop_time";
835  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
836  return(false);
837  }
838  int sm = s_ind_1;
839  int sp = s_ind_1+1;
840  double coeff_sm = fastTimes[sp]-charcross;
841  double coeff_sp = charcross-fastTimes[sm];
842  if (sp == blockCount) { sp = 0; }
843  double dt = h2[s_ind_1];
844  timept_ = stop_time;
845  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
846  {
847  Xyce::dout() << "charcross = " << charcross << std::endl;
848  Xyce::dout() << "s_ind_1 = " << s_ind_1 << std::endl;
849  Xyce::dout() << "sp = " << sp << std::endl;
850  Xyce::dout() << "sm = " << sm << std::endl;
851  Xyce::dout() << "dt = " << dt << std::endl;
852  Xyce::dout() << "timept = " << timept_ << std::endl;
853  Xyce::dout() << "coeff_sm = " << coeff_sm << std::endl;
854  Xyce::dout() << "coeff_sp = " << coeff_sp << std::endl;
855  }
856  blockTmpVecPtr->block(0).linearCombo(
857  coeff_sm/dt, blockTmpSolnVecPtr->block(sm),
858  coeff_sp/dt, blockTmpSolnVecPtr->block(sp)
859  );
860  outputManagerAdapter.tranOutput(timept_, blockTmpVecPtr->block(0),
864  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
865  Xyce::dout() << "Interpolated to t = " << timept_ << std::endl;
866  }
867  else if(DEBUG_TIME && isActive(Diag::TIME_OUTPUT)) // no extra interpolation
868  {
869  Xyce::dout() << "No further interpolation required." << std::endl;
870  }
871 
872  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
873  Xyce::dout() << Xyce::section_divider << std::endl;
874 
875  return true;
876 }
877 
878 //-----------------------------------------------------------------------------
879 // Function : OneStep::printWaMPDEOutputSolution()
880 // Purpose : Print transient output from WaMPDE simulation
881 // Special Notes : This routine uses interpolateSolution.
882 // Scope : public
883 // Creator : Ting Mei, SNL
884 // Creation Date : 12/15/06
885 //-----------------------------------------------------------------------------
887  Analysis::OutputMgrAdapter & outputManagerAdapter,
888  const double time,
889  Linear::Vector * solnVecPtr,
890  const std::vector<double> & fastTimes,
891  const int phiGID )
892 {
893  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
894  {
895  Xyce::dout() << std::endl;
896  Xyce::dout() << Xyce::section_divider << std::endl;
897  Xyce::dout() <<
898  " OneStep::printWaMPDEOutputSolution" << std::endl;
899  }
900 
901  double timestep = sec.lastAttemptedTimeStep;
902  double lasttime = sec.currentTime - timestep;
903  double tn = sec.currentTime;
904  // Set these values up to read output time intervals. FIXME
905  double beg_of_output_time_interval = lasttime;
906  double end_of_output_time_interval = tn;
907  double start_time = max(lasttime,beg_of_output_time_interval);
908  double stop_time = min(tn,end_of_output_time_interval);
909  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
910  {
911  Xyce::dout() << "start_time = " << start_time << std::endl;
912  Xyce::dout() << "stop_time = " << stop_time << std::endl;
913  }
914 
915  // 12/15/06 tscoffe:
916  // First break the interval up as printOutputSolution does:
917  // hh = timestep/(sec.usedOrder_) and interpolate in the intervals:
918  // [tn+(i-1)*hh,tn+i*hh], i=1..usedOrder
919  // Assume phi(t_1) is linear in these intervals and approximate with:
920  // phi(t) = (1/hh)*(phi(tn)(tn+hh-t)+phi(tn+hh)(t-tn))
921  // Then the t_1 values we want to interpolate are:
922  // n2 = number of fast time points.
923  // T2 = fast time period
924  // h2 = T2/n2 = average spacing on fast time scale
925  // t1_vals = [tn:h2:tn+hh]
926  // And the t_2 values we want to interpolate are:
927  // t2_vals = phi(t1_vals) mod T2
928  // Then take the N_LAS blocks and do 2D linear interpolation on the intervals:
929  // (t1,s1), (t1,s2), (t2,s1), (t2,s2)
930  // x(t) = x(t,s) approx =
931  // (1/(t2-t1))(1/(s2-s1))[ x(t1,s1)(t2-t)(s2-s)
932  // +x(t1,s2)(t2-t)(s-s1)
933  // +x(t2,s1)(t-t1)(s2-s)
934  // +x(t2,s2)(t-t1)(s-s1) ]
935  // where t = t1_vals and s = t2_vals
936 
937  Linear::BlockVector * blockTmpSolVectorPtr =
938  dynamic_cast<Linear::BlockVector*>(ds.tmpSolVectorPtr);
939  Linear::BlockVector * blockTmpXn0APtr =
940  dynamic_cast<Linear::BlockVector*>(ds.tmpXn0APtr);
941  Linear::BlockVector * blockTmpXn0BPtr =
942  dynamic_cast<Linear::BlockVector*>(ds.tmpXn0BPtr);
943  if (blockTmpSolVectorPtr == NULL)
944  {
945  std::string msg = "OneStep::printWaMPDEOutputSolution: ";
946  msg += "Linear::Vector ds.tmpSolVectorPtr is not of type Linear::BlockVector";
947  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
948  return(false);
949  }
950  if (blockTmpXn0APtr == NULL)
951  {
952  std::string msg = "OneStep::printWaMPDEOutputSolution: ";
953  msg += "Linear::Vector ds.tmpXn0APtr is not of type Linear::BlockVector";
954  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
955  return(false);
956  }
957  if (blockTmpXn0BPtr == NULL)
958  {
959  std::string msg = "OneStep::printWaMPDEOutputSolution: ";
960  msg += "Linear::Vector ds.tmpXn0BPtr is not of type Linear::BlockVector";
961  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
962  return(false);
963  }
964  int phiLID = blockTmpSolVectorPtr->pmap()->globalToLocalIndex(phiGID);
965  double hh = timestep/(sec.usedOrder_);
966  double timeA = -1.0;
967  double timeB = -1.0;
968  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
969  {
970  Xyce::dout() << " sec.usedOrder_ = " << sec.usedOrder_ << std::endl;
971  Xyce::dout() << " sec.currentTime_ = " << sec.currentTime << std::endl;
972  Xyce::dout() << " lasttime = " << lasttime << std::endl;
973  }
974 
975  for (int i=0 ; i < sec.usedOrder_ ; ++i)
976  {
977  if (i == 0)
978  {
979  bool junk;
980  timeA = lasttime + hh*i;
982  if (!junk)
983  {
984  std::string msg = "interpolateSolution returned false!";
985  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0,msg);
986  }
987  }
988  else
989  {
990  // We don't need to interpolate this again.
992  timeA = timeB;
993  }
994  timeB = lasttime + hh*(i+1);
996  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
997  {
998  Xyce::dout() << "Interpolating in [ " << timeA << ", " << timeB << " ]" << std::endl;
999  Xyce::dout() << "timeA = " << timeA << std::endl;
1000  Xyce::dout() << "timeB = " << timeB << std::endl;
1001  }
1002 
1003  // Now we can interpolate [tmpXn0APtr,tmpXn0BPtr] in [timeA,timeB].
1004  std::vector<double> t1vals;
1005  double T2 = fastTimes.back();
1006  int blockCount = blockTmpSolVectorPtr->blockCount();
1007  double h2 = T2/blockCount; // Average mesh width in fast time-scale
1008  double tval = timeA+h2;
1009  while (tval <= timeB)
1010  {
1011  t1vals.push_back(tval);
1012  tval += h2;
1013  }
1014  // fudge factor for printing, this should come from elsewhere FIXME
1015  double eps = fabs(timeB)*1.0e-8;
1016  if ( (t1vals.size() == 0) || (fabs(t1vals.back() - timeB) >= eps) )
1017  {
1018  t1vals.push_back(timeB);
1019  }
1020  std::vector<double> t2vals, phiAB(2);
1021  std::vector<double> tmpPhiAB(2, 0.0);
1022  if (phiLID >= 0)
1023  {
1024  tmpPhiAB[0] = (*ds.tmpXn0APtr)[phiLID]; // Get from MPDE Manager
1025  tmpPhiAB[1] = (*ds.tmpXn0BPtr)[phiLID]; // Get from MPDE Manager
1026  }
1027  blockTmpSolVectorPtr->pmap()->pdsComm().sumAll( &tmpPhiAB[0], &phiAB[0], 2 );
1028 
1029  double phiA = phiAB[0], phiB = phiAB[1];
1030  for (unsigned int j=0 ; j<t1vals.size() ; ++j)
1031  {
1032  double phi = (1/(timeB-timeA))*(phiA*(timeB-t1vals[j])+phiB*(t1vals[j]-timeA));
1033  t2vals.push_back(fmod(phi,T2)); // phi(t1vals[j]) mod T2
1034  }
1035  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1036  {
1037  Xyce::dout() << "t1vals = " << std::endl;
1038  for (unsigned int j=0 ; j < t1vals.size() ; ++j)
1039  {
1040  Xyce::dout() << t1vals[j] << std::endl;
1041  }
1042  Xyce::dout() << "phi(" << timeA << ") = " << phiA << std::endl;
1043  Xyce::dout() << "phi(" << timeB << ") = " << phiB << std::endl;
1044  Xyce::dout() << "t2vals = " << std::endl;
1045  for (unsigned int j=0 ; j< t2vals.size() ; ++j)
1046  {
1047  Xyce::dout() << t2vals[j] << std::endl;
1048  }
1049  }
1050 
1051  // Now we can do our block 2D interpolations
1052  // loop through t1vals and move the fast time blocks as we go
1053  double t1 = timeA; // slow time indices
1054  double t2 = timeB;
1055  double t = t1vals[0]; // current time indices
1056  double s = t2vals[0];
1057  int b1,b2; // fast time block indices corresponding to s1,s2
1058  // Find the block surrounding s:
1059  b1 = -2;
1060  for (int j=0 ; j < blockCount ; ++j)
1061  {
1062  if ((fastTimes[j] <= s) && (s < fastTimes[j+1]))
1063  {
1064  b1 = j;
1065  }
1066  }
1067  b2 = b1+1;
1068  if (b2 == blockCount)
1069  {
1070  b2 = 0;
1071  }
1072  double s1 = fastTimes[b1];
1073  double s2 = fastTimes[b1+1]; // Note: fastTimes[blockCount] = T2
1074  if ((s < s1) || (s > s2))
1075  {
1076  std::string msg = "OneStep::printWaMPDEOutputSolution: ";
1077  msg += " Interpolator cannot find a fast time block containing the first point ";
1078  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
1079  }
1080  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1081  Xyce::dout() << "Found s = " << s << " in block " << b1 << " with boundary = [" << s1 << "," << s2 << "]" << std::endl;
1082 
1083  for (unsigned int j=0 ; j < t1vals.size() ; ++j)
1084  {
1085  t = t1vals[j];
1086  s = t2vals[j];
1087  if (t > t2) break; // This should never occur
1088  // If s has moved outside our block, then increment block.
1089  if ( (s < s1) || (s > s2) )
1090  {
1091  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1092  Xyce::dout() << "Incrementing fast time block for next interpolation." << std::endl;
1093 
1094  b1++;
1095  if (b1 == blockCount)
1096  {
1097  b1 = 0;
1098  }
1099  b2 = b1+1;
1100  if (b2 == blockCount)
1101  {
1102  b2 = 0;
1103  }
1104  s1 = fastTimes[b1];
1105  s2 = fastTimes[b1+1];
1106  }
1107  // If s isn't in the next block, then search for it.
1108  if ((s < s1) || (s > s2))
1109  {
1110  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1111  Xyce::dout() << "Searching for fast time block for next interpolation." << std::endl;
1112 
1113  b1 = -2;
1114  for (int j2=0 ; j2 < blockCount ; ++j2)
1115  {
1116  if ((fastTimes[j2] <= s) && (s < fastTimes[j2+1]))
1117  {
1118  b1 = j2;
1119  }
1120  }
1121  b2 = b1+1;
1122  if (b2 == blockCount)
1123  {
1124  b2 = 0;
1125  }
1126  s1 = fastTimes[b1];
1127  s2 = fastTimes[b1+1];
1128  }
1129  // If a block surrounding s can't be found, then quit.
1130  if ((s < s1) || (s > s2))
1131  {
1132  std::string msg = "OneStep::printWaMPDEOutputSolution: ";
1133  msg += " Interpolator moved fast time block but new point is not in this block ";
1134  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
1135  }
1136  if (s > T2) break; // Just double checking...
1137  //blockTmpXn0APtr->block(b1) // x(t1,s1)
1138  //blockTmpXn0APtr->block(b2) // x(t1,s2)
1139  //blockTmpXn0BPtr->block(b1) // x(t2,s1)
1140  //blockTmpXn0BPtr->block(b2) // x(t2,s2)
1141  // (1/(t2-t1))(1/(s2-s1))[ x(t1,s1)(t2-t)(s2-s)
1142  // +x(t1,s2)(t2-t)(s-s1)
1143  // +x(t2,s1)(t-t1)(s2-s)
1144  // +x(t2,s2)(t-t1)(s-s1) ]
1145  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1146  {
1147  Xyce::dout() << "Interpolating in the block:" << std::endl;
1148  Xyce::dout() << "(t1,t2) = (" << t1 << "," << t2 << ")" << std::endl;
1149  Xyce::dout() << "(s1,s2) = (" << s1 << "," << s2 << ")" << std::endl;
1150  }
1151 
1152  double denom = (t2-t1)*(s2-s1);
1153  double coeff0 = (t2-t)*(s2-s)/denom;
1154  double coeff1 = (t2-t)*(s-s1)/denom;
1155  double coeff2 = (t-t1)*(s2-s)/denom;
1156  double coeff3 = (t-t1)*(s-s1)/denom;
1157  (blockTmpSolVectorPtr->block(b1)).linearCombo(
1158  coeff0, blockTmpXn0APtr->block(b1),
1159  coeff1, blockTmpXn0APtr->block(b2),
1160  coeff2, blockTmpXn0BPtr->block(b1) );
1161  (blockTmpSolVectorPtr->block(b1)).update(
1162  coeff3, blockTmpXn0BPtr->block(b2), 1.0 );
1163 
1164  // erkeite 2/24/07. This is needed because currently the interpolation goes back to t=-1.0.
1165  if (t >= 0.0)
1166  {
1167  outputManagerAdapter.tranOutput(t, blockTmpSolVectorPtr->block(b1),
1171  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1172  Xyce::dout() << "Interpolated to (t,phi(t)) = (" << t << "," << s << ")" << std::endl;
1173  }
1174  }
1175  }
1176 
1177  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1178  Xyce::dout() << Xyce::section_divider << std::endl;
1179 
1180  return true;
1181 }
1182 
1183 //-----------------------------------------------------------------------------
1184 // Function : OneStep::printOutputSolution()
1185 // Purpose : Print output that is dumbed down in order.
1186 // Special Notes : This routine picks smaller time steps to approximate first
1187 // : order integration from the perspective of the output.
1188 // Scope : public
1189 // Creator : Ting Mei, SNL
1190 // Creation Date : 11/16/07
1191 //-----------------------------------------------------------------------------
1193  Analysis::OutputMgrAdapter & outputManagerAdapter,
1194  const TIAParams & tia_params,
1195  const double time,
1196  Linear::Vector * solnVecPtr,
1197  const bool doNotInterpolate,
1198  const std::vector<double> &outputInterpolationTimes,
1199  bool skipPrintLineOutput)
1200 {
1201  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1202  {
1203  Xyce::dout() << std::endl;
1204  Xyce::dout() << Xyce::section_divider << std::endl;
1205  Xyce::dout() <<
1206  " OneStep::printOutputSolution" << std::endl;
1207  Xyce::dout() << "usedOrder_ = " << sec.usedOrder_ << std::endl;
1208  }
1209 
1210  double timestep = sec.lastAttemptedTimeStep;
1211  double lasttime = sec.currentTime - timestep;
1212  bool dointerp = true;
1213  double hh = timestep/(sec.usedOrder_);
1214 
1215  if (hh <= 10*sec.minTimeStep)
1216  {
1217  dointerp = false;
1218  }
1219 
1220  if (!tia_params.interpOutputFlag)
1221  {
1222  dointerp = false;
1223  }
1224 
1225  if (doNotInterpolate)
1226  {
1227  dointerp = false;
1228  }
1229 
1230  if (dointerp && !outputInterpolationTimes.empty())
1231  {
1232  for (unsigned int i=0;i<outputInterpolationTimes.size();++i)
1233  {
1234  interpolateSolution(outputInterpolationTimes[i], ds.tmpSolVectorPtr, ds.xHistory); // interpolate solution
1235  interpolateSolution(outputInterpolationTimes[i], ds.tmpStaVectorPtr, ds.sHistory); // interpolate state
1236  interpolateSolution(outputInterpolationTimes[i], ds.tmpStoVectorPtr, ds.stoHistory);// interpolate store
1237 
1238  interpolateSolution(outputInterpolationTimes[i], ds.tmpLeadCurrentVectorPtr, ds.leadCurrentHistory);// interpolate lead current
1239  interpolateSolution(outputInterpolationTimes[i], ds.tmpLeadDeltaVPtr, ds.leadDeltaVHistory);// interpolate junction voltage
1240  interpolateSolution(outputInterpolationTimes[i], ds.tmpLeadCurrentQDerivVectorPtr, ds.leadCurrentQDerivHistory);// interpolate lead current q comp.
1241 
1242  outputManagerAdapter.tranOutput(outputInterpolationTimes[i], *ds.tmpSolVectorPtr,
1246  }
1247  }
1248 
1249  // Either way, do an output on the actual computed time step, but only
1250  // if we weren't given a list of specific times *or* we were told not to
1251  // interpoloate.
1252  if (outputInterpolationTimes.empty() || doNotInterpolate)
1253  {
1254  outputManagerAdapter.tranOutput(time, *ds.currSolutionPtr,
1258  skipPrintLineOutput);
1259  }
1260 
1261  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1262  Xyce::dout() << Xyce::section_divider << std::endl;
1263 
1264  return true;
1265 }
1266 
1267 //-----------------------------------------------------------------------------
1268 // Function : OneStep::saveOutputSolution
1269 // Purpose : This is similar to printOutputSolution, but is in support of
1270 // the .SAVE capability, rather than .PRINT.
1271 // Special Notes :
1272 // Scope : public
1273 // Creator : Eric Keiter, SNL
1274 // Creation Date : 10/21/07
1275 //-----------------------------------------------------------------------------
1277  Parallel::Machine comm,
1278  IO::InitialConditionsManager & initial_conditions_manager,
1279  const NodeNameMap & node_name_map,
1280  const TIAParams & tia_params,
1281  Linear::Vector * solnVecPtr,
1282  const double saveTime,
1283  const bool doNotInterpolate)
1284 {
1285  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1286  {
1287  Xyce::dout() << std::endl;
1288  Xyce::dout() << Xyce::section_divider << std::endl;
1289  Xyce::dout() << " OneStep::saveOutputSolution" << std::endl;
1290  }
1291 
1292  double timestep = sec.lastAttemptedTimeStep;
1293  double lasttime = sec.currentTime - timestep;
1294  bool dointerp = true;
1295  double hh = timestep/(sec.usedOrder_);
1296 
1297  // outputManagerAdapter.outputDCOP( *(ds.currSolutionPtr) );
1298  initial_conditions_manager.outputDCOP(comm, node_name_map, *ds.currSolutionPtr);
1299 
1300  if (DEBUG_TIME && isActive(Diag::TIME_OUTPUT))
1301  Xyce::dout() << Xyce::section_divider << std::endl;
1302 
1303  return true;
1304 }
1305 
1306 //-----------------------------------------------------------------------------
1307 // Function : OneStep::updateHistory
1308 // Purpose : Update history array after a successful step
1309 // Special Notes :
1310 // Scope : public
1311 // Creator : Ting Mei, SNL
1312 // Creation Date : 11/16/07
1313 //-----------------------------------------------------------------------------
1315 {
1316  if (DEBUG_TIME && isActive(Diag::TIME_HISTORY))
1317  {
1318  Xyce::dout() << std::endl;
1319  Xyce::dout() << Xyce::section_divider << std::endl;
1320  Xyce::dout() <<
1321  " OneStep::updateHistory" << std::endl;
1322  Xyce::dout() << "\n Before updates \n" << std::endl;
1323  for (int i=0; i<=sec.maxOrder_ ; ++i)
1324  {
1325  Xyce::dout() << "\n xHistory["<< i << "]: \n" << std::endl;
1326  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1327  Xyce::dout() << std::endl;
1328  }
1329  for (int i=0; i<=sec.maxOrder_ ; ++i)
1330  {
1331  Xyce::dout() << "\n qHistory["<< i << "]: \n" << std::endl;
1332  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1333  Xyce::dout() << std::endl;
1334  }
1335  for (int i=0; i<=sec.maxOrder_ ; ++i)
1336  {
1337  Xyce::dout() << "\n sHistory["<< i << "]: \n" << std::endl;
1338  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1339  Xyce::dout() << std::endl;
1340  }
1341  Xyce::dout() << Xyce::section_divider << std::endl;
1342  }
1343 
1344  if (sec.currentOrder_ == 2)
1345  {
1346  *(ds.xHistory[2]) = *(ds.xHistory[1]);
1347  (ds.qHistory[2])->linearCombo(1.0, *(ds.daeFVectorPtr), -1.0, *(ds.daeBVectorPtr));
1348  *(ds.stoHistory[2]) = *(ds.stoHistory[1]);
1352  *(ds.leadDeltaVHistory[2]) = *(ds.leadDeltaVHistory[1]);
1353  }
1354 
1355  (ds.xHistory[1])->linearCombo(1.0, *ds.nextSolutionPtr, -1.0,*(ds.xHistory[0]));
1356  (ds.qHistory[1])->linearCombo(1.0, *ds.daeQVectorPtr, -1.0,*(ds.qHistory[0]));
1357 
1358  (ds.stoHistory[1])->linearCombo(1.0, *ds.nextStorePtr, -1.0,*(ds.stoHistory[0]));
1359  (ds.stoLeadCurrQHistory[1])->linearCombo(1.0, *ds.nextStoreLeadCurrQPtr, -1.0,*(ds.stoLeadCurrQHistory[0]));
1360 
1361  (ds.leadCurrentHistory[1])->linearCombo(1.0, *ds.nextLeadCurrentPtr, -1.0,*(ds.leadCurrentHistory[0]));
1362  (ds.leadCurrentQHistory[1])->linearCombo(1.0, *ds.nextLeadCurrentQPtr, -1.0,*(ds.leadCurrentQHistory[0]));
1363  (ds.leadDeltaVHistory[1])->linearCombo(1.0, *ds.nextLeadDeltaVPtr, -1.0,*(ds.leadDeltaVHistory[0]));
1364 
1365  *(ds.xHistory[0]) = *ds.nextSolutionPtr;
1366  *(ds.qHistory[0]) = *ds.daeQVectorPtr;
1367  *(ds.sHistory[0]) = *ds.nextStatePtr;
1368  *(ds.stoHistory[0]) = *ds.nextStorePtr;
1373 
1374  if (DEBUG_TIME && isActive(Diag::TIME_HISTORY))
1375  {
1376  Xyce::dout() << "\n After updates \n" << std::endl;
1377  Xyce::dout() << "\n newtonCorrectionPtr: " << std::endl;
1378  ds.newtonCorrectionPtr->printPetraObject(Xyce::dout());
1379  Xyce::dout() << "\n qnewtonCorrectionPtr: " << std::endl;
1380  ds.qNewtonCorrectionPtr->printPetraObject(Xyce::dout());
1381  for (int i=0; i<=sec.maxOrder_ ; ++i)
1382  {
1383  Xyce::dout() << "\n xHistory["<< i << "]: \n" << std::endl;
1384  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1385  Xyce::dout() << std::endl;
1386  }
1387  for (int i=0; i<=sec.maxOrder_ ; ++i)
1388  {
1389  Xyce::dout() << "\n qHistory["<< i << "]: \n" << std::endl;
1390  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1391  Xyce::dout() << std::endl;
1392  }
1393  Xyce::dout() << "\n sNewtonCorrectionPtr: " << std::endl;
1394  ds.sNewtonCorrectionPtr->printPetraObject(Xyce::dout());
1395  Xyce::dout() << std::endl;
1396  Xyce::dout() << "\n nextStatePtr: " << std::endl;
1397  ds.nextStatePtr->printPetraObject(Xyce::dout());
1398  Xyce::dout() << std::endl;
1399  for (int i=0; i<=sec.maxOrder_ ; ++i)
1400  {
1401  Xyce::dout() << "\n sHistory["<< i << "]: \n" << std::endl;
1402  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1403  Xyce::dout() << std::endl;
1404  }
1405  Xyce::dout() << Xyce::section_divider << std::endl;
1406  }
1407 
1409 }
1410 
1411 //-----------------------------------------------------------------------------
1412 // Function : OneStep::updateSensitivityHistory
1413 // Purpose : Update sensitivity history array after a successful step
1414 // Special Notes :
1415 // Scope : public
1416 // Creator : Eric Keiter, SNL
1417 // Creation Date :
1418 //-----------------------------------------------------------------------------
1420 {
1421  int numParams = ds.sensRHSPtrVector.size();
1422  for (int ip=0; ip<numParams;++ip)
1423  {
1424  std::vector<Linear::Vector*> & dqdpHistory = ds.dqdpHistory[ip];
1425  std::vector<Linear::Vector*> & dXdpHistory = ds.dXdpHistory[ip];
1426 
1427  Linear::Vector & nextDXdpVec = *(ds.nextDXdpPtrVector[ip]);
1428  Linear::Vector & nextDfdpVec = *(ds.nextDfdpPtrVector[ip]);
1429  Linear::Vector & nextDqdpVec = *(ds.nextDqdpPtrVector[ip]);
1430  Linear::Vector & nextDbdpVec = *(ds.nextDbdpPtrVector[ip]);
1431 
1432  if (sec.currentOrder_ == 2)
1433  {
1434  *(dXdpHistory[2]) = *(dXdpHistory[1]);
1435  (dqdpHistory[2])->linearCombo(1.0, nextDfdpVec, -1.0, nextDbdpVec);
1436  }
1437 
1438  (dXdpHistory[1])->linearCombo(1.0, nextDXdpVec, -1.0,*(dXdpHistory[0]));
1439  (dqdpHistory[1])->linearCombo(1.0, nextDqdpVec, -1.0,*(dqdpHistory[0]));
1440 
1441  *(dXdpHistory[0]) = nextDXdpVec;
1442  *(dqdpHistory[0]) = nextDqdpVec;
1443 
1444 #ifdef DEBUG_SENS
1445  Xyce::dout() << "dxdp history ip = " << ip << ":\n";
1446  for (int i=0; i<=sec.maxOrder_ ; ++i)
1447  {
1448  dXdpHistory[i]->printPetraObject(Xyce::dout());
1449  }
1450 #endif
1451  }
1452 }
1453 
1454 //-----------------------------------------------------------------------------
1455 // Function : OneStep::restoreHistory
1456 // Purpose : Restore history array after a failed step
1457 // Special Notes :
1458 // Scope : public
1459 // Creator : Ting Mei, SNL
1460 // Creation Date : 10/21/07
1461 //-----------------------------------------------------------------------------
1463 {
1464  for (int i=1;i<=sec.currentOrder_;++i)
1465  {
1466  sec.psi_[i-1] = sec.psi_[i];
1467  }
1468  if (DEBUG_TIME && isActive(Diag::TIME_HISTORY))
1469  {
1470  Xyce::dout() << std::endl;
1471  Xyce::dout() << Xyce::section_divider << std::endl;
1472  Xyce::dout() <<
1473  " OneStep::restoreHistory" << std::endl;
1474  for (int i=1;i<=sec.currentOrder_;++i)
1475  Xyce::dout() << "\n sec.psi_[i] = " << sec.psi_[i] << std::endl;
1476  for (int i=0; i<=sec.maxOrder_ ; ++i)
1477  {
1478  Xyce::dout() << "\n xHistory["<< i << "]: \n" << std::endl;
1479  (ds.xHistory[i])->printPetraObject(Xyce::dout());
1480  Xyce::dout() << std::endl;
1481  }
1482  for (int i=0; i<=sec.maxOrder_ ; ++i)
1483  {
1484  Xyce::dout() << "\n qHistory["<< i << "]: \n" << std::endl;
1485  (ds.qHistory[i])->printPetraObject(Xyce::dout());
1486  Xyce::dout() << std::endl;
1487  }
1488  for (int i=0; i<=sec.maxOrder_ ; ++i)
1489  {
1490  Xyce::dout() << "\n sHistory["<< i << "]: \n" << std::endl;
1491  (ds.sHistory[i])->printPetraObject(Xyce::dout());
1492  Xyce::dout() << std::endl;
1493  }
1494  Xyce::dout() << Xyce::section_divider << std::endl;
1495  }
1496 }
1497 
1498 //-----------------------------------------------------------------------------
1499 // Function : OneStep::updateCoeffs
1500 // Purpose : Update method coefficients
1501 // Special Notes :
1502 // Scope : public
1503 // Creator : Ting Mei, SNL
1504 // Creation Date : 10/21/07
1505 //-----------------------------------------------------------------------------
1507 {
1508  // synchronize with Step Error Control
1509  // sec.psi_[0] = sec.currentTimeStep;
1510  if (DEBUG_TIME && isActive(Diag::TIME_COEFFICIENTS))
1511  {
1512  Xyce::dout() << std::endl;
1513  Xyce::dout() << Xyce::section_divider << std::endl;
1514  Xyce::dout() << " OneStep::updateCoeffs" << std::endl;
1515  Xyce::dout() << " currentTimeStep = " << sec.currentTimeStep << std::endl;
1516  Xyce::dout() << " numberOfSteps_ = " << sec.numberOfSteps_ << std::endl;
1517  Xyce::dout() << " currentOrder_ = " << sec.currentOrder_ << std::endl;
1518  Xyce::dout() << " nscsco_ = " << sec.nscsco_ << std::endl;
1519  Xyce::dout() << " psi_[0] = " << sec.psi_[0] << std::endl;
1520  }
1521 
1522  double temp1 = sec.currentTimeStep;
1523 
1524  if (sec.currentOrder_ == 2)
1525  {
1526  sec.psi_[2] = sec.psi_[1];
1527  }
1528  sec.psi_[1] = sec.psi_[0];
1529  sec.psi_[0] = temp1;
1530 
1531  sec.beta_[0] = 1.0;
1532  sec.alpha_[0] = 1.0;
1533  // sec.ck_ = 1.0;
1534  sec.alphas_ = -1.0;
1535 
1536  if (sec.currentOrder_ == 2)
1537  {
1538  double temp2 = sec.psi_[1];
1539  sec.beta_[1] = temp1/temp2 + (temp1/temp2)*(temp1/temp2)/2;
1540  sec.beta_[2] = -1.0*temp1*temp1/temp2/sec.psi_[2]/2;
1542  }
1543  else
1544  {
1545  sec.beta_[1] = temp1/sec.psi_[1];
1547  }
1548 
1549  if (DEBUG_TIME && isActive(Diag::TIME_COEFFICIENTS))
1550  {
1551  Xyce::dout() << " nscsco_ = " << sec.nscsco_ << std::endl;
1552  Xyce::dout() << " beta_[0] = " << sec.beta_[0] << std::endl;
1553  Xyce::dout() << " beta_[1] = " << sec.beta_[1] << std::endl;
1554  Xyce::dout() << " beta_[2] = " << sec.beta_[2] << std::endl;
1555  Xyce::dout() << " beta_[3] = " << sec.beta_[3] << std::endl;
1556  Xyce::dout() << " beta_[4] = " << sec.beta_[4] << std::endl;
1557  Xyce::dout() << " alpha_[0] = " << sec.alpha_[0] << std::endl;
1558  Xyce::dout() << " alpha_[1] = " << sec.alpha_[1] << std::endl;
1559  Xyce::dout() << " alpha_[2] = " << sec.alpha_[2] << std::endl;
1560  Xyce::dout() << " alpha_[3] = " << sec.alpha_[3] << std::endl;
1561  Xyce::dout() << " alpha_[4] = " << sec.alpha_[4] << std::endl;
1562  Xyce::dout() << " alphas_ = " << sec.alphas_ << std::endl;
1563  Xyce::dout() << " alpha0_ = " << sec.alpha0_ << std::endl;
1564  Xyce::dout() << " gamma_[0] = " << sec.gamma_[0] << std::endl;
1565  Xyce::dout() << " gamma_[1] = " << sec.gamma_[1] << std::endl;
1566  Xyce::dout() << " gamma_[2] = " << sec.gamma_[2] << std::endl;
1567  Xyce::dout() << " gamma_[3] = " << sec.gamma_[3] << std::endl;
1568  Xyce::dout() << " gamma_[4] = " << sec.gamma_[4] << std::endl;
1569  Xyce::dout() << " psi_[0] = " << sec.psi_[0] << std::endl;
1570  Xyce::dout() << " psi_[1] = " << sec.psi_[1] << std::endl;
1571  Xyce::dout() << " psi_[2] = " << sec.psi_[2] << std::endl;
1572  Xyce::dout() << " psi_[3] = " << sec.psi_[3] << std::endl;
1573  Xyce::dout() << " psi_[4] = " << sec.psi_[4] << std::endl;
1574  Xyce::dout() << " sigma_[0] = " << sec.sigma_[0] << std::endl;
1575  Xyce::dout() << " sigma_[1] = " << sec.sigma_[1] << std::endl;
1576  Xyce::dout() << " sigma_[2] = " << sec.sigma_[2] << std::endl;
1577  Xyce::dout() << " sigma_[3] = " << sec.sigma_[3] << std::endl;
1578  Xyce::dout() << " sigma_[4] = " << sec.sigma_[4] << std::endl;
1579  Xyce::dout() << " ck_ = " << sec.ck_ << std::endl;
1580  Xyce::dout() << Xyce::section_divider << std::endl;
1581  }
1582 }
1583 
1584 //-----------------------------------------------------------------------------
1585 // Function : OneStep::initialize
1586 // Purpose : Initialize method with initial solution & step-size
1587 // Special Notes :
1588 // Scope : public
1589 // Creator : Ting Mei, SNL
1590 // Creation Date : 10/21/07
1591 //-----------------------------------------------------------------------------
1592 void OneStep::initialize(const TIAParams &tia_params)
1593 {
1594  // we assume the solution vector is available here
1595  // Note that I'm using currSolutionPtr instead of
1596  // nextSolutionPtr because this is the first step.
1597 
1598  // Update next stop time from StepErrorControl:
1599  // ERK. Commenting this out, as it is already called from Analysis::AnalysisManager,
1600  // right before this initialize call. It should not be called 2x, as
1601  // it is history dependent (unfortunately), so calling it 2x in a row changes
1602  // the stop time to a different number.
1603  // sec.updateStopTime();
1604 
1605  // Choose initial step-size
1606  double time_to_stop = sec.stopTime - sec.currentTime;
1607  double currentTimeStep;
1608 
1609  sec.TimeStepLimitedbyBP = false;
1610 
1611  if (tia_params.constantTimeStepFlag)
1612  {
1613  currentTimeStep = 0.1 * time_to_stop;
1614  currentTimeStep = std::min(sec.startingTimeStep, currentTimeStep);
1615  sec.currentTimeStep = currentTimeStep;
1616  }
1617  else
1618  {
1619  // compute an initial step-size based on rate of change in the
1620  // solution initially
1621  double dnorm_q = ds.delta_x_errorNorm_q1();
1622  if (dnorm_q > 0.0) // time-dependent DAE
1623  {
1624  if (sec.currentTime == sec.initialTime)
1625  currentTimeStep = std::min(sec.h0_max_factor_*abs(time_to_stop),sqrt(2.0)/(sec.h0_safety_*dnorm_q));
1626  else
1627  currentTimeStep = 0.1* std::min(sec.savedTimeStep, abs(time_to_stop));
1628  }
1629  else // non-time-dependent DAE
1630  {
1631  if (sec.currentTime == sec.initialTime)
1632  currentTimeStep = sec.h0_max_factor_*abs(time_to_stop);
1633  else
1634  currentTimeStep = 0.1* std::min(sec.savedTimeStep, abs(time_to_stop));
1635  }
1636  // choose min of user specified value and our value:
1637  if (sec.startingTimeStep > 0.0 && (sec.currentTime == sec.initialTime))
1638  currentTimeStep = std::min(sec.startingTimeStep, currentTimeStep);
1639  // check for maximum step-size:
1640  double rh = abs(currentTimeStep)*sec.h_max_inv_;
1641  if (rh>1.0) currentTimeStep = currentTimeStep/rh;
1642 
1643 
1644  // Apply this new stepsize only if it is smaller than the one preceding
1645  // the breakpoint, but only do this if this is a non-DCOP breakpoint.
1646  if (sec.currentTime != sec.initialTime) // if not DCOP:
1647  {
1648  sec.currentTimeStep = std::min(sec.currentTimeStep, currentTimeStep);
1649  }
1650  else // else if DCOP:
1651  {
1652  sec.currentTimeStep = currentTimeStep;
1653  }
1654  }
1655 
1656  sec.currentTimeStepRatio = 1.0;
1658 
1662 
1664  sec.stepAttemptStatus = true;
1665 
1666  if (VERBOSE_TIME && tia_params.errorAnalysisOption == TimeIntg::NO_LOCAL_TRUNCATED_ESTIMATES)
1667  {
1668  Xyce::dout() << "ERROROPTION=1: DeltaT Grow = 2" << "\n" << std::endl
1669  << "ERROROPTION=1: DeltaT Cut = 0.125" << "\n" << std::endl
1670  << "ERROROPTION=1: NL MIN = " << tia_params.NLmin << "\n" << std::endl
1671  << "ERROROPTION=1: NL MAX = " << tia_params.NLmax << "\n" << std::endl
1672  << "ERROROPTION=1: DELMAX = " << sec.maxTimeStep << "\n" << std::endl;
1673  }
1674 
1675  // sec.tolAimFac_ = 0.5;
1676 
1678 
1679  // x history
1680  *(ds.xHistory[0]) = *(ds.currSolutionPtr);
1681  (ds.xHistory[1])->putScalar(0.0); // no need to multiply by dt here
1682 
1683  // q history
1684  *(ds.qHistory[0]) = *(ds.daeQVectorPtr);
1685  (ds.qHistory[1])->linearCombo(1.0, *(ds.daeFVectorPtr), -1.0, *(ds.daeBVectorPtr));
1686  (ds.qHistory[1])->scale(-sec.currentTimeStep);
1687 
1688  // state history
1689  *(ds.sHistory[0]) = *(ds.currStatePtr);
1690  (ds.sHistory[1])->putScalar(0.0);
1691 
1692  // store history
1693  *(ds.stoHistory[0]) = *(ds.currStorePtr);
1694  (ds.stoHistory[1])->putScalar(0.0);
1695 
1696  // lead current Q component history
1698  (ds.stoLeadCurrQHistory[1])->putScalar(0.0);
1699 
1700  // new lead current Q component history
1702  (ds.leadCurrentHistory[1])->putScalar(0.0);
1703 
1705  (ds.leadCurrentQHistory[1])->putScalar(0.0);
1706 
1708  (ds.leadDeltaVHistory[1])->putScalar(0.0);
1709 
1710  // Coefficient initialization
1711  sec.numberOfSteps_ = 0; // number of total time integration steps taken
1712  sec.currentOrder_ = 1;
1713  sec.usedOrder_ = 1;
1714  sec.psi_[0] = sec.currentTimeStep;
1715  sec.cj_ = 1/sec.psi_[0];
1716  sec.nscsco_ = 0;
1717  if (DEBUG_TIME && isActive(Diag::TIME_HISTORY))
1718  {
1719  Xyce::dout() << std::endl;
1720  Xyce::dout() << Xyce::section_divider << std::endl;
1721  Xyce::dout() <<
1722  " OneStep::initialize" << std::endl;
1723  Xyce::dout() << "\n xHistory: \n" << std::endl;
1724  (ds.xHistory[0])->printPetraObject(Xyce::dout());
1725  Xyce::dout() << std::endl;
1726  (ds.xHistory[1])->printPetraObject(Xyce::dout());
1727  Xyce::dout() << std::endl;
1728  Xyce::dout() << "\n qHistory: \n" << std::endl;
1729  (ds.qHistory[0])->printPetraObject(Xyce::dout());
1730  Xyce::dout() << std::endl;
1731  (ds.qHistory[1])->printPetraObject(Xyce::dout());
1732  Xyce::dout() << std::endl;
1733  Xyce::dout() << "\n sHistory: \n" << std::endl;
1734  (ds.sHistory[0])->printPetraObject(Xyce::dout());
1735  Xyce::dout() << std::endl;
1736  (ds.sHistory[1])->printPetraObject(Xyce::dout());
1737  Xyce::dout() << std::endl;
1738  Xyce::dout() << "\n" << "currentTimeStep = " << currentTimeStep << "\n" << std::endl;
1739  Xyce::dout() << "\n" << "time_to_stop = " << time_to_stop << "\n" << std::endl;
1740  Xyce::dout() << Xyce::section_divider << std::endl;
1741  }
1742 
1744 }
1745 
1746 //-----------------------------------------------------------------------------
1747 // Function : OneStep::initializeSensitivities
1748 // Purpose :
1749 // Special Notes :
1750 // Scope : public
1751 // Creator : Eric Keiter, SNL
1752 // Creation Date :
1753 //-----------------------------------------------------------------------------
1755 {
1756  int numParams = ds.sensRHSPtrVector.size();
1757  for (int ip=0; ip<numParams;++ip)
1758  {
1759  std::vector<Linear::Vector*> & dqdpHistory = ds.dqdpHistory[ip];
1760  std::vector<Linear::Vector*> & dXdpHistory = ds.dXdpHistory[ip];
1761 
1762  Linear::Vector * currDxdpPtr = ds.currDXdpPtrVector[ip];
1763  Linear::Vector * currDqdpPtr = ds.currDqdpPtrVector[ip];
1764 
1765  // dXdp history
1766  *(dXdpHistory[0]) = *(currDxdpPtr);
1767  *(dXdpHistory[1]) = *(currDxdpPtr);
1768 
1769  // dqdp history
1770  *(dqdpHistory[0]) = *(currDqdpPtr);
1771  *(dqdpHistory[1]) = *(currDqdpPtr);
1772  }
1773 }
1774 
1775 //-----------------------------------------------------------------------------
1776 // Function : OneStep::setTwoLevelTimeInfo
1777 // Purpose :
1778 // Special Notes :
1779 // Scope : public
1780 // Creator : Eric Keiter, SNL
1781 // Creation Date : 03/01/07
1782 //-----------------------------------------------------------------------------
1783 void
1785 {
1786  // set initial step-size
1787  double time_to_stop = sec.stopTime - sec.currentTime;
1788 
1789  // x history
1790  *ds.xHistory[0] = *ds.currSolutionPtr;
1791  ds.xHistory[1]->putScalar(0.0); // no need to multiply by dt here
1792 
1793  // q history
1794  *ds.qHistory[0] = *ds.daeQVectorPtr;
1795  ds.qHistory[1]->linearCombo(1.0, *ds.daeFVectorPtr, -1.0, *ds.daeBVectorPtr);
1796  ds.qHistory[1]->scale(-sec.currentTimeStep);
1797 
1798  // state history
1799  *ds.sHistory[0] = *ds.nextStatePtr;
1800  ds.sHistory[1]->putScalar(0.0);
1801 
1802  // Coefficient initialization
1803  sec.numberOfSteps_ = 0; // number of total time integration steps taken
1804  sec.usedOrder_ = 1;
1805  sec.psi_[0] = sec.currentTimeStep;
1806  sec.cj_ = 1/sec.psi_[0];
1807  sec.nscsco_ = 0;
1808 }
1809 
1810 //-----------------------------------------------------------------------------
1811 // Function : OneStep::checkReduceOrder()
1812 // Purpose : check whether to reduce order independent of local error test
1813 // Special Notes :
1814 // Scope : public
1815 // Creator : Ting Mei, SNL
1816 // Creation Date : 10/21/07
1817 //-----------------------------------------------------------------------------
1819 {
1820 
1821 }
1822 
1823 //-----------------------------------------------------------------------------
1824 // Function : OneStep::rejectStep()
1825 // Purpose : code to restore history, choose new order/step-size
1826 // Special Notes :
1827 // Scope : public
1828 // Creator : Ting Mei, SNL
1829 // Creation Date : 10/21/07
1830 //-----------------------------------------------------------------------------
1831 void
1833  const TIAParams & tia_params)
1834 {
1835  // This routine puts its output newTimeStep_
1836  sec.TimeStepLimitedbyBP = false;
1837 
1838  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
1839  {
1840  Xyce::dout() << std::endl;
1841  Xyce::dout() << Xyce::section_divider << std::endl;
1842  Xyce::dout() << " OneStep::rejectStep" << std::endl;
1843  }
1844 
1845  // Only update the time step if we are NOT running constant stepsize.
1846  bool adjustStep = !tia_params.constantTimeStepFlag;
1847 
1849 
1850  double newTimeStep_ = sec.currentTimeStep;
1851  double rr = 1.0; // step size ratio = new step / old step
1852  if ((sec.stepAttemptStatus == false) && (adjustStep))
1853  {
1855  {
1856  newTimeStep_ = sec.currentTimeStep/8;
1857  }
1858  else
1859  {
1860  sec.initialPhase_ = false;
1861  sec.nef_++;
1862  restoreHistory();
1863  if (sec.nef_ >= sec.max_LET_fail_)
1864  {
1865  std::string msg = "OneStep::rejectStep: ";
1866  msg += " Maximum number of local error test failures. ";
1867  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, msg);
1868  }
1869 
1870  if ((sec.newtonConvergenceStatus <= 0))
1871  {
1872  /// 11/11/05 erkeite: If the Newton solver fails, don't
1873  // rely on the error estimate - it may be full of Nan's.
1874  // rr = sec.r_min_;
1875 
1876  newTimeStep_ = sec.currentTimeStep/8;
1878  }
1879  else
1880  {
1881  // 03/11/04 tscoffe: Here is the block for choosing order &
1882  // step-size when the local error test FAILS (but Newton
1883  // succeeded).
1884  if (sec.nef_== 1)
1885  {
1886 
1887  // sec.estOverTol_
1888  sec.Est_ = sec.estOverTol_;
1889 
1891  rr = sec.tolAimFac_/(sec.estOverTol_ + 0.0001);
1892  rr = pow(rr, 1.0/(sec.currentOrder_+1.0));
1893  rr = std::max(sec.r_min_,std::min(sec.r_max_,rr));
1894 
1895  newTimeStep_ = rr * sec.currentTimeStep;
1896  }
1897  else
1898  {
1899  rr = sec.r_min_;
1900  newTimeStep_ = rr * sec.currentTimeStep;
1901 
1903  }
1904  }
1905 
1906  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
1907  {
1908  Xyce::dout() << " currentTimeStep = " << sec.currentTimeStep << std::endl;
1909  Xyce::dout() << " numberOfSteps_ = " << sec.numberOfSteps_ << std::endl;
1910  Xyce::dout() << " currentOrder_ = " << sec.currentOrder_ << std::endl;
1911  Xyce::dout() << " nscsco_ = " << sec.nscsco_ << std::endl;
1912  Xyce::dout() << " alpha_[0] = " << sec.alpha_[0] << std::endl;
1913  Xyce::dout() << " alpha_[1] = " << sec.alpha_[1] << std::endl;
1914  Xyce::dout() << " alpha_[2] = " << sec.alpha_[2] << std::endl;
1915  Xyce::dout() << " alpha_[3] = " << sec.alpha_[3] << std::endl;
1916  Xyce::dout() << " alpha_[4] = " << sec.alpha_[4] << std::endl;
1917  Xyce::dout() << " psi_[0] = " << sec.psi_[0] << std::endl;
1918  Xyce::dout() << " psi_[1] = " << sec.psi_[1] << std::endl;
1919  Xyce::dout() << " psi_[2] = " << sec.psi_[2] << std::endl;
1920  Xyce::dout() << " psi_[3] = " << sec.psi_[3] << std::endl;
1921  Xyce::dout() << " psi_[4] = " << sec.psi_[4] << std::endl;
1922  Xyce::dout() << " sigma_[0] = " << sec.sigma_[0] << std::endl;
1923  Xyce::dout() << " sigma_[1] = " << sec.sigma_[1] << std::endl;
1924  Xyce::dout() << " sigma_[2] = " << sec.sigma_[2] << std::endl;
1925  Xyce::dout() << " sigma_[3] = " << sec.sigma_[3] << std::endl;
1926  Xyce::dout() << " rr = " << rr << std::endl;
1927  Xyce::dout() << " Est_ = " << sec.Est_ << std::endl;
1928  Xyce::dout() << " nef_ = " << sec.nef_ << std::endl;
1929  Xyce::dout() << " newOrder_ = " << sec.newOrder_ << std::endl;
1930  Xyce::dout() << " currentTimeStep = " << sec.currentTimeStep << std::endl;
1931  Xyce::dout() << " newTimeStep_ = " << newTimeStep_ << std::endl;
1932  }
1933  }
1934  }
1935  else if ((sec.stepAttemptStatus == false) & (!adjustStep))
1936  {
1937  std::string tmp = " OneStep:rejectStep: Warning: Local error test failed with constant step-size.\n";
1938  Xyce::dout() << tmp << std::endl;
1939  }
1940 
1941  // If the step needs to be adjusted:
1942  if (adjustStep)
1943  {
1944  newTimeStep_ = std::max(newTimeStep_, sec.minTimeStep);
1945  newTimeStep_ = std::min(newTimeStep_, sec.maxTimeStep);
1946 
1947  double nextTimePt = sec.currentTime + newTimeStep_;
1948 
1949  if (nextTimePt > sec.stopTime)
1950  {
1951  nextTimePt = sec.stopTime;
1952  newTimeStep_ = sec.stopTime - sec.currentTime;
1953  sec.TimeStepLimitedbyBP = true;
1954  }
1955 
1956  sec.nextTime = nextTimePt;
1957 
1958  sec.currentTimeStepRatio = newTimeStep_/sec.lastTimeStep;
1959  sec.currentTimeStepSum = newTimeStep_ + sec.lastTimeStep;
1960 
1961  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
1962  {
1963  Xyce::dout() << " newTimeStep_ = " << newTimeStep_ << std::endl;
1964  Xyce::dout() << " nextTime = " << sec.nextTime << std::endl;
1965  }
1966 
1967  sec.currentTimeStep = newTimeStep_;
1968  }
1969  else // if time step is constant for this step:
1970  {
1971  double nextTimePt = sec.currentTime + sec.currentTimeStep;
1972 
1973  if (nextTimePt > sec.stopTime)
1974  {
1975  nextTimePt = sec.stopTime;
1977  }
1978 
1981 
1982  sec.nextTime = nextTimePt;
1983  }
1984  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
1985  {
1986  Xyce::dout() << Xyce::section_divider << std::endl;
1987  }
1988 }
1989 
1990 //-----------------------------------------------------------------------------
1991 // Function : OneStep::rejectStepForHabanero
1992 // Purpose : step rejection, but from an outside program (Habanero API)
1993 // Special Notes :
1994 // Scope : public
1995 // Creator : Eric Keiter, SNL
1996 // Creation Date : 08/11/09
1997 //-----------------------------------------------------------------------------
1999 {
2000  restoreHistory();
2002 }
2003 
2004 //-----------------------------------------------------------------------------
2005 // Function : OneStep::completeStep()
2006 // Purpose : code to update history, choose new order/step-size
2007 // Special Notes :
2008 // Scope : public
2009 // Creator : Ting Mei, SNL
2010 // Creation Date : 10/21/07
2011 //-----------------------------------------------------------------------------
2012 void OneStep::completeStep(const TIAParams &tia_params)
2013 {
2014  sec.TimeStepLimitedbyBP = false;
2015 
2016  sec.numberOfSteps_ ++;
2017  sec.nef_ = 0;
2020 
2021  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2022  {
2023  Xyce::dout() << std::endl;
2024  Xyce::dout() << Xyce::section_divider << std::endl;
2025 
2026  Xyce::dout() << " OneStep::completeStep" << std::endl;
2027  }
2028 
2029  // Only update the time step if we are NOT running constant stepsize.
2030  bool adjustStep = !tia_params.constantTimeStepFlag;
2031 
2033 
2034  double newTimeStep_ = sec.currentTimeStep;
2035  double rr = 1.0; // step size ratio = new step / old step
2036  // 03/11/04 tscoffe: Here is the block for choosing order & step-size when
2037  // the local error test PASSES (and Newton succeeded).
2038 
2039  // need the lastTimeStep for output interpolation. Save it before
2040  // overwriting it with currentTimeStep;
2041  // This history for this step is saved in updateHistory(), called below
2043 
2045  sec.lastTimeStepRatio = sec.currentTimeStepRatio; // copied from calcTStep1
2046  sec.lastTimeStepSum = sec.currentTimeStepSum; // copied from calcTStep1
2047  int orderDiff = sec.currentOrder_ - sec.usedOrder_;
2050 
2051  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2052  {
2053  Xyce::dout() << " initialPhase_ = " << sec.initialPhase_ << std::endl;
2054  Xyce::dout() << " rr = " << rr << std::endl;
2055  Xyce::dout() << " currentTimeStep = " << sec.currentTimeStep << std::endl;
2056  Xyce::dout() << " currentTime = " << sec.currentTime << std::endl;
2057  Xyce::dout() << " nextTime = " << sec.nextTime << std::endl;
2058  Xyce::dout() << " newTimeStep_ = " << newTimeStep_ << std::endl;
2059  Xyce::dout() << " minTimeStep = " << sec.minTimeStep << std::endl;
2060  Xyce::dout() << " maxTimeStep = " << sec.maxTimeStep << std::endl;
2061  }
2062 
2064  {
2065  if (sec.numberOfSteps_ >= 2 && sec.maxOrder_ == 2)
2066  {
2067  sec.currentOrder_ = 2;
2068  }
2069 
2070  rr = 1;
2071 
2072  if (sec.nIterations <= tia_params.NLmin)
2073  rr = 2;
2074 
2075  if (sec.nIterations > tia_params.NLmax)
2076  rr = 1.0/8;
2077 
2078  newTimeStep_ = rr*sec.currentTimeStep;
2079  }
2080  else
2081  {
2082  rr = sec.tolAimFac_/(sec.estOverTol_ + 0.0001);
2083  rr = pow(rr, 1.0/(sec.currentOrder_+1.0));
2084 
2085  if (sec.numberOfSteps_ >= 2 && sec.maxOrder_ == 2)
2086  {
2087  if (sec.currentOrder_ == 1)
2088  {
2089  sec.currentOrder_ = 2;
2090  rr = sec.tolAimFac_/(sec.estOverTol_ + 0.0001);
2091  rr = pow(rr, 1.0/(sec.currentOrder_+1.0));
2092 
2093  if (rr <= 1.05)
2094  {
2095 
2097  }
2098  }
2099  }
2100  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2101  {
2102  Xyce::dout() << " currentOrder_ = " << sec.currentOrder_ << std::endl;
2103  Xyce::dout() << " r_hincr_ = " << sec.r_hincr_ << std::endl;
2104  Xyce::dout() << " r_hincr_test_ = " << sec.r_hincr_test_ << std::endl;
2105  Xyce::dout() << " Est = " << sec.Est_ << std::endl;
2106  Xyce::dout() << " raw rr = " << rr << std::endl;
2107  }
2108 
2109  if (rr >= sec.r_hincr_test_)
2110  {
2111  rr = sec.r_hincr_;
2112  newTimeStep_ = rr*sec.currentTimeStep;
2113  }
2114  else if (rr <= 1)
2115  {
2116  rr = std::max(sec.r_min_,std::min(sec.r_max_,rr));
2117  newTimeStep_ = rr*sec.currentTimeStep;
2118  }
2119  }
2120 
2121  updateHistory();
2122 
2123  newTimeStep_ = std::max(newTimeStep_, sec.minTimeStep);
2124  newTimeStep_ = std::min(newTimeStep_, sec.maxTimeStep);
2125 
2126  // 12/01/05 tscoffe: This is necessary to avoid currentTimeStep == 0 right
2127  // before a breakpoint. So I'm checking to see if currentTime is identically
2128  // equal to stopTime, in which case we are right before a breakpoint and we
2129  // should not adjust currentStepSize because that would result in
2130  // currentStepSize == 0.
2132  {
2133  // If the step needs to be adjusted:
2134  if (adjustStep)
2135  {
2136  double nextTimePt = sec.currentTime + newTimeStep_;
2137  if (nextTimePt > sec.stopTime)
2138  {
2139 
2140  sec.savedTimeStep = newTimeStep_;
2141 
2142  nextTimePt = sec.stopTime;
2143 
2144  newTimeStep_ = sec.stopTime - sec.currentTime;
2145  sec.TimeStepLimitedbyBP = true;
2146  }
2147 
2148  sec.nextTime = nextTimePt;
2149 
2150  sec.currentTimeStepRatio = newTimeStep_/sec.lastTimeStep;
2151  sec.currentTimeStepSum = newTimeStep_ + sec.lastTimeStep;
2152 
2153  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2154  {
2155  Xyce::dout() << " nextTime = " << sec.nextTime << std::endl;
2156  Xyce::dout() << " newTimeStep_ = " << newTimeStep_ << std::endl;
2157  }
2158 
2159  sec.currentTimeStep = newTimeStep_;
2160  }
2161  else // if time step is constant for this step:
2162  {
2163  double nextTimePt = sec.currentTime + sec.currentTimeStep;
2164 
2165  if (nextTimePt > sec.stopTime)
2166  {
2168 
2169  nextTimePt = sec.stopTime;
2171  }
2172 
2175 
2176  sec.nextTime = nextTimePt;
2177  }
2178  }
2179 
2180  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2181  {
2182  Xyce::dout() << Xyce::section_divider << std::endl;
2183  }
2184 
2185 }
2186 
2187 //-----------------------------------------------------------------------------
2188 // Function : OneStep::updateStateDeriv
2189 // Purpose :
2190 // Special Notes :
2191 // Scope : public
2192 // Creator : Ting Mei, SNL
2193 // Creation Date : 11/17/05
2194 //-----------------------------------------------------------------------------
2196 {
2197  // dS/dt = spn0 - (sec.alpha_/hn)(S(x)-sn0)
2198  ds.nextStateDerivPtr->linearCombo(1.0,*ds.nextStatePtr,-1.0,*ds.sn0Ptr);
2199  // ds.nextStateDerivPtr->linearCombo(1.0,*ds.spn0Ptr,-sec.alphas_/sec.currentTimeStep,*ds.nextStateDerivPtr);
2200 
2201  if (sec.currentOrder_ == 1)
2202  {
2204  }
2205  else
2206  {
2208  }
2209 
2210  if (DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
2211  {
2212  Xyce::dout() << "\n next state Ptr: \n" << std::endl;
2213  ds.nextStatePtr->printPetraObject(Xyce::dout());
2214  Xyce::dout() << std::endl;
2215 
2216  Xyce::dout() << "\n sn0: \n" << std::endl;
2217  ds.sn0Ptr->printPetraObject(Xyce::dout());
2218  Xyce::dout() << std::endl;
2219 
2220  Xyce::dout() << "\n next State Deriv: \n" << std::endl;
2221  ds.nextStateDerivPtr->printPetraObject(Xyce::dout());
2222  Xyce::dout() << std::endl;
2223  }
2224 }
2225 
2226 //-----------------------------------------------------------------------------
2227 // Function : OneStep::updateLeadCurrent
2228 // Purpose : calculates lead currents in store vector with
2229 // the storeLeadCurrQVec.
2230 // Special Notes :
2231 // Scope : public
2232 // Creator : Richard Schiek, Electrical Systems Modeling, SNL
2233 // Creation Date : 03/22/2013
2234 //-----------------------------------------------------------------------------
2236 {
2238  if (sec.currentOrder_ == 1)
2239  {
2241  }
2242  else
2243  {
2245  linearCombo(-1.0,*(ds.currStoreLeadCurrQDerivPtr),
2247  }
2248  ds.nextStorePtr->linearCombo(1.0,*ds.nextStorePtr,1.0,*ds.nextStoreLeadCurrQDerivPtr);
2249 
2250  if (DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
2251  {
2252  Xyce::dout() << "\n next store Ptr: \n" << std::endl;
2253  ds.nextStorePtr->printPetraObject(Xyce::dout());
2254  Xyce::dout() << std::endl;
2255  }
2256 }
2257 
2258 //-----------------------------------------------------------------------------
2259 // Function : OneStep::updateLeadCurrentVec
2260 // Purpose : calculates lead currents in lead current vector with
2261 // the leadCurrentQVec.
2262 // Special Notes :
2263 // Scope : public
2264 // Creator : Richard Schiek, Electrical Systems Modeling, SNL
2265 // Creation Date : 01/22/2015
2266 //-----------------------------------------------------------------------------
2268 {
2270  if (sec.currentOrder_ == 1)
2271  {
2273  }
2274  else
2275  {
2277  linearCombo(-1.0,*(ds.currLeadCurrentQDerivPtr),
2279  }
2281 
2282  if (DEBUG_TIME && isActive(Diag::TIME_STEP))
2283  {
2284  Xyce::dout() << "\n next lead current Ptr: \n" << std::endl;
2285  ds.nextLeadCurrentPtr->printPetraObject(Xyce::dout());
2286  Xyce::dout() << std::endl;
2287 
2288  Xyce::dout() << "\n next lead current Q Ptr: \n" << std::endl;
2289  ds.nextLeadCurrentQPtr->printPetraObject(Xyce::dout());
2290  Xyce::dout() << std::endl;
2291 
2292  Xyce::dout() << "\n curr lead current Q Ptr: \n" << std::endl;
2293  ds.leadCurrentQn0Ptr->printPetraObject(Xyce::dout());
2294  Xyce::dout() << std::endl;
2295  }
2296 }
2297 
2298 //-----------------------------------------------------------------------------
2299 // Function : OneStep::getInitialQnorm
2300 // Purpose : Needed by 2-level solves.
2301 // Special Notes :
2302 // Scope : public
2303 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2304 // Creation Date : 03/18/07
2305 //-----------------------------------------------------------------------------
2307 {
2308  tle.q1HistorySum = ds.partialSum_q1();
2309 }
2310 
2311 //-----------------------------------------------------------------------------
2312 // Function : OneStep::setupTwoLevelError
2313 // Purpose : Needed by 2-level solves.
2314 // Special Notes :
2315 // Scope : public
2316 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2317 // Creation Date : 03/15/07
2318 //-----------------------------------------------------------------------------
2320 {
2321  tle.xErrorSum = ds.partialErrorNormSum ();
2326  tle.innerSize = ds.globalLength ();
2327 
2328  if (DEBUG_TIME && isActive(Diag::TIME_ERROR))
2329  Xyce::dout() << tle;
2330 }
2331 
2332 //-----------------------------------------------------------------------------
2333 // Function : OneStep::partialTimeDeriv
2334 // Purpose :
2335 // Special Notes :
2336 // Scope : public
2337 // Creator :
2338 // Creation Date : 1/20/07
2339 //-----------------------------------------------------------------------------
2341 {
2342  if (sec.currentTimeStep < 1e-30)
2343  {
2344  Xyce::Report::UserWarning() << "Excessively small current time step, incorrectly returning with large value";
2345 
2346  return leadingCoeff * 1.e+30;
2347  }
2348 
2349  return leadingCoeff / sec.currentTimeStep;
2350 }
2351 
2352 } // namespace TimeIntg
2353 } // namespace Xyce
Linear::Vector * sNewtonCorrectionPtr
Linear::Vector * nextLeadCurrentQPtr
Linear::Vector * leadCurrentQn0Ptr
std::vector< Linear::Vector * > currDQdxDXdpDerivPtrVector
bool interpolateSolution(double timepoint, Linear::Vector *tmpSolVectorPtr, std::vector< Linear::Vector * > &historyVec)
Linear::Vector * tmpLeadDeltaVPtr
std::vector< Linear::Vector * > nextDqdpPtrVector
Linear::Vector * currStateDerivPtr
bool printOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const TIAParams &tia_params, const double time, Linear::Vector *solnVecPtr, const bool doNotInterpolate, const std::vector< double > &outputInterpolationTimes, bool skipPrintLineOutput)
Pure virtual class to augment a linear system.
void initialize(const TIAParams &tia_params)
int nIterations
Number of newton iterations.
std::vector< double > dOdpVec_
std::vector< double > scaled_dOdpVec_
std::vector< Linear::Vector * > nextDXdpPtrVector
Linear::Vector * tmpStaVectorPtr
Linear::Vector * currStorePtr
std::vector< double > scaled_dOdpAdjVec_
std::vector< Linear::Vector * > leadDeltaVHistory
Linear::Vector * tmpSolVectorPtr
Linear::Vector * leadCurrentpn0Ptr
std::vector< Linear::Vector * > nextDbdpPtrVector
double partialSum_m2(int currentOrder)
int errorAnalysisOption
Error analysis option.
void rejectStep(const TIAParams &tia_params)
Linear::Vector * tmpStoVectorPtr
std::vector< Linear::Vector * > nextDfdpPtrVector
std::vector< Linear::Vector * > nextDQdxDXdpDerivPtrVector
std::vector< Linear::Vector * > qHistory
Linear::Vector * nextLeadDeltaVPtr
Linear::Vector * currStatePtr
std::vector< double > objectiveVec_
std::vector< Linear::Vector * > currDXdpPtrVector
std::vector< Linear::Vector * > leadCurrentHistory
bool constantTimeStepFlag
Constant time step integration flag.
bool printMPDEOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const double time, Linear::Vector *solnVecPtr, const std::vector< double > &fastTimes)
Linear::Vector * leadCurrentn0Ptr
Linear::Vector * daeQVectorPtr
Linear::Vector * tmpLeadCurrentVectorPtr
double partialSum_p1(int currentOrder, int maxOrder)
void completeStep(const TIAParams &tia_params)
DataStore & ds
Reference to the TIA data-store object.
Linear::Vector * stopn0Ptr
StepErrorControl & sec
Reference to step-error control object.
Linear::Vector * leadCurrentQpn0Ptr
Linear::Vector * daeFVectorPtr
Linear::Vector * qNewtonCorrectionPtr
Linear::Vector * currLeadCurrentQPtr
double leadingCoeff
Time-integration method leading coefficient value.
void getInitialQnorm(TwoLevelError &tle) const
Linear::Vector * nextStoreLeadCurrQDerivPtr
std::vector< Linear::Vector * > currDqdpDerivPtrVector
bool printWaMPDEOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const double time, Linear::Vector *solnVecPtr, const std::vector< double > &fastTimes, const int phiGID)
static TimeIntegrationMethod * factory(const TIAParams &tia_params, StepErrorControl &step_error_control, DataStore &data_store)
Definition: N_TIA_OneStep.C:91
std::vector< Linear::Vector * > leadCurrentQDerivHistory
Linear::Matrix * dFdxMatrixPtr
Linear::Matrix * JMatrixPtr
Linear::Vector * currLeadCurrentQDerivPtr
Linear::Vector * nextStatePtr
std::vector< Linear::Vector * > leadCurrentQHistory
std::vector< Linear::Vector * > nextDqdpDerivPtrVector
Linear::Vector * dFdxdVpVectorPtr
std::vector< std::vector< Linear::Vector * > > dqdpHistory
Linear::Vector * currLeadDeltaVPtr
Linear::Vector * currStoreLeadCurrQPtr
Linear::Vector * nextSolutionPtr
Linear::Vector * RHSVectorPtr
bool saveOutputSolution(Parallel::Machine comm, IO::InitialConditionsManager &initial_conditions_manager, const NodeNameMap &node_name_map, const TIAParams &tia_params, Linear::Vector *solnVecPtr, const double saveTime, const bool doNotInterpolate)
Linear::Vector * tmpXn0BPtr
Linear::Vector * nextStorePtr
Linear::Vector * stoQn0Ptr
Linear::Vector * dQdxdVpVectorPtr
bool interpolateMPDESolution(std::vector< double > &timepoint, Linear::Vector *tmpSolVectorPtr)
OneStep(const TIAParams &tiaP, StepErrorControl &secTmp, DataStore &dsTmp)
Linear::Vector * currLeadCurrentPtr
std::vector< double > dOdpAdjVec_
Linear::Vector * nextLeadCurrentQDerivPtr
Linear::Vector * newtonCorrectionPtr
void loadFinalSensitivityDerivatives()
Linear::Vector * tmpLeadCurrentQDerivVectorPtr
Linear::Vector * tmpXn0APtr
Linear::Vector * currSolutionPtr
std::vector< Linear::Vector * > stoHistory
double timept_
Keep track of last interpolation point in printMPDEOutputSolution.
Linear::Vector * stoQpn0Ptr
Linear::Vector * nextStoreLeadCurrQPtr
Linear::Vector * currStoreLeadCurrQDerivPtr
Linear::Vector * nextStateDerivPtr
std::vector< Linear::Vector * > xHistory
std::vector< Linear::Vector * > sensRHSPtrVector
Linear::Matrix * dQdxMatrixPtr
double partialTimeDeriv() const
void tranOutput(double time, Linear::Vector &currSolutionPtr, Linear::Vector &stateVecPtr, Linear::Vector &storeVecPtr, Linear::Vector &lead_current_vector, Linear::Vector &junction_voltage_vector, Linear::Vector &lead_current_dqdt_vector, std::vector< double > &objectiveVec_, std::vector< double > &dOdpVec_, std::vector< double > &dOdpAdjVec_, std::vector< double > &scaled_dOdpVec_, std::vector< double > &scaled_dOdpAdjVec_, bool skipPrintLineOutput=false)
std::vector< Linear::Vector * > currDQdxDXdpPtrVector
double partialSum_m1(int currentOrder)
static const char * name
Definition: N_TIA_OneStep.h:75
std::vector< std::vector< Linear::Vector * > > dXdpHistory
Linear::Vector * daeBVectorPtr
std::vector< Linear::Vector * > nextDQdxDXdpPtrVector
std::vector< Linear::Vector * > currDqdpPtrVector
std::vector< Linear::Vector * > stoLeadCurrQHistory
void getTwoLevelError(TwoLevelError &tle) const
Linear::Vector * nextLeadCurrentPtr
std::vector< Linear::Vector * > sHistory