00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef Rythmos_IMPLICITBDF_STEPPER_H
00030 #define Rythmos_IMPLICITBDF_STEPPER_H
00031
00032 #include "Rythmos_Stepper.hpp"
00033 #include "Teuchos_RefCountPtr.hpp"
00034 #include "Thyra_VectorBase.hpp"
00035 #include "Thyra_ModelEvaluator.hpp"
00036 #include "Thyra_ModelEvaluatorHelpers.hpp"
00037 #include "Thyra_NonlinearSolverBase.hpp"
00038 #include "Thyra_SingleResidSSDAEModelEvaluator.hpp"
00039 #include "Thyra_SolveSupportTypes.hpp"
00040
00041 namespace Rythmos {
00042
00043 enum BDFactionFlag { ACTION_UNSET, ACTION_LOWER, ACTION_MAINTAIN, ACTION_RAISE };
00044 enum BDFstatusFlag { PREDICT_AGAIN, CONTINUE_ANYWAY, REP_ERR_FAIL, REP_CONV_FAIL };
00045
00047 template<class Scalar>
00048 class ImplicitBDFStepper : virtual public Stepper<Scalar>
00049 {
00050 public:
00051
00052 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00053
00055 ImplicitBDFStepper(
00056 const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model
00057 ,const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver
00058 );
00059
00061 ImplicitBDFStepper(
00062 const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model
00063 ,const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver
00064 ,Teuchos::ParameterList ¶meterList
00065 );
00066
00068 void InitializeStepper(Teuchos::ParameterList &implicitBDFParameters);
00069
00071 void setModel(const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model);
00072
00074 void setSolver(const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver);
00075
00077 Scalar TakeStep(Scalar dt);
00078
00080 Scalar TakeStep();
00081
00083 Teuchos::RefCountPtr<const Thyra::VectorBase<Scalar> > get_solution() const;
00084
00086 Teuchos::RefCountPtr<const Thyra::VectorBase<Scalar> > get_residual() const;
00087
00089 std::string description() const;
00090
00092 void describe(
00093 Teuchos::FancyOStream &out
00094 ,const Teuchos::EVerbosityLevel verbLevel
00095 ) const;
00096
00097 bool ErrWtVecSet(
00098 Thyra::VectorBase<Scalar> *w,
00099 const Thyra::VectorBase<Scalar> &y
00100 );
00101
00102 Scalar WRMSNorm(
00103 const Thyra::VectorBase<Scalar> &w
00104 , const Thyra::VectorBase<Scalar> &y
00105 ) const;
00106
00109 bool SetPoints(
00110 const std::vector<Scalar>& time_list
00111 ,const std::vector<Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > >& x_list
00112 ,const std::vector<Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > >& xdot_list);
00113
00115 bool GetPoints(
00116 const std::vector<Scalar>& time_list
00117 ,std::vector<Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > >* x_list
00118 ,std::vector<Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > >* xdot_list
00119 ,std::vector<ScalarMag>* accuracy_list) const;
00120
00122 bool SetRange(
00123 const Scalar& time_lower
00124 ,const Scalar& time_upper
00125 ,const InterpolationBuffer<Scalar> & IB);
00126
00128 bool GetNodes(std::vector<Scalar>* time_list) const;
00129
00131 bool RemoveNodes(std::vector<Scalar>& time_list) const;
00132
00134 int GetOrder() const;
00135
00136
00137 private:
00138
00139
00140 void obtainPredictor();
00141 void obtainResidual();
00142 void obtainJacobian();
00143
00144 void updateHistory();
00145 void restoreHistory();
00146 void updateCoeffs();
00147 void initialize();
00148 Scalar checkReduceOrder();
00149 BDFstatusFlag rejectStep();
00150 void completeStep();
00151
00152 void setDefaultMagicNumbers(Teuchos::ParameterList &magicNumberList);
00153
00154
00155 Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > model;
00156 Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > solver;
00157 Thyra::SingleResidSSDAEModelEvaluator<Scalar> neModel;
00158
00159 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > xn0;
00160 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > xpn0;
00161 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > x_dot_base;
00162 std::vector<Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > > xHistory;
00163 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > ee;
00164 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > delta;
00165 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > residual;
00166 Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > errWtVec;
00167
00168 Scalar time;
00169
00170
00171
00172 ScalarMag relErrTol;
00173 ScalarMag absErrTol;
00174 Scalar hh;
00175 int currentOrder;
00176 int oldOrder;
00177 int maxOrder;
00178 int usedOrder;
00179 Scalar alpha_s;
00180 vector<Scalar> alpha;
00181
00182 Scalar alpha_0;
00183 Scalar cj ;
00184 Scalar ck ;
00185 vector<Scalar> gamma;
00186 vector<Scalar> beta;
00187 vector<Scalar> psi;
00188
00189 vector<Scalar> sigma;
00190 int numberOfSteps;
00191 int nef;
00192 Scalar usedStep;
00193 int nscsco;
00194 Scalar Ek;
00195 Scalar Ekm1;
00196 Scalar Ekm2;
00197 Scalar Ekp1;
00198 Scalar Est;
00199 Scalar Tk;
00200 Scalar Tkm1;
00201 Scalar Tkm2;
00202 Scalar Tkp1;
00203 int newOrder;
00204 bool initialPhase;
00205 Scalar stopTime;
00206 bool constantStepSize;
00207
00208
00209 Scalar h0_safety;
00210 Scalar h0_max_factor;
00211 Scalar h_phase0_incr;
00212 Scalar h_max_inv;
00213 Scalar Tkm1_Tk_safety;
00214 Scalar Tkp1_Tk_safety;
00215 Scalar r_factor;
00216 Scalar r_safety;
00217 Scalar r_fudge;
00218 Scalar r_min;
00219 Scalar r_max;
00220 Scalar r_hincr_test;
00221 Scalar r_hincr;
00222 int max_LET_fail;
00223 Scalar minTimeStep;
00224 Scalar maxTimeStep;
00225
00226 int newtonConvergenceStatus;
00227
00228 #ifdef Rythmos_DEBUG
00229 int debugLevel;
00230 Teuchos::RefCountPtr<Teuchos::FancyOStream> debug_out;
00231 #endif // Rythmos_DEBUG
00232
00233
00234 };
00235
00236
00237
00238
00239 template<class Scalar>
00240 void ImplicitBDFStepper<Scalar>::InitializeStepper(
00241 Teuchos::ParameterList &implicitBDFParameters
00242 )
00243 {
00244 typedef Teuchos::ScalarTraits<Scalar> ST;
00245
00246 maxOrder = implicitBDFParameters.get("maxOrder",int(5));
00247 maxOrder = max(1,min(maxOrder,5));
00248 currentOrder=1;
00249 oldOrder=1;
00250 usedOrder=1;
00251 alpha_s=Scalar(-ST::one());
00252 alpha.reserve(maxOrder+1);
00253
00254 gamma.reserve(maxOrder+1);
00255 beta.reserve(maxOrder+1);
00256 psi.reserve(maxOrder+1);
00257
00258 sigma.reserve(maxOrder+1);
00259 for (int i=0 ; i<maxOrder ; ++i)
00260 {
00261 alpha.push_back(ST::zero());
00262 beta.push_back(ST::zero());
00263 gamma.push_back(ST::zero());
00264 psi.push_back(ST::zero());
00265 sigma.push_back(ST::zero());
00266 }
00267 alpha_0=ST::zero();
00268 cj=ST::zero();
00269 ck=ST::zero();
00270 hh=ST::zero();
00271 numberOfSteps=0;
00272 nef=0;
00273 usedStep=ST::zero();
00274 nscsco=0;
00275 Ek=ST::zero();
00276 Ekm1=ST::zero();
00277 Ekm2=ST::zero();
00278 Ekp1=ST::zero();
00279 Est=ST::zero();
00280 Tk=ST::zero();
00281 Tkm1=ST::zero();
00282 Tkm2=ST::zero();
00283 Tkp1=ST::zero();
00284 newOrder=1;
00285 initialPhase=true;
00286
00287 relErrTol = implicitBDFParameters.get( "relErrTol", Scalar(1.0e-4) );
00288 absErrTol = implicitBDFParameters.get( "absErrTol", Scalar(1.0e-6) );
00289 constantStepSize = implicitBDFParameters.get( "constantStepSize", false );
00290 stopTime = implicitBDFParameters.get( "stopTime", Scalar(10.0) );
00291
00292
00293 #ifdef Rythmos_DEBUG
00294 debugLevel = implicitBDFParameters.get( "debugLevel", int(1) );
00295 debug_out = Teuchos::VerboseObjectBase::getDefaultOStream();
00296 debug_out->precision(15);
00297 debug_out->setMaxLenLinePrefix(28);
00298 debug_out->pushLinePrefix("Rythmos::ImplicitBDFStepper");
00299 debug_out->setShowLinePrefix(true);
00300 debug_out->setTabIndentStr(" ");
00301 #endif // Rythmos_DEBUG
00302
00303 setDefaultMagicNumbers(implicitBDFParameters.sublist("magicNumbers"));
00304
00305 #ifdef Rythmos_DEBUG
00306 Teuchos::OSTab ostab(debug_out,1,"InitializeStepper");
00307 if (debugLevel > 1)
00308 {
00309 *debug_out << "maxOrder = " << maxOrder << endl;
00310 *debug_out << "currentOrder = " << currentOrder << endl;
00311 *debug_out << "oldOrder = " << oldOrder << endl;
00312 *debug_out << "usedOrder = " << usedOrder << endl;
00313 *debug_out << "alpha_s = " << alpha_s << endl;
00314 for (int i=0 ; i<maxOrder ; ++i)
00315 {
00316 *debug_out << "alpha[" << i << "] = " << alpha[i] << endl;
00317 *debug_out << "beta[" << i << "] = " << beta[i] << endl;
00318 *debug_out << "gamma[" << i << "] = " << gamma[i] << endl;
00319 *debug_out << "psi[" << i << "] = " << psi[i] << endl;
00320 *debug_out << "sigma[" << i << "] = " << sigma[i] << endl;
00321 }
00322 *debug_out << "alpha_0 = " << alpha_0 << endl;
00323 *debug_out << "cj = " << cj << endl;
00324 *debug_out << "ck = " << ck << endl;
00325 *debug_out << "numberOfSteps = " << numberOfSteps << endl;
00326 *debug_out << "nef = " << nef << endl;
00327 *debug_out << "usedStep = " << usedStep << endl;
00328 *debug_out << "nscsco = " << nscsco << endl;
00329 *debug_out << "Ek = " << Ek << endl;
00330 *debug_out << "Ekm1 = " << Ekm1 << endl;
00331 *debug_out << "Ekm2 = " << Ekm2 << endl;
00332 *debug_out << "Ekp1 = " << Ekp1 << endl;
00333 *debug_out << "Est = " << Est << endl;
00334 *debug_out << "Tk = " << Tk << endl;
00335 *debug_out << "Tkm1 = " << Tkm1 << endl;
00336 *debug_out << "Tkm2 = " << Tkm2 << endl;
00337 *debug_out << "Tkp1 = " << Tkp1 << endl;
00338 *debug_out << "newOrder = " << newOrder << endl;
00339 *debug_out << "initialPhase = " << initialPhase << endl;
00340 *debug_out << "relErrTol = " << relErrTol << endl;
00341 *debug_out << "absErrTol = " << absErrTol << endl;
00342 *debug_out << "constantStepSize = " << constantStepSize << endl;
00343 *debug_out << "stopTime = " << stopTime << endl;
00344 }
00345 #endif // Rythmos_DEBUG
00346 }
00347
00348 template<class Scalar>
00349 ImplicitBDFStepper<Scalar>::ImplicitBDFStepper(
00350 const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model
00351 ,const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver
00352 ,Teuchos::ParameterList ¶meterList
00353 )
00354 {
00355 InitializeStepper(parameterList);
00356
00357
00358 setModel(model);
00359 setSolver(solver);
00360 }
00361
00362 template<class Scalar>
00363 ImplicitBDFStepper<Scalar>::ImplicitBDFStepper(
00364 const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model
00365 ,const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver
00366 )
00367 {
00368 Teuchos::ParameterList emptyList;
00369 InitializeStepper(emptyList);
00370
00371
00372 setModel(model);
00373 setSolver(solver);
00374 }
00375
00376 template<class Scalar>
00377 void ImplicitBDFStepper<Scalar>::setDefaultMagicNumbers(
00378 Teuchos::ParameterList &magicNumberList)
00379 {
00380
00381 h0_safety = magicNumberList.get( "h0_safety", Scalar(2.0) );
00382 h0_max_factor = magicNumberList.get( "h0_max_factor", Scalar(0.001) );
00383 h_phase0_incr = magicNumberList.get( "h_phase0_incr", Scalar(2.0) );
00384 h_max_inv = magicNumberList.get( "h_max_inv", Scalar(0.0) );
00385 Tkm1_Tk_safety = magicNumberList.get( "Tkm1_Tk_safety", Scalar(2.0) );
00386 Tkp1_Tk_safety = magicNumberList.get( "Tkp1_Tk_safety", Scalar(0.5) );
00387 r_factor = magicNumberList.get( "r_factor", Scalar(0.9) );
00388 r_safety = magicNumberList.get( "r_safety", Scalar(2.0) );
00389 r_fudge = magicNumberList.get( "r_fudge", Scalar(0.0001) );
00390 r_min = magicNumberList.get( "r_min", Scalar(0.125) );
00391 r_max = magicNumberList.get( "r_max", Scalar(0.9) );
00392 r_hincr_test = magicNumberList.get( "r_hincr_test", Scalar(2.0) );
00393 r_hincr = magicNumberList.get( "r_hincr", Scalar(2.0) );
00394 max_LET_fail = magicNumberList.get( "max_LET_fail", int(15) );
00395 minTimeStep = magicNumberList.get( "minTimeStep", Scalar(0.0) );
00396 maxTimeStep = magicNumberList.get( "maxTimeStep", Scalar(10.0) );
00397
00398 #ifdef Rythmos_DEBUG
00399 Teuchos::OSTab ostab(debug_out,1,"setDefaultMagicNumbers");
00400 if (debugLevel > 1)
00401 {
00402 *debug_out << "h0_safety = " << h0_safety << endl;
00403 *debug_out << "h0_max_factor = " << h0_max_factor << endl;
00404 *debug_out << "h_phase0_incr = " << h_phase0_incr << endl;
00405 *debug_out << "h_max_inv = " << h_max_inv << endl;
00406 *debug_out << "Tkm1_Tk_safety = " << Tkm1_Tk_safety << endl;
00407 *debug_out << "Tkp1_Tk_safety = " << Tkp1_Tk_safety << endl;
00408 *debug_out << "r_factor = " << r_factor << endl;
00409 *debug_out << "r_safety = " << r_safety << endl;
00410 *debug_out << "r_fudge = " << r_fudge << endl;
00411 *debug_out << "r_min = " << r_min << endl;
00412 *debug_out << "r_max = " << r_max << endl;
00413 *debug_out << "r_hincr_test = " << r_hincr_test << endl;
00414 *debug_out << "r_hincr = " << r_hincr << endl;
00415 *debug_out << "max_LET_fail = " << max_LET_fail << endl;
00416 *debug_out << "minTimeStep = " << minTimeStep << endl;
00417 *debug_out << "maxTimeStep = " << maxTimeStep << endl;
00418 }
00419 #endif // Rythmos_DEBUG
00420 }
00421
00422 template<class Scalar>
00423 void ImplicitBDFStepper<Scalar>::setModel(const Teuchos::RefCountPtr<const Thyra::ModelEvaluator<Scalar> > &model_)
00424 {
00425 typedef Teuchos::ScalarTraits<Scalar> ST;
00426 model = model_;
00427 time = ST::zero();
00428 xn0 = model->getNominalValues().get_x()->clone_v();
00429 xpn0 = model->getNominalValues().get_x_dot()->clone_v();
00430 x_dot_base = model->getNominalValues().get_x_dot()->clone_v();
00431 ee = model->getNominalValues().get_x()->clone_v();
00432 delta = model->getNominalValues().get_x()->clone_v();
00433 residual = Thyra::createMember(model->get_f_space());
00434 errWtVec = xn0->clone_v();
00435 ErrWtVecSet(&*errWtVec,*xn0);
00436 xHistory.push_back(xn0->clone_v());
00437 xHistory.push_back(xpn0->clone_v());
00438 for (int i=2 ; i<=maxOrder ; ++i)
00439 {
00440 xHistory.push_back(xn0->clone_v());
00441 V_S(&*xHistory[i],ST::zero());
00442 }
00443 initialize();
00444 }
00445
00446 template<class Scalar>
00447 void ImplicitBDFStepper<Scalar>::setSolver(const Teuchos::RefCountPtr<Thyra::NonlinearSolverBase<Scalar> > &solver_)
00448 {
00449 solver = solver_;
00450 }
00451
00452 template<class Scalar>
00453 Scalar ImplicitBDFStepper<Scalar>::TakeStep()
00454 {
00455 typedef Teuchos::ScalarTraits<Scalar> ST;
00456 typedef typename Thyra::ModelEvaluatorBase::InArgs<Scalar>::ScalarMag ScalarMag;
00457 #ifdef Rythmos_DEBUG
00458 Teuchos::OSTab ostab(debug_out,1,"TakeStep");
00459 #endif // Rythmos_DEBUG
00460 BDFstatusFlag status;
00461 while (1)
00462 {
00463
00464 updateCoeffs();
00465
00466 ErrWtVecSet(&*errWtVec,*xn0);
00467
00468 obtainPredictor();
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 Scalar coeff_x_dot = Scalar(-ST::one())*alpha_s/hh;
00482 V_StVpStV( &*x_dot_base, ST::one(), *xpn0, alpha_s/hh, *xn0 );
00483 neModel.initialize(model,coeff_x_dot,x_dot_base,ST::one(),Teuchos::null,time+hh,xn0);
00484
00485
00486
00487
00488
00489 if(solver->getModel().get()!=&neModel)
00490 solver->setModel( Teuchos::rcp(&neModel,false) );
00491
00492
00493
00494
00495
00496
00497
00498
00499 Thyra::SolveStatus<Scalar> nonlinearSolveStatus = solver->solve( &*xn0, NULL, &*ee );
00500 if (nonlinearSolveStatus.solveStatus == Thyra::SOLVE_STATUS_CONVERGED)
00501 newtonConvergenceStatus = 0;
00502 else
00503 newtonConvergenceStatus = -1;
00504
00505
00506 Scalar enorm = checkReduceOrder();
00507
00508 #ifdef Rythmos_DEBUG
00509 if (debugLevel > 1)
00510 {
00511 *debug_out << "xn0 = " << std::endl;
00512 xn0->describe(*debug_out,Teuchos::VERB_EXTREME);
00513 *debug_out << "ee = " << std::endl;
00514 ee->describe(*debug_out,Teuchos::VERB_EXTREME);
00515 *debug_out << "delta = " << std::endl;
00516 delta->describe(*debug_out,Teuchos::VERB_EXTREME);
00517 for (int i=0; i<max(2,maxOrder); ++i)
00518 {
00519 *debug_out << "xHistory[" << i << "] = " << std::endl;
00520 xHistory[i]->describe(*debug_out,Teuchos::VERB_EXTREME);
00521 }
00522 *debug_out << "ck = " << ck << endl;
00523 *debug_out << "enorm = " << enorm << endl;
00524 *debug_out << "Local Truncation Error Check: (ck*enorm) < 1: (" << ck*enorm << ") <?= 1" << endl;
00525 }
00526 #endif // Rythmos_DEBUG
00527
00528 if ((ck*enorm) > ST::one())
00529 status = rejectStep();
00530 else
00531 break;
00532 if (status == CONTINUE_ANYWAY)
00533 break;
00534 if (status == REP_ERR_FAIL)
00535 return(Scalar(-ST::one()));
00536 }
00537
00538 completeStep();
00539 return(usedStep);
00540 }
00541
00542 template<class Scalar>
00543 Scalar ImplicitBDFStepper<Scalar>::TakeStep(Scalar dt)
00544 {
00545 constantStepSize = true;
00546 hh = dt;
00547 dt = TakeStep();
00548 return(dt);
00549 }
00550
00551 template<class Scalar>
00552 Teuchos::RefCountPtr<const Thyra::VectorBase<Scalar> > ImplicitBDFStepper<Scalar>::get_solution() const
00553 {
00554 return(xHistory[0]);
00555 }
00556
00557 template<class Scalar>
00558 Teuchos::RefCountPtr<const Thyra::VectorBase<Scalar> > ImplicitBDFStepper<Scalar>::get_residual() const
00559 {
00560 return(residual);
00561 }
00562
00563 template<class Scalar>
00564 std::string ImplicitBDFStepper<Scalar>::description() const
00565 {
00566 std::string name = "Rythmos::ImplicitBDFStepper";
00567 return(name);
00568 }
00569
00570 template<class Scalar>
00571 void ImplicitBDFStepper<Scalar>::describe(
00572 Teuchos::FancyOStream &out
00573 ,const Teuchos::EVerbosityLevel verbLevel
00574 ) const
00575 {
00576 if (verbLevel == Teuchos::VERB_EXTREME)
00577 {
00578 out << description() << "::describe" << std::endl;
00579 out << "model = " << std::endl;
00580 model->describe(out,verbLevel);
00581 out << "solver = " << std::endl;
00582 solver->describe(out,verbLevel);
00583 out << "xn0 = " << std::endl;
00584 xn0->describe(out,verbLevel);
00585 out << "xpn0 = " << std::endl;
00586 xpn0->describe(out,verbLevel);
00587 out << "x_dot_base = " << std::endl;
00588 x_dot_base->describe(out,verbLevel);
00589 out << "xHistory = " << std::endl;
00590 for (int i=0 ; i < max(2,maxOrder) ; ++i)
00591 {
00592 out << "xHistory[" << i << "] = " << std::endl;
00593 xHistory[i]->describe(out,verbLevel);
00594 }
00595 out << "ee = " << std::endl;
00596 ee->describe(out,verbLevel);
00597 out << "delta = " << std::endl;
00598 delta->describe(out,verbLevel);
00599 out << "residual = " << std::endl;
00600 residual->describe(out,verbLevel);
00601 out << "errWtVec = " << std::endl;
00602 errWtVec->describe(out,verbLevel);
00603 out << "time = " << time << std::endl;
00604 out << "hh = " << hh << std::endl;
00605 out << "currentOrder = " << currentOrder << std::endl;
00606 out << "neModel = " << std::endl;
00607 neModel.describe(out,verbLevel);
00608 }
00609 }
00610
00611 template<class Scalar>
00612 void ImplicitBDFStepper<Scalar>::obtainPredictor()
00613 {
00614 typedef Teuchos::ScalarTraits<Scalar> ST;
00615
00616 #ifdef Rythmos_DEBUG
00617 Teuchos::OSTab ostab(debug_out,1,"obtainPredictor");
00618 if (debugLevel > 1)
00619 {
00620 *debug_out << "currentOrder = " << currentOrder << std::endl;
00621 }
00622 #endif // Rythmos_DEBUG
00623
00624
00625 for (int i=nscsco;i<=currentOrder;++i)
00626 {
00627 Vt_S(&*xHistory[i],beta[i]);
00628 }
00629
00630
00631 V_V(&*xn0,*xHistory[0]);
00632 V_S(&*xpn0,ST::zero());
00633 for (int i=1;i<=currentOrder;++i)
00634 {
00635 Vp_V(&*xn0,*xHistory[i]);
00636 Vp_StV(&*xpn0,gamma[i],*xHistory[i]);
00637 }
00638 #ifdef Rythmos_DEBUG
00639 if (debugLevel > 1)
00640 {
00641 *debug_out << "xn0 = " << std::endl;
00642 xn0->describe(*debug_out,Teuchos::VERB_EXTREME);
00643 *debug_out << "xpn0 = " << std::endl;
00644 xpn0->describe(*debug_out,Teuchos::VERB_EXTREME);
00645 }
00646 #endif // Rythmos_DEBUG
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 template<class Scalar>
00695 void ImplicitBDFStepper<Scalar>::updateHistory()
00696 {
00697
00698
00699 if (usedOrder < maxOrder)
00700 {
00701 assign( &*xHistory[usedOrder+1], *ee );
00702 }
00703
00704 Vp_V( &*xHistory[usedOrder], *ee );
00705 for (int j=usedOrder-1;j>=0;j--)
00706 {
00707 Vp_V( &*xHistory[j], *xHistory[j+1] );
00708 }
00709 #ifdef Rythmos_DEBUG
00710 Teuchos::OSTab ostab(debug_out,1,"updateHistory");
00711 if (debugLevel > 1)
00712 {
00713 for (int i=0;i<max(2,maxOrder);++i)
00714 {
00715 *debug_out << "xHistory[" << i << "] = " << endl;
00716 xHistory[i]->describe(*debug_out,Teuchos::VERB_EXTREME);
00717 }
00718 }
00719 #endif // Rythmos_DEBUG
00720
00721 }
00722
00723 template<class Scalar>
00724 void ImplicitBDFStepper<Scalar>::restoreHistory()
00725 {
00726 typedef Teuchos::ScalarTraits<Scalar> ST;
00727
00728
00729 for (int i=nscsco;i<=currentOrder;++i)
00730 {
00731 Vt_S( &*xHistory[i], ST::one()/beta[i] );
00732 }
00733 for (int i=1;i<=currentOrder;++i)
00734 {
00735 psi[i-1] = psi[i] - hh;
00736 }
00737 #ifdef Rythmos_DEBUG
00738 Teuchos::OSTab ostab(debug_out,1,"restoreHistory");
00739 if (debugLevel > 1)
00740 {
00741 for (int i=0;i<maxOrder;++i)
00742 *debug_out << "psi[" << i << "] = " << psi[i] << endl;
00743 for (int i=0;i<maxOrder;++i)
00744 {
00745 *debug_out << "xHistory[" << i << "] = " << endl;
00746 xHistory[i]->describe(*debug_out,Teuchos::VERB_EXTREME);
00747 }
00748 }
00749 #endif // Rythmos_DEBUG
00750 }
00751
00752 template<class Scalar>
00753 void ImplicitBDFStepper<Scalar>::updateCoeffs()
00754 {
00755 typedef Teuchos::ScalarTraits<Scalar> ST;
00756
00757
00758
00759
00760
00761 if ((hh != usedStep) || (currentOrder != usedOrder))
00762 nscsco = 0;
00763 nscsco = min(nscsco+1,usedOrder+2);
00764 if (currentOrder+1 >= nscsco)
00765 {
00766 beta[0] = ST::one();
00767 alpha[0] = ST::one();
00768 Scalar temp1 = hh;
00769 sigma[0] = ST::one();
00770 gamma[0] = ST::zero();
00771 for (int i=1;i<=currentOrder;++i)
00772 {
00773 Scalar temp2 = psi[i-1];
00774 psi[i-1] = temp1;
00775 beta[i] = beta[i-1]*psi[i-1]/temp2;
00776 temp1 = temp2 + hh;
00777 alpha[i] = hh/temp1;
00778 sigma[i] = Scalar(i+1)*sigma[i-1]*alpha[i];
00779 gamma[i] = gamma[i-1]+alpha[i-1]/hh;
00780 }
00781 psi[currentOrder] = temp1;
00782 alpha_s = ST::zero();
00783 alpha_0 = ST::zero();
00784 for (int i=0;i<currentOrder;++i)
00785 {
00786 alpha_s = alpha_s - Scalar(ST::one()/(i+ST::one()));
00787 alpha_0 = alpha_0 - alpha[i];
00788 }
00789 cj = -alpha_s/hh;
00790 ck = abs(alpha[currentOrder]+alpha_s-alpha_0);
00791 ck = max(ck,alpha[currentOrder]);
00792 }
00793 #ifdef Rythmos_DEBUG
00794 Teuchos::OSTab ostab(debug_out,1,"updateCoeffs");
00795 if (debugLevel > 1)
00796 {
00797 for (int i=0;i<=maxOrder;++i)
00798 {
00799 *debug_out << "alpha[" << i << "] = " << alpha[i] << endl;
00800 *debug_out << "beta[" << i << "] = " << beta[i] << endl;
00801 *debug_out << "sigma[" << i << "] = " << sigma[i] << endl;
00802 *debug_out << "gamma[" << i << "] = " << gamma[i] << endl;
00803 *debug_out << "psi[" << i << "] = " << psi[i] << endl;
00804 *debug_out << "alpha_s = " << alpha_s << endl;
00805 *debug_out << "alpha_0 = " << alpha_0 << endl;
00806 *debug_out << "cj = " << cj << endl;
00807 *debug_out << "ck = " << ck << endl;
00808 }
00809 }
00810 #endif // Rythmos_DEBUG
00811
00812 }
00813
00814 template<class Scalar>
00815 void ImplicitBDFStepper<Scalar>::initialize()
00816 {
00817 typedef Teuchos::ScalarTraits<Scalar> ST;
00818
00819
00820 Scalar time_to_stop = stopTime - time;
00821 Scalar currentTimeStep;
00822 if (constantStepSize)
00823 {
00824 currentTimeStep = hh;
00825
00826
00827 }
00828 else
00829 {
00830
00831 Scalar ypnorm = WRMSNorm(*errWtVec,*xHistory[1]);
00832 if (ypnorm > ST::zero())
00833 {
00834 currentTimeStep = min(h0_max_factor*abs(time_to_stop),sqrt(2.0)/(h0_safety*ypnorm));
00835 }
00836 else
00837 {
00838 currentTimeStep = h0_max_factor*abs(time_to_stop);
00839 }
00840
00841 if (hh > ST::zero())
00842 currentTimeStep = min(hh, currentTimeStep);
00843
00844 Scalar rh = abs(currentTimeStep)*h_max_inv;
00845 if (rh>1.0) currentTimeStep = currentTimeStep/rh;
00846 }
00847 hh = currentTimeStep;
00848 #ifdef Rythmos_DEBUG
00849 Teuchos::OSTab ostab(debug_out,1,"initialize");
00850 if (debugLevel > 1)
00851 {
00852 *debug_out << "hh = " << hh << endl;
00853 }
00854 #endif // Rythmos_DEBUG
00855
00856
00857 assign(&*xHistory[0],*xn0);
00858 V_S(&*xHistory[1],ST::zero());
00859
00860
00861 numberOfSteps = 0;
00862 currentOrder = 1;
00863 usedOrder = 1;
00864 psi[0] = hh;
00865 cj = 1/psi[0];
00866 nscsco = 0;
00867 }
00868
00869 template<class Scalar>
00870 Scalar ImplicitBDFStepper<Scalar>::checkReduceOrder()
00871 {
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 Scalar enorm = WRMSNorm(*errWtVec,*ee);
00883 Ek = sigma[currentOrder]*enorm;
00884 Tk = Scalar(currentOrder+1)*Ek;
00885 Est = Ek;
00886 newOrder = currentOrder;
00887 #ifdef Rythmos_DEBUG
00888 Teuchos::OSTab ostab(debug_out,1,"checkReduceOrder");
00889 if (debugLevel > 1)
00890 {
00891 *debug_out << "currentOrder = " << currentOrder << std::endl;
00892 *debug_out << "Ek = " << Ek << std::endl;
00893 *debug_out << "Tk = " << Tk << std::endl;
00894 *debug_out << "enorm = " << enorm << std::endl;
00895 }
00896 #endif // Rythmos_DEBUG
00897 if (currentOrder>1)
00898 {
00899 V_VpV(&*delta,*xHistory[currentOrder],*ee);
00900 Ekm1 = sigma[currentOrder-1]*WRMSNorm(*errWtVec,*delta);
00901