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
00030 #include "EpetraExt_DiagonalTransientModel.hpp"
00031 #include "Rythmos_BackwardEulerStepper.hpp"
00032 #include "Rythmos_ImplicitBDFStepper.hpp"
00033 #include "Rythmos_ImplicitRKStepper.hpp"
00034 #include "Rythmos_ForwardSensitivityStepper.hpp"
00035 #include "Rythmos_TimeStepNonlinearSolver.hpp"
00036 #include "Rythmos_DefaultIntegrator.hpp"
00037 #include "Rythmos_SimpleIntegrationControlStrategy.hpp"
00038 #include "Rythmos_StepperAsModelEvaluator.hpp"
00039 #include "Rythmos_RKButcherTableauBuilder.hpp"
00040 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
00041 #include "Thyra_EpetraModelEvaluator.hpp"
00042 #include "Thyra_DirectionalFiniteDiffCalculator.hpp"
00043 #include "Thyra_TestingTools.hpp"
00044 #include "Teuchos_StandardCatchMacros.hpp"
00045 #include "Teuchos_GlobalMPISession.hpp"
00046 #include "Teuchos_DefaultComm.hpp"
00047 #include "Teuchos_VerboseObject.hpp"
00048 #include "Teuchos_XMLParameterListHelpers.hpp"
00049 #include "Teuchos_CommandLineProcessor.hpp"
00050 #include "Teuchos_VerbosityLevelCommandLineProcessorHelpers.hpp"
00051 #include "Teuchos_as.hpp"
00052
00053 #ifdef HAVE_MPI
00054 # include "Epetra_MpiComm.h"
00055 #else
00056 # include "Epetra_SerialComm.h"
00057 #endif // HAVE_MPI
00058
00059
00060 namespace {
00061
00062
00063 const std::string TimeStepNonlinearSolver_name = "TimeStepNonlinearSolver";
00064
00065 const std::string Stratimikos_name = "Stratimikos";
00066
00067 const std::string DiagonalTransientModel_name = "DiagonalTransientModel";
00068
00069 const std::string RythmosStepper_name = "Rythmos Stepper";
00070
00071 const std::string RythmosIntegrator_name = "Rythmos Integrator";
00072
00073 const std::string FdCalc_name = "FD Calc";
00074
00075
00076 Teuchos::RCP<const Teuchos::ParameterList>
00077 getValidParameters()
00078 {
00079 using Teuchos::RCP; using Teuchos::ParameterList;
00080 static RCP<const ParameterList> validPL;
00081 if (is_null(validPL)) {
00082 RCP<ParameterList> pl = Teuchos::parameterList();
00083 pl->sublist(TimeStepNonlinearSolver_name);
00084 pl->sublist(Stratimikos_name);
00085 pl->sublist(DiagonalTransientModel_name);
00086 pl->sublist(RythmosStepper_name);
00087 pl->sublist(RythmosIntegrator_name);
00088 pl->sublist(FdCalc_name);
00089 validPL = pl;
00090 }
00091 return validPL;
00092 }
00093
00094
00095 }
00096
00097
00098 int main(int argc, char *argv[])
00099 {
00100
00101 using std::endl;
00102 typedef double Scalar;
00103 typedef double ScalarMag;
00104 using Teuchos::describe;
00105 using Teuchos::RCP;
00106 using Teuchos::rcp;
00107 using Teuchos::rcp_implicit_cast;
00108 using Teuchos::rcp_dynamic_cast;
00109 using Teuchos::as;
00110 using Teuchos::ParameterList;
00111 using Teuchos::CommandLineProcessor;
00112 typedef Teuchos::ParameterList::PrintOptions PLPrintOptions;
00113 typedef Thyra::ModelEvaluatorBase MEB;
00114 typedef Thyra::DefaultMultiVectorProductVectorSpace<Scalar> DMVPVS;
00115 using Thyra::productVectorBase;
00116
00117 bool result, success = true;
00118
00119 Teuchos::GlobalMPISession mpiSession(&argc,&argv);
00120
00121 RCP<Epetra_Comm> epetra_comm;
00122 #ifdef HAVE_MPI
00123 epetra_comm = rcp( new Epetra_MpiComm(MPI_COMM_WORLD) );
00124 #else
00125 epetra_comm = rcp( new Epetra_SerialComm );
00126 #endif // HAVE_MPI
00127
00128 RCP<Teuchos::FancyOStream>
00129 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00130
00131 try {
00132
00133
00134
00135
00136
00137 CommandLineProcessor clp;
00138 clp.throwExceptions(false);
00139 clp.addOutputSetupOptions(true);
00140
00141 std::string paramsFileName = "";
00142 clp.setOption( "params-file", ¶msFileName,
00143 "File name for XML parameters" );
00144
00145 std::string extraParamsString = "";
00146 clp.setOption( "extra-params", &extraParamsString,
00147 "Extra XML parameters" );
00148
00149 double maxStateError = 1e-6;
00150 clp.setOption( "max-state-error", &maxStateError,
00151 "The maximum allowed error in the integrated state in relation to the exact state solution" );
00152
00153 double finalTime = 1e-3;
00154 clp.setOption( "final-time", &finalTime,
00155 "Final integration time (initial time is 0.0)" );
00156
00157 int numTimeSteps = 10;
00158 clp.setOption( "num-time-steps", &numTimeSteps,
00159 "Number of (fixed) time steps. If <= 0.0, then variable time steps are taken" );
00160
00161 bool useBDF = false;
00162 clp.setOption( "use-BDF", "use-BE", &useBDF,
00163 "Use BDF or Backward Euler (BE)" );
00164
00165 bool useIRK = false;
00166 clp.setOption( "use-IRK", "use-other", &useIRK,
00167 "Use IRK or something" );
00168
00169 bool doFwdSensSolve = false;
00170 clp.setOption( "fwd-sens-solve", "state-solve", &doFwdSensSolve,
00171 "Do the forward sensitivity solve or just the state solve" );
00172
00173 bool doFwdSensErrorControl = false;
00174 clp.setOption( "fwd-sens-err-cntrl", "no-fwd-sens-err-cntrl", &doFwdSensErrorControl,
00175 "Do error control on the forward sensitivity solve or not" );
00176
00177 double maxRestateError = 0.0;
00178 clp.setOption( "max-restate-error", &maxRestateError,
00179 "The maximum allowed error between the state integrated by itself verses integrated along with DxDp" );
00180
00181 double maxSensError = 1e-4;
00182 clp.setOption( "max-sens-error", &maxSensError,
00183 "The maximum allowed error in the integrated sensitivity in relation to"
00184 " the finite-difference sensitivity" );
00185
00186 Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_DEFAULT;
00187 setVerbosityLevelOption( "verb-level", &verbLevel,
00188 "Top-level verbosity level. By default, this gets deincremented as you go deeper into numerical objects.",
00189 &clp );
00190
00191 bool testExactSensitivity = false;
00192 clp.setOption( "test-exact-sens", "no-test-exact-sens", &testExactSensitivity,
00193 "Test the exact sensitivity with finite differences or not." );
00194
00195 bool dumpFinalSolutions = false;
00196 clp.setOption(
00197 "dump-final-solutions", "no-dump-final-solutions", &dumpFinalSolutions,
00198 "Determine if the final solutions are dumpped or not." );
00199
00200 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00201 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00202
00203 if ( Teuchos::VERB_DEFAULT == verbLevel )
00204 verbLevel = Teuchos::VERB_LOW;
00205
00206 const Teuchos::EVerbosityLevel
00207 solnVerbLevel = ( dumpFinalSolutions ? Teuchos::VERB_EXTREME : verbLevel );
00208
00209
00210
00211
00212
00213
00214 RCP<ParameterList>
00215 paramList = Teuchos::parameterList();
00216 if (paramsFileName.length())
00217 updateParametersFromXmlFile( paramsFileName, &*paramList );
00218 if (extraParamsString.length())
00219 updateParametersFromXmlString( extraParamsString, &*paramList );
00220
00221 if (testExactSensitivity) {
00222 paramList->sublist(DiagonalTransientModel_name).set("Exact Solution as Response",true);
00223 }
00224
00225 paramList->validateParameters(*getValidParameters(),0);
00226
00227
00228
00229
00230
00231
00232
00233
00234 Stratimikos::DefaultLinearSolverBuilder linearSolverBuilder;
00235 linearSolverBuilder.setParameterList(sublist(paramList,Stratimikos_name));
00236 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
00237 W_factory = createLinearSolveStrategy(linearSolverBuilder);
00238
00239
00240
00241
00242
00243 RCP<EpetraExt::DiagonalTransientModel>
00244 epetraStateModel = EpetraExt::diagonalTransientModel(
00245 epetra_comm,
00246 sublist(paramList,DiagonalTransientModel_name)
00247 );
00248
00249 *out <<"\nepetraStateModel valid options:\n";
00250 epetraStateModel->getValidParameters()->print(
00251 *out, PLPrintOptions().indent(2).showTypes(true).showDoc(true)
00252 );
00253
00254
00255
00256
00257
00258 RCP<Thyra::ModelEvaluator<double> >
00259 stateModel = epetraModelEvaluator(epetraStateModel,W_factory);
00260
00261 *out << "\nParameter names = " << *stateModel->get_p_names(0) << "\n";
00262
00263
00264
00265
00266
00267 RCP<Rythmos::TimeStepNonlinearSolver<double> >
00268 nonlinearSolver = Rythmos::timeStepNonlinearSolver<double>();
00269 RCP<ParameterList>
00270 nonlinearSolverPL = sublist(paramList,TimeStepNonlinearSolver_name);
00271 nonlinearSolverPL->get("Default Tol",1e-3*maxStateError);
00272 nonlinearSolver->setParameterList(nonlinearSolverPL);
00273
00274 RCP<Rythmos::StepperBase<Scalar> > stateStepper;
00275
00276 if (useBDF) {
00277 stateStepper = rcp(
00278 new Rythmos::ImplicitBDFStepper<double>(
00279 stateModel, nonlinearSolver
00280 )
00281 );
00282 }
00283 else if (useIRK) {
00284
00285 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
00286 irk_W_factory = createLinearSolveStrategy(linearSolverBuilder);
00287 RCP<Rythmos::RKButcherTableauBase<double> > irkbt = Rythmos::createRKBT<double>("Backward Euler");
00288 stateStepper = Rythmos::implicitRKStepper<double>(
00289 stateModel, nonlinearSolver, irk_W_factory, irkbt
00290 );
00291 }
00292 else {
00293 stateStepper = rcp(
00294 new Rythmos::BackwardEulerStepper<double>(
00295 stateModel, nonlinearSolver
00296 )
00297 );
00298 }
00299
00300 *out <<"\nstateStepper:\n" << describe(*stateStepper,verbLevel);
00301 *out <<"\nstateStepper valid options:\n";
00302 stateStepper->getValidParameters()->print(
00303 *out, PLPrintOptions().indent(2).showTypes(true).showDoc(true)
00304 );
00305
00306 stateStepper->setParameterList(sublist(paramList,RythmosStepper_name));
00307
00308
00309
00310
00311
00312 Thyra::DirectionalFiniteDiffCalculator<Scalar> fdCalc;
00313 fdCalc.setParameterList(sublist(paramList,FdCalc_name));
00314 fdCalc.setOStream(out);
00315 fdCalc.setVerbLevel(verbLevel);
00316
00317
00318
00319
00320
00321 const MEB::InArgs<Scalar>
00322 state_ic = stateModel->getNominalValues();
00323 *out << "\nstate_ic:\n" << describe(state_ic,verbLevel);
00324
00325 RCP<Rythmos::IntegratorBase<Scalar> > integrator;
00326 {
00327 RCP<ParameterList>
00328 integratorPL = sublist(paramList,RythmosIntegrator_name);
00329 integratorPL->set( "Take Variable Steps", as<bool>(numTimeSteps < 0) );
00330 integratorPL->set( "Fixed dt", as<double>((finalTime - state_ic.get_t())/numTimeSteps) );
00331 RCP<Rythmos::IntegratorBase<Scalar> >
00332 defaultIntegrator = Rythmos::controlledDefaultIntegrator<Scalar>(
00333 Rythmos::simpleIntegrationControlStrategy<Scalar>(integratorPL)
00334 );
00335 integrator = defaultIntegrator;
00336 }
00337
00338 RCP<Rythmos::StepperAsModelEvaluator<Scalar> >
00339 stateIntegratorAsModel = Rythmos::stepperAsModelEvaluator(
00340 stateStepper, integrator, state_ic
00341 );
00342 stateIntegratorAsModel->setVerbLevel(verbLevel);
00343
00344 *out << "\nUse the StepperAsModelEvaluator to integrate state x(p,finalTime) ... \n";
00345
00346 RCP<Thyra::VectorBase<Scalar> > x_final;
00347
00348 {
00349
00350 Teuchos::OSTab tab(out);
00351
00352 x_final = createMember(stateIntegratorAsModel->get_g_space(0));
00353
00354 eval_g(
00355 *stateIntegratorAsModel,
00356 0, *state_ic.get_p(0),
00357 finalTime,
00358 0, &*x_final
00359 );
00360
00361 *out
00362 << "\nx_final = x(p,finalTime) evaluated using stateIntegratorAsModel:\n"
00363 << describe(*x_final,solnVerbLevel);
00364
00365 }
00366
00367
00368
00369
00370
00371 RCP<const Thyra::VectorBase<Scalar> >
00372 exact_x_final = create_Vector(
00373 epetraStateModel->getExactSolution(finalTime),
00374 stateModel->get_x_space()
00375 );
00376
00377 result = Thyra::testRelNormDiffErr(
00378 "exact_x_final", *exact_x_final, "x_final", *x_final,
00379 "maxStateError", maxStateError, "warningTol", 1.0,
00380 &*out, solnVerbLevel
00381 );
00382 if (!result) success = false;
00383
00384
00385
00386
00387
00388 if (doFwdSensSolve) {
00389
00390
00391
00392
00393
00394 RCP<Rythmos::ForwardSensitivityStepper<Scalar> > stateAndSensStepper =
00395 Rythmos::forwardSensitivityStepper<Scalar>();
00396 if (doFwdSensErrorControl) {
00397 stateAndSensStepper->initializeDecoupledSteppers(
00398 stateModel, 0, stateModel->getNominalValues(),
00399 stateStepper, nonlinearSolver,
00400 integrator->cloneIntegrator(), finalTime
00401 );
00402 }
00403 else {
00404 stateAndSensStepper->initializeSyncedSteppers(
00405 stateModel, 0, stateModel->getNominalValues(),
00406 stateStepper, nonlinearSolver
00407 );
00408
00409
00410
00411 }
00412
00413
00414
00415
00416
00417 RCP<Thyra::VectorBase<Scalar> > s_bar_init
00418 = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space());
00419 assign( &*s_bar_init, 0.0 );
00420 RCP<Thyra::VectorBase<Scalar> > s_bar_dot_init
00421 = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space());
00422 assign( &*s_bar_dot_init, 0.0 );
00423
00424
00425
00426
00427 RCP<const Rythmos::StateAndForwardSensitivityModelEvaluator<Scalar> >
00428 stateAndSensModel = stateAndSensStepper->getStateAndFwdSensModel();
00429
00430 MEB::InArgs<Scalar>
00431 state_and_sens_ic = stateAndSensStepper->getModel()->createInArgs();
00432
00433
00434 state_and_sens_ic.setArgs(state_ic);
00435
00436 state_and_sens_ic.set_x(
00437 stateAndSensModel->create_x_bar_vec(state_ic.get_x(),s_bar_init)
00438 );
00439
00440 state_and_sens_ic.set_x_dot(
00441 stateAndSensModel->create_x_bar_vec(state_ic.get_x_dot(),s_bar_dot_init)
00442 );
00443
00444 *out << "\nstate_and_sens_ic:\n" << describe(state_and_sens_ic,verbLevel);
00445
00446 stateAndSensStepper->setInitialCondition(state_and_sens_ic);
00447
00448
00449
00450
00451
00452 RCP<Rythmos::StepperAsModelEvaluator<Scalar> >
00453 stateAndSensIntegratorAsModel = Rythmos::stepperAsModelEvaluator(
00454 rcp_implicit_cast<Rythmos::StepperBase<Scalar> >(stateAndSensStepper),
00455 integrator, state_and_sens_ic
00456 );
00457 stateAndSensIntegratorAsModel->setVerbLevel(verbLevel);
00458
00459 *out << "\nUse the StepperAsModelEvaluator to integrate state + sens x_bar(p,finalTime) ... \n";
00460
00461 RCP<Thyra::VectorBase<Scalar> > x_bar_final;
00462
00463 {
00464
00465 Teuchos::OSTab tab(out);
00466
00467 x_bar_final = createMember(stateAndSensIntegratorAsModel->get_g_space(0));
00468
00469 eval_g(
00470 *stateAndSensIntegratorAsModel,
00471 0, *state_ic.get_p(0),
00472 finalTime,
00473 0, &*x_bar_final
00474 );
00475
00476 *out
00477 << "\nx_bar_final = x_bar(p,finalTime) evaluated using stateAndSensIntegratorAsModel:\n"
00478 << describe(*x_bar_final,solnVerbLevel);
00479
00480 }
00481
00482
00483
00484
00485
00486 *out << "\nChecking that x(p,finalTime) computed as part of x_bar above is the same ...\n";
00487
00488 {
00489
00490 Teuchos::OSTab tab(out);
00491
00492 RCP<const Thyra::VectorBase<Scalar> >
00493 x_in_x_bar_final = productVectorBase<Scalar>(x_bar_final)->getVectorBlock(0);
00494
00495 result = Thyra::testRelNormDiffErr<Scalar>(
00496 "x_final", *x_final,
00497 "x_in_x_bar_final", *x_in_x_bar_final,
00498 "maxRestateError", maxRestateError,
00499 "warningTol", 1.0,
00500 &*out, solnVerbLevel
00501 );
00502 if (!result) success = false;
00503
00504 }
00505
00506
00507
00508
00509
00510 *out << "\nApproximating DxDp(p,t) using directional finite differences of integrator for x(p,t) ...\n";
00511
00512 RCP<Thyra::MultiVectorBase<Scalar> > DxDp_fd_final;
00513
00514 {
00515
00516 Teuchos::OSTab tab(out);
00517
00518
00519 MEB::InArgs<Scalar>
00520 fdBasePoint = stateIntegratorAsModel->createInArgs();
00521
00522 fdBasePoint.set_t(finalTime);
00523 fdBasePoint.set_p(0,stateModel->getNominalValues().get_p(0));
00524
00525 DxDp_fd_final = createMembers(
00526 stateIntegratorAsModel->get_g_space(0),
00527 stateIntegratorAsModel->get_p_space(0)->dim()
00528 );
00529
00530 typedef Thyra::DirectionalFiniteDiffCalculatorTypes::SelectedDerivatives
00531 SelectedDerivatives;
00532
00533 MEB::OutArgs<Scalar> fdOutArgs =
00534 fdCalc.createOutArgs(
00535 *stateIntegratorAsModel,
00536 SelectedDerivatives().supports(MEB::OUT_ARG_DgDp,0,0)
00537 );
00538 fdOutArgs.set_DgDp(0,0,DxDp_fd_final);
00539
00540
00541
00542 stateStepper->setVerbLevel(Teuchos::VERB_NONE);
00543 stateIntegratorAsModel->setVerbLevel(Teuchos::VERB_NONE);
00544
00545 fdCalc.calcDerivatives(
00546 *stateIntegratorAsModel, fdBasePoint,
00547 stateIntegratorAsModel->createOutArgs(),
00548 fdOutArgs
00549 );
00550
00551 *out
00552 << "\nFinite difference DxDp_fd_final = DxDp(p,finalTime): "
00553 << describe(*DxDp_fd_final,solnVerbLevel);
00554
00555 }
00556
00557
00558
00559
00560
00561 *out << "\nChecking that integrated DxDp(p,finalTime) and finite-diff DxDp(p,finalTime) are similar ...\n";
00562
00563 {
00564
00565 Teuchos::OSTab tab(out);
00566
00567 RCP<const Thyra::VectorBase<Scalar> >
00568 DxDp_vec_final = Thyra::productVectorBase<Scalar>(x_bar_final)->getVectorBlock(1);
00569
00570 RCP<const Thyra::VectorBase<Scalar> >
00571 DxDp_fd_vec_final = Thyra::multiVectorProductVector(
00572 rcp_dynamic_cast<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> >(
00573 DxDp_vec_final->range()
00574 ),
00575 DxDp_fd_final
00576 );
00577
00578 result = Thyra::testRelNormDiffErr(
00579 "DxDp_vec_final", *DxDp_vec_final,
00580 "DxDp_fd_vec_final", *DxDp_fd_vec_final,
00581 "maxSensError", maxSensError,
00582 "warningTol", 1.0,
00583 &*out, solnVerbLevel
00584 );
00585 if (!result) success = false;
00586
00587 }
00588
00589 }
00590
00591 }
00592 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success);
00593
00594 if(success)
00595 *out << "\nEnd Result: TEST PASSED" << endl;
00596 else
00597 *out << "\nEnd Result: TEST FAILED" << endl;
00598
00599 return ( success ? 0 : 1 );
00600
00601 }
00602