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