46 #include "MoochoPack_MoochoThyraSolver.hpp"
47 #include "Rythmos_BackwardEulerStepper.hpp"
48 #include "Rythmos_ImplicitBDFStepper.hpp"
49 #include "Rythmos_ForwardSensitivityStepper.hpp"
50 #include "Rythmos_TimeStepNonlinearSolver.hpp"
51 #include "Rythmos_DefaultIntegrator.hpp"
52 #include "Rythmos_SimpleIntegrationControlStrategy.hpp"
53 #include "Rythmos_StepperAsModelEvaluator.hpp"
54 #include "Rythmos_ForwardSensitivityIntegratorAsModelEvaluator.hpp"
55 #include "Thyra_EpetraModelEvaluator.hpp"
56 #include "Thyra_DefaultSpmdMultiVectorFileIO.hpp"
57 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
58 #include "Thyra_DefaultInverseModelEvaluator.hpp"
59 #include "Thyra_ModelEvaluatorHelpers.hpp"
60 #include "Thyra_DefaultFiniteDifferenceModelEvaluator.hpp"
61 #include "Thyra_TestingTools.hpp"
62 #include "Teuchos_GlobalMPISession.hpp"
63 #include "Teuchos_CommandLineProcessor.hpp"
64 #include "Teuchos_VerbosityLevelCommandLineProcessorHelpers.hpp"
65 #include "Teuchos_StandardCatchMacros.hpp"
66 #include "Teuchos_VerboseObject.hpp"
67 #include "Teuchos_XMLParameterListHelpers.hpp"
69 # include "Epetra_MpiComm.h"
71 # include "Epetra_SerialComm.h"
78 typedef AbstractLinAlgPack::value_type Scalar;
84 int main(
int argc,
char* argv[] )
90 using Teuchos::rcp_dynamic_cast;
104 RCP<Epetra_Comm> epetra_comm;
111 bool success =
true, result;
123 MoochoThyraSolver moochoThyraSolver;
129 CommandLineProcessor clp;
130 clp.throwExceptions(
false);
131 clp.addOutputSetupOptions(
true);
135 std::string paramsFileName =
"";
136 clp.setOption(
"params-file", ¶msFileName,
137 "File name for varaious parameter lists in xml format.",
141 clp.setOption(
"use-BDF",
"use-BE", &useBDF,
142 "Use BDF or Backward Euler (BE)" );
144 double finalTime = 1e-3;
145 clp.setOption(
"final-time", &finalTime,
146 "Final integration time (initial time is 0.0)" );
148 int numObservationPoints= 10;
149 clp.setOption(
"num-observations", &numObservationPoints,
150 "Number of state observations to take as basis for inversion" );
152 double scaleParamsBy = 1e-2;
153 clp.setOption(
"scale-params-by", &scaleParamsBy,
154 "Amount to scale the parameters by to perturb them" );
157 setVerbosityLevelOption(
"verb-level", &verbLevel,
158 "Top-level verbosity level. By default, this gets deincremented"
159 " as you go deeper into numerical objects.",
162 bool printValidOptions =
false;
163 clp.setOption(
"print-valid-options",
"no-print-valid-options",
164 &printValidOptions,
"Print the valid options or not" );
166 bool testTransientModelEvaluator =
true;
167 clp.setOption(
"test-transient-model",
"no-test-transient-model", &testTransientModelEvaluator,
168 "Test the Rythmos::ForwardSensitivityIntegratorAsModelEvaluator object or not." );
170 double maxSensError = 1e-4;
171 clp.setOption(
"max-sens-error", &maxSensError,
172 "The maximum allowed error in the integrated sensitivity in relation to"
173 " the finite-difference sensitivity" );
175 bool doInverseProblem =
true;
176 clp.setOption(
"do-inv-prob",
"no-do-inv-prob", &doInverseProblem,
177 "Run and test the inverse problem or not" );
179 double p_inv_err_tol = 1e-8;
180 clp.setOption(
"max-p-inv-error", &p_inv_err_tol,
181 "The maximum allowed error in the inverted for parameters" );
183 CommandLineProcessor::EParseCommandLineReturn
184 parse_return = clp.parse(argc,argv,&std::cerr);
186 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL )
189 moochoThyraSolver.readParameters(&*out);
192 paramList = Teuchos::parameterList();
193 if (paramsFileName.length())
194 updateParametersFromXmlFile( paramsFileName, paramList.ptr() );
195 *out <<
"\nRead in parameters list:\n";
196 paramList->print(*out, PLPO().indent(2).showTypes(
true).showDoc(
true));
202 *out <<
"\nCreate the EpetraExt::DiagonalTransientModel wrapper object ...\n";
204 RCP<EpetraExt::DiagonalTransientModel>
205 epetraStateModel = EpetraExt::diagonalTransientModel(
207 sublist(paramList,
"DiagonalTransientModel",
true)
210 if (printValidOptions) {
211 *out <<
"\nepetraStateModel valid options:\n";
212 epetraStateModel->getValidParameters()->print(
213 *out, PLPO().indent(2).showTypes(
true).showDoc(
true)
218 linearSolverBuilder.
setParameterList(sublist(paramList,
"Stratimikos",
true));
219 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
220 W_factory = createLinearSolveStrategy(linearSolverBuilder);
222 RCP<Thyra::ModelEvaluator<Scalar> >
223 stateModel = epetraModelEvaluator(epetraStateModel,W_factory);
230 nonlinearSolverPL = sublist(paramList,
"TimeStepNonlinearSolver",
true);
232 RCP<Rythmos::TimeStepNonlinearSolver<Scalar> >
233 nonlinearSolver =
rcp(
new Rythmos::TimeStepNonlinearSolver<Scalar>());
234 nonlinearSolver->setParameterList(nonlinearSolverPL);
236 RCP<Rythmos::StepperBase<Scalar> > stateStepper;
239 new Rythmos::ImplicitBDFStepper<Scalar>(
240 stateModel, nonlinearSolver
246 new Rythmos::BackwardEulerStepper<Scalar>(
247 stateModel, nonlinearSolver
251 stateStepper->setParameterList(sublist(paramList,
"Rythmos Stepper",
true));
253 *out <<
"\nstateStepper: " << describe(*stateStepper,verbLevel);
254 if (printValidOptions) {
255 *out <<
"\nstateStepper valid options:\n";
256 stateStepper->getValidParameters()->print(
257 *out, PLPO().indent(2).showTypes(
true).showDoc(
true)
261 RCP<Rythmos::IntegratorBase<Scalar> > integrator;
263 integrator = Rythmos::controlledDefaultIntegrator<Scalar>(
264 Rythmos::simpleIntegrationControlStrategy<Scalar>(
265 sublist(paramList,
"Rythmos Integration Control",
true)
270 const MEB::InArgs<Scalar>
271 state_ic = stateModel->getNominalValues();
272 *out <<
"\nstate_ic: " << describe(state_ic,verbLevel);
274 RCP<const Thyra::VectorBase<Scalar> >
275 p = state_ic.get_p(0);
277 stateStepper->setInitialCondition(state_ic);
278 integrator->setStepper(stateStepper,finalTime);
280 if (printValidOptions) {
281 *out <<
"\nintegrator valid options:\n";
282 integrator->getValidParameters()->print(
283 *out, PLPO().indent(2).showTypes(
true).showDoc(
true)
292 Array<Scalar> observationTimes;
293 Array<RCP<const Thyra::VectorBase<Scalar> > > stateObservations;
295 const double obs_dt = (finalTime - state_ic.get_t())/numObservationPoints;
296 *out <<
"\nCollecting observations at intervals of obs_dt = "
297 << obs_dt <<
" ...\n";
302 obs_idx = 0, curr_t = state_ic.get_t() + obs_dt;
303 obs_idx < numObservationPoints;
304 ++obs_idx, curr_t += obs_dt
308 curr_t = std::min(curr_t,finalTime);
310 *out <<
"\nCollecting state observation at curr_t = " << curr_t <<
" ...\n";
311 observationTimes.push_back(curr_t);
312 stateObservations.push_back(get_fwd_x(*integrator,curr_t)->clone_v());
314 *out <<
"\nx("<<curr_t<<
") = "
329 RCP<Rythmos::ForwardSensitivityStepper<Scalar> >
330 stateAndSensStepper = Rythmos::forwardSensitivityStepper<Scalar>(
331 stateModel, 0, stateModel->getNominalValues(),
332 stateStepper, nonlinearSolver
338 const RCP<const DMVPVS>
339 s_bar_space = rcp_dynamic_cast<
const DMVPVS>(
340 stateAndSensStepper->getFwdSensModel()->get_x_space()
347 RCP<Thyra::VectorBase<Scalar> > s_bar_init
348 = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space());
349 assign( s_bar_init.ptr(), 0.0 );
350 RCP<Thyra::VectorBase<Scalar> > s_bar_dot_init
351 = createMember(stateAndSensStepper->getFwdSensModel()->get_x_space());
352 assign( s_bar_dot_init.ptr(), 0.0 );
357 RCP<const Rythmos::StateAndForwardSensitivityModelEvaluator<Scalar> >
358 stateAndSensModel = stateAndSensStepper->getStateAndFwdSensModel();
361 state_and_sens_ic = stateAndSensStepper->getModel()->createInArgs();
364 state_and_sens_ic.setArgs(state_ic);
366 state_and_sens_ic.set_x(
367 stateAndSensModel->create_x_bar_vec(state_ic.get_x(),s_bar_init)
370 state_and_sens_ic.set_x_dot(
371 stateAndSensModel->create_x_bar_vec(state_ic.get_x_dot(),s_bar_dot_init)
374 *out <<
"\nstate_and_sens_ic:\n" << describe(state_and_sens_ic,verbLevel);
376 stateAndSensStepper->setInitialCondition(state_and_sens_ic);
382 Array<RCP<const Thyra::ModelEvaluator<Scalar> > > matchingFuncs;
383 Array<Thyra::ModelEvaluatorBase::InArgs<Scalar> > matchingFuncBasePoints;
385 for (
int obs_idx = 0; obs_idx < numObservationPoints; ++obs_idx ) {
386 RCP<Thyra::DefaultInverseModelEvaluator<Scalar> >
387 matchingFunc = Thyra::defaultInverseModelEvaluator(stateModel);
388 matchingFunc->setParameterList(
389 sublist(paramList,
"DefaultInverseModelEvalautor",
true));
390 matchingFunc->set_observationTarget(stateObservations[obs_idx]);
391 matchingFuncs.push_back(matchingFunc);
392 matchingFuncBasePoints.push_back(state_ic);
399 namespace FSIAMET = Rythmos::ForwardSensitivityIntegratorAsModelEvaluatorTypes;
400 const RCP<Rythmos::IntegratorBase<Scalar> > nullIntegrator;
401 RCP<Rythmos::ForwardSensitivityIntegratorAsModelEvaluator<Scalar> >
402 sensIntegatorAsModelEvaluator =
403 Rythmos::forwardSensitivityIntegratorAsModelEvaluator<Scalar>(
404 stateStepper, integrator, stateAndSensStepper, nullIntegrator,
405 state_and_sens_ic, observationTimes, matchingFuncs,
406 matchingFuncBasePoints, FSIAMET::RESPONSE_TYPE_SUM
408 sensIntegatorAsModelEvaluator->setParameterList(
409 sublist(paramList,
"ForwardSensitivityIntegratorAsModelEvaluator",
true) );
415 if (testTransientModelEvaluator) {
428 *out <<
"\nTest that sensIntegatorAsModelEvaluator computes the right base point ... \n";
431 RCP<Thyra::VectorBase<Scalar> >
432 d_hat = createMember(sensIntegatorAsModelEvaluator->get_g_space(0));
435 *sensIntegatorAsModelEvaluator,
436 0, *state_ic.get_p(0),
441 <<
"\nd_hat(p) evaluated using sensIntegatorAsModelEvaluator:\n"
446 const Scalar d_hat_nrm = norm(*d_hat);
448 const bool d_hat_norm_is_zero = (d_hat_nrm == 0.0);
450 *out <<
"\nCheck: ||d_hat|| = " << d_hat_nrm <<
" == 0 : "
453 if (!d_hat_norm_is_zero)
463 <<
"\nChecking that get_x(stateStepper,finalTime) == stateObservations[numObservationPoints-1] ... \n";
465 RCP<const Thyra::VectorBase<Scalar> >
466 x_final = get_x(*stateStepper,observationTimes[numObservationPoints-1]);
470 "get_x(stateStepper,finalTime)", *x_final,
471 "stateObservations[numObservationPoints-1]", *stateObservations[numObservationPoints-1],
472 "errorTol", 0.0,
"warningTol", 1e-8,
473 &
OSTab(out).o(), verbLevel
475 if (!result) success =
false;
479 *out <<
"\nBase parameters p = " << *p;
481 RCP<Thyra::VectorBase<Scalar> >
482 p_perturb = createMember(p->space());
484 V_StV( p_perturb.ptr(), scaleParamsBy, *p );
486 *out <<
"\nPerturbed parameters p_perturb = " << *p_perturb;
493 *out <<
"\nCompute analytic D(d_hat)/d(p) at p_perturb ...\n";
496 MEB::DerivativeMultiVector<Scalar> D_d_hat_D_p_exact;
499 D_d_hat_D_p_exact = Thyra::create_DgDp_mv(
500 *sensIntegatorAsModelEvaluator, 0, 0, MEB::DERIV_TRANS_MV_BY_ROW );
503 inArgs = sensIntegatorAsModelEvaluator->createInArgs();
504 inArgs.set_p(0,p_perturb);
507 outArgs = sensIntegatorAsModelEvaluator->createOutArgs();
508 outArgs.set_DgDp(0,0,D_d_hat_D_p_exact);
510 sensIntegatorAsModelEvaluator->evalModel(inArgs,outArgs);
513 <<
"\nAnalytic D(d_hat)/d(p)^T = "
514 << describe(*D_d_hat_D_p_exact.getMultiVector(),verbLevel);
519 *out <<
"\nCompute finite-diff D(d_hat)/d(p) at p_perturb ...\n";
522 MEB::DerivativeMultiVector<Scalar> D_d_hat_D_p_fd;
525 RCP<Thyra::DirectionalFiniteDiffCalculator<Scalar> > fdCalc =
526 Thyra::directionalFiniteDiffCalculator<Scalar>(
527 sublist(paramList,
"DirectionalFiniteDiffCalculator",
true)
530 RCP<Thyra::DefaultFiniteDifferenceModelEvaluator<Scalar> > fdModelEval =
531 Thyra::defaultFiniteDifferenceModelEvaluator<Scalar>(
532 sensIntegatorAsModelEvaluator,
537 inArgs = fdModelEval->createInArgs();
538 inArgs.set_p(0,p_perturb);
540 D_d_hat_D_p_fd = Thyra::create_DgDp_mv(
541 *fdModelEval, 0, 0, MEB::DERIV_TRANS_MV_BY_ROW
545 outArgs = fdModelEval->createOutArgs();
546 outArgs.set_DgDp( 0, 0, D_d_hat_D_p_fd );
553 fdModelEval->evalModel(inArgs,outArgs);
556 <<
"\nFinite difference D(d_hat)/d(p)^T = "
557 << describe(*D_d_hat_D_p_fd.getMultiVector(),verbLevel);
562 *out <<
"\nCompare analytic and finite-diff D(d_hat)/d(p)^T ...\n";
565 RCP<const Thyra::VectorBase<Scalar> >
566 D_d_hat_D_p_exact_vec = D_d_hat_D_p_exact.getMultiVector()->col(0),
567 D_d_hat_D_p_fd_vec = D_d_hat_D_p_fd.getMultiVector()->col(0);
570 "D_d_hat_D_p_exact_vec", *D_d_hat_D_p_exact_vec,
571 "D_d_hat_D_p_fd_vec", *D_d_hat_D_p_fd_vec,
572 "maxSensError", maxSensError,
576 if (!result) success =
false;
580 if (doInverseProblem) {
586 *out <<
"\nSetup the MoochoThyraSolver object ...\n";
588 moochoThyraSolver.setParameterList(
589 sublist(paramList,
"MoochoThyraSolver",
true) );
591 moochoThyraSolver.setModel(sensIntegatorAsModelEvaluator);
597 *out <<
"\nSetup the transient inverse problem ...\n";
599 moochoThyraSolver.readInitialGuess(&*out);
601 const MoochoSolver::ESolutionStatus
602 solution_status = moochoThyraSolver.solve();
604 if ( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED )
607 moochoThyraSolver.writeFinalSolution(&*out);
613 RCP<const Thyra::VectorBase<Scalar> >
614 p_inv = moochoThyraSolver.getFinalPoint().get_p(0);
619 "errorTol", p_inv_err_tol,
620 "warningTol", p_inv_err_tol * 1e+2,
623 if (!result) success =
false;
631 *out <<
"\nEnd Result: TEST PASSED\n";
633 *out <<
"\nEnd Result: TEST FAILED\n";
635 return ( success ? 0 : 1 );
basic_OSTab< char > OSTab
void setupCLP(Teuchos::CommandLineProcessor *clp)
basic_FancyOStream & setMaxLenLinePrefix(const int maxLenLinePrefix)
const std::string passfail(const bool result)
bool testRelNormDiffErr(const std::string &v1_name, const VectorBase< Scalar > &v1, const std::string &v2_name, const VectorBase< Scalar > &v2, const std::string &maxRelErr_error_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_error, const std::string &maxRelErr_warning_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_warning, std::ostream *out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_LOW, const std::string &leadingIndent=std::string(""))
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &V_rhs)
void setParameterList(RCP< ParameterList > const ¶mList)
void assign(MatrixOp *M_lhs, const MatrixOp &M_rhs, BLAS_Cpp::Transp trans_rhs)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static RCP< FancyOStream > getDefaultOStream()
TEUCHOSCORE_LIB_DLL_EXPORT bool includesVerbLevel(const EVerbosityLevel verbLevel, const EVerbosityLevel requestedVerbLevel, const bool isDefaultLevel=false)
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)