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