00001 #include "GLpApp_AdvDiffReactOptModelCreator.hpp"
00002 #include "MoochoPack_MoochoThyraSolver.hpp"
00003 #include "Thyra_EpetraModelEvaluator.hpp"
00004 #include "Thyra_EpetraLinearOp.hpp"
00005 #include "Thyra_DefaultClusteredSpmdProductVectorSpace.hpp"
00006 #include "Thyra_DefaultMultiPeriodModelEvaluator.hpp"
00007 #include "Thyra_VectorSpaceTester.hpp"
00008 #include "Thyra_DefaultRealLinearSolverBuilder.hpp"
00009 #include "Thyra_DefaultInverseModelEvaluator.hpp"
00010 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00011 #include "Thyra_DefaultMultipliedLinearOp.hpp"
00012 #include "Thyra_TestingTools.hpp"
00013 #include "RTOpPack_MPI_apply_op_decl.hpp"
00014 #include "Teuchos_OpaqueWrapper.hpp"
00015 #include "Teuchos_GlobalMPISession.hpp"
00016 #include "Teuchos_CommandLineProcessor.hpp"
00017 #include "Teuchos_StandardCatchMacros.hpp"
00018 #include "Teuchos_VerboseObject.hpp"
00019 #include "Teuchos_arrayArg.hpp"
00020 #include "Teuchos_Utils.hpp"
00021 #include "Teuchos_DefaultComm.hpp"
00022 #ifdef HAVE_MPI
00023 # include "Teuchos_DefaultMpiComm.hpp"
00024 # include "Epetra_MpiComm.h"
00025 #else
00026 # include "Teuchos_DefaultSerialComm.hpp"
00027 # include "Epetra_SerialComm.h"
00028 #endif
00029
00030 namespace {
00031
00032 typedef AbstractLinAlgPack::value_type Scalar;
00033
00034 }
00035
00036 int main( int argc, char* argv[] )
00037 {
00038
00039 using Teuchos::rcp;
00040 using Teuchos::rcp_dynamic_cast;
00041 using Teuchos::rcp_implicit_cast;
00042 using Teuchos::null;
00043 using Teuchos::RCP;
00044 using Teuchos::Array;
00045 using Teuchos::tuple;
00046 using Teuchos::ParameterList;
00047 using Teuchos::OpaqueWrapper;
00048 using Teuchos::OSTab;
00049 using Teuchos::CommandLineProcessor;
00050 using Teuchos::toString;
00051 using Thyra::VectorBase;
00052 using Thyra::ProductVectorBase;
00053 typedef Thyra::ModelEvaluatorBase MEB;
00054 typedef Thyra::Index Index;
00055 using Thyra::ModelEvaluator;
00056 using MoochoPack::MoochoSolver;
00057 using MoochoPack::MoochoThyraSolver;
00058
00059 Teuchos::GlobalMPISession mpiSession(&argc,&argv);
00060
00061 const int procRank = mpiSession.getRank();
00062 const int numProcs = mpiSession.getNProc();
00063
00064 Teuchos::Time timer("");
00065
00066 bool result, success = true;
00067
00068 RCP<Teuchos::FancyOStream>
00069 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00070
00071 try {
00072
00073 Thyra::DefaultRealLinearSolverBuilder lowsfCreator;
00074 GLpApp::AdvDiffReactOptModelCreator epetraModelCreator;
00075
00076
00077 MoochoThyraSolver solver;
00078
00079
00080
00081
00082
00083 CommandLineProcessor clp;
00084 clp.throwExceptions(false);
00085 clp.addOutputSetupOptions(true);
00086
00087 epetraModelCreator.setupCLP(&clp);
00088 lowsfCreator.setupCLP(&clp);
00089 solver.setupCLP(&clp);
00090
00091 int numProcsPerCluster = -1;
00092 clp.setOption( "num-procs-per-cluster", &numProcsPerCluster,
00093 "Number of processes in a cluster (<=0 means only one cluster)." );
00094 int numPeriodsPerCluster = 1;
00095 clp.setOption( "num-periods-per-cluster", &numPeriodsPerCluster,
00096 "Number of periods in a cluster." );
00097 bool dumpAll = false;
00098 clp.setOption( "dump-all", "no-dump-all", &dumpAll,
00099 "Set to true, then a bunch of debugging output will be created for the clustered vector tests." );
00100 bool skipSolve = false;
00101 clp.setOption( "skip-solve", "no-skip-solve", &skipSolve,
00102 "Temporary flag for skip solve for testing." );
00103 double perturbedParamScaling = 1.0;
00104 clp.setOption( "p-perturb-scaling", &perturbedParamScaling,
00105 "Scaling for perturbed paramters from the initial forward solve." );
00106 bool doMultiPeriod = true;
00107 clp.setOption( "multi-period", "no-multi-period", &doMultiPeriod,
00108 "Do a mulit-period solve or not." );
00109 bool useOuterInverse = true;
00110 clp.setOption( "use-outer-inverse", "use-inner-inverse", &useOuterInverse,
00111 "Determines if the outer inverse model will be used or the inner inverse." );
00112 double periodParamScale = 1.0;
00113 clp.setOption( "period-param-scale", &periodParamScale,
00114 "Sets the scaling factor to scale z[i] from one period to the next." );
00115 bool initialSolveContinuation = false;
00116 clp.setOption( "init-solve-continuation", "init-solve-all-at-once", &initialSolveContinuation,
00117 "Determines if the inital solve is done using continuation or all at once." );
00118 bool useStatelessPeriodModel = false;
00119 clp.setOption( "use-stateless-period-model", "use-statefull-period-model", &useStatelessPeriodModel,
00120 "Determines if a stateless or a statefull period model should be used or not." );
00121 double stateInvError = 1e-8;
00122 clp.setOption( "state-inv-error", &stateInvError,
00123 "The error in the l2 norm of the state inverse solution error." );
00124 double paramInvError = 1e-8;
00125 clp.setOption( "param-inv-error", ¶mInvError,
00126 "The error in the l2 norm of the parameter inverse solution error." );
00127
00128 CommandLineProcessor::EParseCommandLineReturn
00129 parse_return = clp.parse(argc,argv,&std::cerr);
00130
00131 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL )
00132 return parse_return;
00133
00134 lowsfCreator.readParameters(out.get());
00135 solver.readParameters(out.get());
00136
00137 *out
00138 << "\n***"
00139 << "\n*** NLPThyraEpetraAdvDiffReactOptMain, Global numProcs = "<<numProcs
00140 << "\n***\n";
00141
00142 int clusterRank = -1;
00143 int numClusters = -1;
00144 #ifdef HAVE_MPI
00145
00146 RCP<OpaqueWrapper<MPI_Comm> >
00147 intraClusterMpiComm = Teuchos::opaqueWrapper<MPI_Comm>(MPI_COMM_WORLD),
00148 interClusterMpiComm = Teuchos::null;
00149
00150 {
00151 if ( numProcsPerCluster <= 0 ) {
00152 *out
00153 << "\nnumProcsPerCluster = " << numProcsPerCluster
00154 << " <= 0: Setting to " << numProcs << "...\n";
00155 numProcsPerCluster = numProcs;
00156 }
00157 *out << "\nCreating communicator for local cluster of "<<numProcsPerCluster<<" processes ...\n";
00158 numClusters = numProcs/numProcsPerCluster;
00159 const int remainingProcs = numProcs%numProcsPerCluster;
00160 TEST_FOR_EXCEPTION(
00161 remainingProcs!=0,std::logic_error
00162 ,"Error, The number of processes per cluster numProcsPerCluster="<<numProcsPerCluster
00163 << " does not divide into the global number of processes numProcs="<<numProcs
00164 << " and instead has remainder="<<remainingProcs<<"!"
00165 );
00166
00167
00168 clusterRank = procRank / numProcsPerCluster;
00169 *out << "\nclusterRank = " << clusterRank << "\n";
00170 const int firstClusterProcRank = clusterRank * numProcsPerCluster;
00171 const int lastClusterProcRank = firstClusterProcRank + numProcsPerCluster - 1;
00172 *out << "\nclusterProcRange = ["<<firstClusterProcRank<<","<<lastClusterProcRank<<"]\n";
00173
00174 *out << "\nCreating intraClusterMpiComm ...";
00175 MPI_Comm rawIntraClusterMpiComm = MPI_COMM_NULL;
00176 MPI_Comm_split(
00177 MPI_COMM_WORLD
00178 ,clusterRank
00179 ,0
00180 ,&rawIntraClusterMpiComm
00181 );
00182 intraClusterMpiComm = Teuchos::opaqueWrapper(rawIntraClusterMpiComm,MPI_Comm_free);
00183 {
00184 *out << "\nintraClusterMpiComm:";
00185 Teuchos::OSTab tab(out);
00186 int rank, size;
00187 MPI_Comm_size(*intraClusterMpiComm,&size);
00188 MPI_Comm_rank(*intraClusterMpiComm,&rank);
00189 *out << "\nsize="<<size;
00190 *out << "\nrank="<<rank;
00191 *out << "\n";
00192 }
00193
00194 *out << "\nCreating interClusterMpiComm ...";
00195 MPI_Comm rawInterClusterMpiComm = MPI_COMM_NULL;
00196 MPI_Comm_split(
00197 MPI_COMM_WORLD
00198 ,procRank==firstClusterProcRank?0:MPI_UNDEFINED
00199 ,0
00200 ,&rawInterClusterMpiComm
00201 );
00202 if(rawInterClusterMpiComm!=MPI_COMM_NULL)
00203 interClusterMpiComm = Teuchos::opaqueWrapper(rawInterClusterMpiComm,MPI_Comm_free);
00204 else
00205 interClusterMpiComm = Teuchos::opaqueWrapper(rawInterClusterMpiComm);
00206 {
00207 *out << "\ninterClusterMpiComm:";
00208 Teuchos::OSTab tab(out);
00209 if(*interClusterMpiComm==MPI_COMM_NULL) {
00210 *out << " NULL\n";
00211 }
00212 else {
00213 int rank, size;
00214 MPI_Comm_size(*interClusterMpiComm,&size);
00215 MPI_Comm_rank(*interClusterMpiComm,&rank);
00216 *out << "\nsize="<<size;
00217 *out << "\nrank="<<rank;
00218 *out << "\n";
00219 }
00220 }
00221 }
00222
00223 #endif
00224
00225 RCP<Epetra_Comm> comm = Teuchos::null;
00226 #ifdef HAVE_MPI
00227 comm = Teuchos::rcp(new Epetra_MpiComm(*intraClusterMpiComm));
00228 Teuchos::set_extra_data(intraClusterMpiComm,"mpiComm",&comm);
00229 #else
00230 comm = Teuchos::rcp(new Epetra_SerialComm());
00231 #endif
00232
00233
00234
00235
00236
00237 *out << "\nCreate the GLpApp::AdvDiffReactOptModel wrapper object ...\n";
00238
00239 RCP<GLpApp::AdvDiffReactOptModel>
00240 epetraModel = epetraModelCreator.createModel(comm);
00241
00242 *out << "\nCreate the Thyra::LinearOpWithSolveFactory object ...\n";
00243
00244 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
00245 lowsFactory = lowsfCreator.createLinearSolveStrategy("");
00246
00247
00248 *out << "\nCreate the Thyra::EpetraModelEvaluator wrapper object ...\n";
00249
00250 RCP<Thyra::EpetraModelEvaluator>
00251 epetraThyraModel = rcp(new Thyra::EpetraModelEvaluator());
00252 epetraThyraModel->setOStream(out);
00253 epetraThyraModel->initialize(epetraModel,lowsFactory);
00254
00255 *out
00256 << "\nnx = " << epetraThyraModel->get_x_space()->dim()
00257 << "\nnp = " << epetraThyraModel->get_p_space(0)->dim() << "\n";
00258
00259
00260
00261
00262
00263 RCP<const Thyra::ProductVectorSpaceBase<Scalar> >
00264 x_bar_space, f_bar_space;
00265
00266 #ifdef HAVE_MPI
00267
00268
00269
00270
00271
00272 if (skipSolve) {
00273
00274 *out << "\nCreate block parallel vector spaces for multi-period model.x and model.f ...\n";
00275 RCP<const Teuchos::Comm<Index> >
00276 intraClusterComm = rcp(new Teuchos::MpiComm<Index>(intraClusterMpiComm)),
00277 interClusterComm = Teuchos::createMpiComm<Index>(interClusterMpiComm);
00278 x_bar_space = Teuchos::rcp(
00279 new Thyra::DefaultClusteredSpmdProductVectorSpace<Scalar>(
00280 intraClusterComm
00281 ,0
00282 ,interClusterComm
00283 ,1
00284 ,Teuchos::arrayArg<RCP<const Thyra::VectorSpaceBase<Scalar> > >(
00285 epetraThyraModel->get_x_space()
00286 )()
00287 )
00288 );
00289 f_bar_space = Teuchos::rcp(
00290 new Thyra::DefaultClusteredSpmdProductVectorSpace<Scalar>(
00291 intraClusterComm
00292 ,0
00293 ,interClusterComm
00294 ,1
00295 ,Teuchos::arrayArg<RCP<const Thyra::VectorSpaceBase<Scalar> > >(
00296 epetraThyraModel->get_f_space()
00297 )()
00298 )
00299 );
00300
00301 Thyra::VectorSpaceTester<Scalar> vectorSpaceTester;
00302 vectorSpaceTester.show_all_tests(true);
00303 vectorSpaceTester.dump_all(dumpAll);
00304
00305 #ifdef RTOPPACK_SPMD_APPLY_OP_DUMP
00306 RTOpPack::show_mpi_apply_op_dump = dumpAll;
00307 #endif
00308 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00309 Thyra::SpmdVectorBase<Scalar>::show_dump = dumpAll;
00310 #endif
00311
00312 *out << "\nTesting the vector space x_bar_space ...\n";
00313 result = vectorSpaceTester.check(*x_bar_space,OSTab(out).get());
00314 if(!result) success = false;
00315
00316 *out << "\nTesting the vector space f_bar_space ...\n";
00317 result = vectorSpaceTester.check(*f_bar_space,OSTab(out).get());
00318 if(!result) success = false;
00319
00320 RCP<const VectorBase<Scalar> >
00321 x0 = epetraThyraModel->getNominalValues().get_x();
00322 double nrm_x0;
00323
00324 *out << "\nTiming a global reduction across just this cluster: ||x0||_1 = ";
00325 timer.start(true);
00326 nrm_x0 = Thyra::norm_1(*x0);
00327 *out << nrm_x0 << "\n";
00328 timer.stop();
00329 *out << "\n time = " << timer.totalElapsedTime() << " seconds\n";
00330
00331 *out << "\nTiming a global reduction across the entire set of processes: ||x0||_1 = ";
00332 timer.start(true);
00333 RTOpPack::ROpNorm1<Scalar> norm_1_op;
00334 RCP<RTOpPack::ReductTarget> norm_1_targ = norm_1_op.reduct_obj_create();
00335 const VectorBase<Scalar>* vecs[] = { &*x0 };
00336 Teuchos::dyn_cast<const Thyra::SpmdVectorBase<Scalar> >(*x0).applyOp(
00337 &*Teuchos::DefaultComm<Index>::getComm()
00338 ,norm_1_op,1,vecs,0,static_cast<VectorBase<Scalar>**>(NULL),&*norm_1_targ
00339 ,0,-1,0
00340 );
00341 nrm_x0 = norm_1_op(*norm_1_targ);
00342 *out << nrm_x0 << "\n";
00343 timer.stop();
00344 *out << "\n time = " << timer.totalElapsedTime() << " seconds\n";
00345
00346 #ifdef RTOPPACK_SPMD_APPLY_OP_DUMP
00347 RTOpPack::show_mpi_apply_op_dump = false;
00348 #endif
00349 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00350 Thyra::SpmdVectorBase<Scalar>::show_dump = false;
00351 #endif
00352
00353 }
00354
00355 #endif // HAVE_MPI
00356
00357 if(skipSolve) {
00358
00359 if(success)
00360 *out << "\nEnd Result: TEST PASSED" << endl;
00361 else
00362 *out << "\nEnd Result: TEST FAILED" << endl;
00363
00364 return ( success ? 0 : 1 );
00365
00366 }
00367
00368 const int N = numPeriodsPerCluster;
00369
00370 Array<RCP<Thyra::ModelEvaluator<Scalar> > >
00371 inverseThyraModels(N);
00372 if (useOuterInverse) {
00373 *out << "\nUsing Thyra::DefaultInverseModelEvaluator for the objective function ...\n";
00374 if ( useStatelessPeriodModel ) {
00375 *out << "\nBuilding a single Thyra::DefaultInverseModelEvaluator object where the matching vector will be maintained externally ...\n";
00376 }
00377 else {
00378 *out << "\nBuilding multiple Thyra::DefaultInverseModelEvaluator objects where the matching vector is held internally ...\n";
00379 }
00380 RCP<ParameterList> invMEPL = Teuchos::parameterList();
00381 invMEPL->set( "Observation Multiplier", 1.0 );
00382 invMEPL->set( "Parameter Multiplier", epetraModel->getDataPool()->getbeta() );
00383 if ( useStatelessPeriodModel )
00384 invMEPL->set( "Observation Target as Parameter", true );
00385 RCP<const Thyra::EpetraLinearOp>
00386 H = Thyra::epetraLinearOp(epetraModel->getDataPool()->getH(),"H"),
00387 R = Thyra::epetraLinearOp(epetraModel->getDataPool()->getR(),"R");
00388 RCP<const Thyra::MultiVectorBase<Scalar> >
00389 B_bar = Thyra::create_MultiVector(
00390 epetraModel->get_B_bar(),
00391 R->spmdRange()
00392 );
00393 RCP<const Thyra::LinearOpBase<Scalar> >
00394 R_bar = Thyra::multiply<Scalar>(Thyra::adjoint<Scalar>(B_bar),R,B_bar);
00395 for ( int i = 0; i < N; ++i ) {
00396 if ( ( useStatelessPeriodModel && i==0 ) || !useStatelessPeriodModel ) {
00397 RCP<Thyra::DefaultInverseModelEvaluator<Scalar> >
00398 _inverseThyraModel = Thyra::defaultInverseModelEvaluator<Scalar>(
00399 epetraThyraModel );
00400 _inverseThyraModel->setParameterList(invMEPL);
00401 _inverseThyraModel->set_observationMatchWeightingOp(H);
00402 _inverseThyraModel->set_parameterRegularizationWeightingOp(R_bar);
00403 inverseThyraModels[i] = _inverseThyraModel;
00404 }
00405 else {
00406 #ifdef TEUCHOS_DEBUG
00407 TEST_FOR_EXCEPT( ! ( useStatelessPeriodModel && i > 0 ) );
00408 #endif
00409 inverseThyraModels[i] = inverseThyraModels[0];
00410 }
00411 }
00412 }
00413 else {
00414 *out << "\nUsing built-in inverse objective function ...\n";
00415 TEST_FOR_EXCEPTION(
00416 N != 1, std::logic_error,
00417 "Error, you can't have N = "<<N<<" > 1\n"
00418 "and be using an internal inverse objective!" );
00419 inverseThyraModels[0] = epetraThyraModel;
00420 }
00421
00422 const int p_index = 0;
00423 const int z_index = 1;
00424 const int z_p_index = 1;
00425 const int z_x_index = 2;
00426 Array<int> z_indexes
00427 = (
00428 useStatelessPeriodModel
00429 ? tuple<int>(z_p_index, z_x_index)
00430 : tuple<int>(z_p_index)
00431 );
00432 Array<Array<RCP<const VectorBase<Scalar> > > > z;
00433 const int g_index = ( useOuterInverse ? 1 : 0 );
00434 Array<Scalar> weights;
00435 RCP<VectorBase<Scalar> >
00436 z_base = inverseThyraModels[0]->getNominalValues().get_p(z_index)->clone_v();
00437 *out << "\nz_base =\n" << Teuchos::describe(*z_base,Teuchos::VERB_EXTREME);
00438 Scalar scale_z_i = 1.0;
00439 for ( int i = 0; i < N; ++i ) {
00440 weights.push_back(1.0);
00441 RCP<VectorBase<Scalar> > z_i = z_base->clone_v();
00442 Vt_S( &*z_i, scale_z_i );
00443 *out << "\nz["<<i<<"] =\n" << Teuchos::describe(*z_i,Teuchos::VERB_EXTREME);
00444 if ( useStatelessPeriodModel ) {
00445 z.push_back(
00446 tuple<RCP<const VectorBase<Scalar> > >(
00447 z_i,
00448 null
00449 )
00450 );
00451 }
00452 else {
00453 z.push_back(
00454 tuple<RCP<const VectorBase<Scalar> > >(z_i)
00455 );
00456 }
00457 scale_z_i *= periodParamScale;
00458 }
00459
00460 RCP<Thyra::ModelEvaluator<Scalar> >
00461 thyraModel = inverseThyraModels[0];
00462
00463 if (doMultiPeriod) {
00464 thyraModel =
00465 rcp(
00466 new Thyra::DefaultMultiPeriodModelEvaluator<Scalar>(
00467 N, inverseThyraModels, z_indexes, z, g_index, weights,
00468 x_bar_space, f_bar_space
00469 )
00470 );
00471 }
00472
00473 MoochoSolver::ESolutionStatus solution_status;
00474
00475
00476 *out << "\n***\n*** Solving the initial forward problem\n***\n";
00477
00478
00479
00480 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_FORWARD);
00481
00482
00483 RCP<const VectorBase<Scalar> >
00484 x_opt,
00485 x_init,
00486 p_opt = inverseThyraModels[0]->getNominalValues().get_p(0)->clone_v();
00487
00488 *out << "\np_opt =\n" << Teuchos::describe(*p_opt,Teuchos::VERB_EXTREME);
00489
00490 if ( initialSolveContinuation ) {
00491
00492 *out << "\nSolving individual period problems one at time using continuation ...\n";
00493
00494 RCP<ProductVectorBase<Scalar> >
00495 x_opt_prod = rcp_dynamic_cast<ProductVectorBase<Scalar> >(
00496 createMember( thyraModel->get_x_space() ), true );
00497
00498 RCP<const VectorBase<Scalar> > period_x;
00499
00500 for ( int i = 0; i < N; ++i ) {
00501
00502 *out << "\nSolving period i = " << i << " using guess from last period ...\n";
00503
00504
00505 solver.getSolver().set_output_context("fwd-init-"+toString(i));
00506
00507
00508 solver.setModel(inverseThyraModels[i]);
00509
00510
00511 MEB::InArgs<Scalar> initialGuess = inverseThyraModels[i]->createInArgs();
00512 initialGuess.set_p(z_index,z[i][0]->clone_v());
00513 initialGuess.set_p(p_index,p_opt->clone_v());
00514 if ( i == 0 ) {
00515
00516
00517 }
00518 else {
00519
00520 initialGuess.set_x(period_x);
00521 }
00522 solver.setInitialGuess(initialGuess);
00523
00524
00525 solution_status = solver.solve();
00526 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00527
00528
00529 period_x = solver.getFinalPoint().get_x()->clone_v();
00530 assign( &*x_opt_prod->getNonconstVectorBlock(i), *period_x );
00531 if ( useStatelessPeriodModel )
00532 z[i][1] = period_x->clone_v();
00533
00534 }
00535
00536 x_opt = x_opt_prod;
00537 x_init = x_opt->clone_v();
00538
00539 if ( useStatelessPeriodModel ) {
00540 rcp_dynamic_cast<Thyra::DefaultMultiPeriodModelEvaluator<Scalar> >(
00541 thyraModel
00542 )->reset_z(z);
00543 }
00544
00545 }
00546 else {
00547
00548 *out << "\nSolving all periods simultaniously ...\n";
00549
00550
00551 solver.getSolver().set_output_context("fwd-init");
00552
00553
00554 solver.setModel(thyraModel);
00555
00556
00557 solver.readInitialGuess(out.get());
00558
00559
00560 solution_status = solver.solve();
00561 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00562
00563
00564 x_opt = solver.getFinalPoint().get_x()->clone_v();
00565 x_init = solver.getFinalPoint().get_x()->clone_v();
00566
00567 }
00568
00569
00570 *out << "\n***\n*** Solving the perturbed forward problem\n***\n";
00571
00572
00573
00574 solver.getSolver().set_output_context("fwd");
00575
00576
00577 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_FORWARD);
00578
00579
00580 solver.setModel(thyraModel);
00581
00582
00583 RCP<VectorBase<Scalar> >
00584 p_init = p_opt->clone_v();
00585 {
00586 MEB::InArgs<Scalar> initialGuess = thyraModel->createInArgs();
00587 initialGuess.setArgs(thyraModel->getNominalValues());
00588 initialGuess.set_x(x_init);
00589 Thyra::Vt_S(&*p_init,perturbedParamScaling);
00590 initialGuess.set_p(0,p_init);
00591
00592 solver.setInitialGuess(initialGuess);
00593 }
00594
00595
00596 solution_status = solver.solve();
00597
00598
00599 x_init = solver.getFinalPoint().get_x()->clone_v();
00600 p_init = solver.getFinalPoint().get_p(0)->clone_v();
00601
00602 *out
00603 << "\nrelVectorErr(x_perturb,x_opt) = " << Thyra::relVectorErr(*x_init,*x_opt)
00604 << "\nrelVectorErr(p_perturb,p_opt) = " << Thyra::relVectorErr(*p_init,*p_opt)
00605 << "\n";
00606
00607
00608 *out << "\n***\n*** Solving the perturbed inverse problem\n***\n";
00609
00610
00611
00612 solver.getSolver().set_output_context("inv");
00613
00614
00615
00616
00617 if ( N > 1 ) {
00618 TEST_FOR_EXCEPTION(
00619 !useOuterInverse, std::logic_error,
00620 "Error, if N > 1, you have to use the outer inverse objective function\n"
00621 "since each target vector will be different!" );
00622 RCP<const ProductVectorBase<Scalar> >
00623 x_opt_prod = rcp_dynamic_cast<const ProductVectorBase<Scalar> >(
00624 rcp_implicit_cast<const VectorBase<Scalar> >(x_opt), true
00625 );
00626 for ( int i = 0; i < N; ++i ) {
00627 rcp_dynamic_cast<Thyra::DefaultInverseModelEvaluator<Scalar> >(
00628 inverseThyraModels[i], true
00629 )->set_observationTarget(x_opt_prod->getVectorBlock(i));
00630 }
00631 }
00632 else if ( 1 == N ) {
00633 RCP<const ProductVectorBase<Scalar> >
00634 x_opt_prod = rcp_dynamic_cast<const ProductVectorBase<Scalar> >(
00635 rcp_implicit_cast<const VectorBase<Scalar> >(x_opt)
00636 );
00637 RCP<const VectorBase<Scalar> >
00638 x_opt_i =
00639 ( !is_null(x_opt_prod)
00640 ? x_opt_prod->getVectorBlock(0)
00641 : rcp_implicit_cast<const VectorBase<Scalar> >(x_opt)
00642 );
00643 if (useOuterInverse) {
00644 rcp_dynamic_cast<Thyra::DefaultInverseModelEvaluator<Scalar> >(
00645 inverseThyraModels[0], true
00646 )->set_observationTarget(x_opt_i);
00647 }
00648 else {
00649 epetraModel->set_q(
00650 Thyra::get_Epetra_Vector(*epetraModel->get_x_map(), x_opt_i)
00651 );
00652 }
00653 }
00654 else {
00655 TEST_FOR_EXCEPT("Error, should not get here!");
00656 }
00657
00658
00659 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_OPTIMIZE);
00660
00661
00662 solver.setModel(thyraModel);
00663
00664
00665 {
00666 MEB::InArgs<Scalar> initialGuess = thyraModel->createInArgs();
00667 initialGuess.setArgs(thyraModel->getNominalValues());
00668 initialGuess.set_x(x_init);
00669 initialGuess.set_p(0,p_init);
00670
00671 solver.setInitialGuess(initialGuess);
00672 }
00673
00674
00675 solution_status = solver.solve();
00676 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00677
00678
00679 *out << "\n***\n*** Testing the error in the inversion\n***\n";
00680
00681
00682
00683
00684 RCP<const VectorBase<Scalar> >
00685 x_inv = solver.getFinalPoint().get_x(),
00686 p_inv = solver.getFinalPoint().get_p(0);
00687
00688 *out << "\np_opt =\n" << Teuchos::describe(*p_opt,Teuchos::VERB_EXTREME);
00689 *out << "\np_inv =\n" << Teuchos::describe(*p_inv,Teuchos::VERB_EXTREME);
00690
00691 const Scalar
00692 x_err = Thyra::relVectorErr( *x_inv, *x_opt ),
00693 p_err = Thyra::relVectorErr( *p_inv, *p_opt );
00694
00695 const bool
00696 x_test_passed = ( x_err <= stateInvError ),
00697 p_test_passed = ( p_err <= paramInvError );
00698
00699 *out
00700 << "\nrelVectorErr(x_inv,x_opt) = " << x_err << " <= " << stateInvError
00701 << " : " << Thyra::passfail(x_test_passed)
00702 << "\nrelVectorErr(p_inv,p_opt) = " << p_err << " <= " << paramInvError
00703 << " : " << Thyra::passfail(p_test_passed)
00704 << "\n";
00705
00706
00707 solver.writeFinalSolution(out.get());
00708
00709
00710 lowsfCreator.writeParamsFile(*lowsFactory);
00711 solver.writeParamsFile();
00712
00713 TEST_FOR_EXCEPT(
00714 solution_status != MoochoSolver::SOLVE_RETURN_SOLVED
00715 );
00716
00717 }
00718 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success)
00719
00720 if(success)
00721 *out << "\nEnd Result: TEST PASSED" << endl;
00722 else
00723 *out << "\nEnd Result: TEST FAILED" << endl;
00724
00725 return ( success ? 0 : 1 );
00726
00727 }