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