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 "Stratimikos_DefaultLinearSolverBuilder.hpp"
00009 #include "Thyra_DefaultInverseModelEvaluator.hpp"
00010 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00011 #include "Thyra_DefaultMultipliedLinearOp.hpp"
00012 #include "Thyra_TestingTools.hpp"
00013 #include "Teuchos_OpaqueWrapper.hpp"
00014 #include "Teuchos_GlobalMPISession.hpp"
00015 #include "Teuchos_CommandLineProcessor.hpp"
00016 #include "Teuchos_StandardCatchMacros.hpp"
00017 #include "Teuchos_VerboseObject.hpp"
00018 #include "Teuchos_arrayArg.hpp"
00019 #include "Teuchos_Utils.hpp"
00020 #include "Teuchos_DefaultComm.hpp"
00021 #ifdef HAVE_MPI
00022 # include "Teuchos_DefaultMpiComm.hpp"
00023 # include "Epetra_MpiComm.h"
00024 #else
00025 # include "Teuchos_DefaultSerialComm.hpp"
00026 # include "Epetra_SerialComm.h"
00027 #endif
00028
00029 namespace {
00030
00031 typedef AbstractLinAlgPack::value_type Scalar;
00032
00033 }
00034
00035 int main( int argc, char* argv[] )
00036 {
00037
00038 using Teuchos::rcp;
00039 using Teuchos::rcp_dynamic_cast;
00040 using Teuchos::rcp_implicit_cast;
00041 using Teuchos::null;
00042 using Teuchos::RCP;
00043 using Teuchos::outArg;
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 Stratimikos::DefaultLinearSolverBuilder 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", outArg(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
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 #ifdef RTOPPACK_SPMD_APPLY_OP_DUMP
00354 RTOpPack::show_mpi_apply_op_dump = false;
00355 #endif
00356 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00357 Thyra::SpmdVectorBase<Scalar>::show_dump = false;
00358 #endif
00359
00360 }
00361
00362 #endif // HAVE_MPI
00363
00364 if(skipSolve) {
00365
00366 if(success)
00367 *out << "\nEnd Result: TEST PASSED" << endl;
00368 else
00369 *out << "\nEnd Result: TEST FAILED" << endl;
00370
00371 return ( success ? 0 : 1 );
00372
00373 }
00374
00375 const int N = numPeriodsPerCluster;
00376
00377 Array<RCP<Thyra::ModelEvaluator<Scalar> > >
00378 inverseThyraModels(N);
00379 if (useOuterInverse) {
00380 *out << "\nUsing Thyra::DefaultInverseModelEvaluator for the objective function ...\n";
00381 if ( useStatelessPeriodModel ) {
00382 *out << "\nBuilding a single Thyra::DefaultInverseModelEvaluator object where the matching vector will be maintained externally ...\n";
00383 }
00384 else {
00385 *out << "\nBuilding multiple Thyra::DefaultInverseModelEvaluator objects where the matching vector is held internally ...\n";
00386 }
00387 RCP<ParameterList> invMEPL = Teuchos::parameterList();
00388 invMEPL->set( "Observation Multiplier", 1.0 );
00389 invMEPL->set( "Parameter Multiplier", epetraModel->getDataPool()->getbeta() );
00390 if ( useStatelessPeriodModel )
00391 invMEPL->set( "Observation Target as Parameter", true );
00392 RCP<const Thyra::EpetraLinearOp>
00393 H = Thyra::epetraLinearOp(epetraModel->getDataPool()->getH(),"H"),
00394 R = Thyra::epetraLinearOp(epetraModel->getDataPool()->getR(),"R");
00395 RCP<const Thyra::MultiVectorBase<Scalar> >
00396 B_bar = Thyra::create_MultiVector(
00397 epetraModel->get_B_bar(),
00398 R->spmdRange()
00399 );
00400 RCP<const Thyra::LinearOpBase<Scalar> >
00401 R_bar = Thyra::multiply<Scalar>(Thyra::adjoint<Scalar>(B_bar),R,B_bar);
00402 for ( int i = 0; i < N; ++i ) {
00403 if ( ( useStatelessPeriodModel && i==0 ) || !useStatelessPeriodModel ) {
00404 RCP<Thyra::DefaultInverseModelEvaluator<Scalar> >
00405 _inverseThyraModel = Thyra::defaultInverseModelEvaluator<Scalar>(
00406 epetraThyraModel );
00407 _inverseThyraModel->setParameterList(invMEPL);
00408 _inverseThyraModel->set_observationMatchWeightingOp(H);
00409 _inverseThyraModel->set_parameterRegularizationWeightingOp(R_bar);
00410 inverseThyraModels[i] = _inverseThyraModel;
00411 }
00412 else {
00413 #ifdef TEUCHOS_DEBUG
00414 TEST_FOR_EXCEPT( ! ( useStatelessPeriodModel && i > 0 ) );
00415 #endif
00416 inverseThyraModels[i] = inverseThyraModels[0];
00417 }
00418 }
00419 }
00420 else {
00421 *out << "\nUsing built-in inverse objective function ...\n";
00422 TEST_FOR_EXCEPTION(
00423 N != 1, std::logic_error,
00424 "Error, you can't have N = "<<N<<" > 1\n"
00425 "and be using an internal inverse objective!" );
00426 inverseThyraModels[0] = epetraThyraModel;
00427 }
00428
00429 const int p_index = 0;
00430 const int z_index = 1;
00431 const int z_p_index = 1;
00432 const int z_x_index = 2;
00433 Array<int> z_indexes;
00434 if (useStatelessPeriodModel)
00435 z_indexes = tuple<int>(z_p_index, z_x_index);
00436 else
00437 z_indexes = tuple<int>(z_p_index);
00438 Array<Array<RCP<const VectorBase<Scalar> > > > z;
00439 const int g_index = ( useOuterInverse ? 1 : 0 );
00440 Array<Scalar> weights;
00441 RCP<VectorBase<Scalar> >
00442 z_base = inverseThyraModels[0]->getNominalValues().get_p(z_index)->clone_v();
00443 *out << "\nz_base =\n" << Teuchos::describe(*z_base,Teuchos::VERB_EXTREME);
00444 Scalar scale_z_i = 1.0;
00445 for ( int i = 0; i < N; ++i ) {
00446 weights.push_back(1.0);
00447 RCP<VectorBase<Scalar> > z_i = z_base->clone_v();
00448 Vt_S( &*z_i, scale_z_i );
00449 *out << "\nz["<<i<<"] =\n" << Teuchos::describe(*z_i,Teuchos::VERB_EXTREME);
00450 if ( useStatelessPeriodModel ) {
00451 z.push_back(
00452 tuple<RCP<const VectorBase<Scalar> > >(
00453 z_i,
00454 null
00455 )
00456 );
00457 }
00458 else {
00459 z.push_back(
00460 tuple<RCP<const VectorBase<Scalar> > >(z_i)
00461 );
00462 }
00463 scale_z_i *= periodParamScale;
00464 }
00465
00466 RCP<Thyra::ModelEvaluator<Scalar> >
00467 thyraModel = inverseThyraModels[0];
00468
00469 if (doMultiPeriod) {
00470 thyraModel =
00471 rcp(
00472 new Thyra::DefaultMultiPeriodModelEvaluator<Scalar>(
00473 N, inverseThyraModels, z_indexes, z, g_index, weights,
00474 x_bar_space, f_bar_space
00475 )
00476 );
00477 }
00478
00479 MoochoSolver::ESolutionStatus solution_status;
00480
00481
00482 *out << "\n***\n*** Solving the initial forward problem\n***\n";
00483
00484
00485
00486 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_FORWARD);
00487
00488
00489 RCP<const VectorBase<Scalar> >
00490 x_opt,
00491 x_init,
00492 p_opt = inverseThyraModels[0]->getNominalValues().get_p(0)->clone_v();
00493
00494 *out << "\np_opt =\n" << Teuchos::describe(*p_opt,Teuchos::VERB_EXTREME);
00495
00496 if ( initialSolveContinuation ) {
00497
00498 *out << "\nSolving individual period problems one at time using continuation ...\n";
00499
00500 RCP<ProductVectorBase<Scalar> >
00501 x_opt_prod = rcp_dynamic_cast<ProductVectorBase<Scalar> >(
00502 createMember( thyraModel->get_x_space() ), true );
00503
00504 RCP<const VectorBase<Scalar> > period_x;
00505
00506 for ( int i = 0; i < N; ++i ) {
00507
00508 *out << "\nSolving period i = " << i << " using guess from last period ...\n";
00509
00510
00511 solver.getSolver().set_output_context("fwd-init-"+toString(i));
00512
00513
00514 solver.setModel(inverseThyraModels[i]);
00515
00516
00517 MEB::InArgs<Scalar> initialGuess = inverseThyraModels[i]->createInArgs();
00518 initialGuess.set_p(z_index,z[i][0]->clone_v());
00519 initialGuess.set_p(p_index,p_opt->clone_v());
00520 if ( i == 0 ) {
00521
00522
00523 }
00524 else {
00525
00526 initialGuess.set_x(period_x);
00527 }
00528 solver.setInitialGuess(initialGuess);
00529
00530
00531 solution_status = solver.solve();
00532 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00533
00534
00535 period_x = solver.getFinalPoint().get_x()->clone_v();
00536 assign( &*x_opt_prod->getNonconstVectorBlock(i), *period_x );
00537 if ( useStatelessPeriodModel )
00538 z[i][1] = period_x->clone_v();
00539
00540 }
00541
00542 x_opt = x_opt_prod;
00543 x_init = x_opt->clone_v();
00544
00545 if ( useStatelessPeriodModel ) {
00546 rcp_dynamic_cast<Thyra::DefaultMultiPeriodModelEvaluator<Scalar> >(
00547 thyraModel
00548 )->reset_z(z);
00549 }
00550
00551 }
00552 else {
00553
00554 *out << "\nSolving all periods simultaniously ...\n";
00555
00556
00557 solver.getSolver().set_output_context("fwd-init");
00558
00559
00560 solver.setModel(thyraModel);
00561
00562
00563 solver.readInitialGuess(out.get());
00564
00565
00566 solution_status = solver.solve();
00567 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00568
00569
00570 x_opt = solver.getFinalPoint().get_x()->clone_v();
00571 x_init = solver.getFinalPoint().get_x()->clone_v();
00572
00573 }
00574
00575
00576 *out << "\n***\n*** Solving the perturbed forward problem\n***\n";
00577
00578
00579
00580 solver.getSolver().set_output_context("fwd");
00581
00582
00583 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_FORWARD);
00584
00585
00586 solver.setModel(thyraModel);
00587
00588
00589 RCP<VectorBase<Scalar> >
00590 p_init = p_opt->clone_v();
00591 {
00592 MEB::InArgs<Scalar> initialGuess = thyraModel->createInArgs();
00593 initialGuess.setArgs(thyraModel->getNominalValues());
00594 initialGuess.set_x(x_init);
00595 Thyra::Vt_S(&*p_init,perturbedParamScaling);
00596 initialGuess.set_p(0,p_init);
00597
00598 solver.setInitialGuess(initialGuess);
00599 }
00600
00601
00602 solution_status = solver.solve();
00603
00604
00605 x_init = solver.getFinalPoint().get_x()->clone_v();
00606 p_init = solver.getFinalPoint().get_p(0)->clone_v();
00607
00608 *out
00609 << "\nrelVectorErr(x_perturb,x_opt) = " << Thyra::relVectorErr(*x_init,*x_opt)
00610 << "\nrelVectorErr(p_perturb,p_opt) = " << Thyra::relVectorErr(*p_init,*p_opt)
00611 << "\n";
00612
00613
00614 *out << "\n***\n*** Solving the perturbed inverse problem\n***\n";
00615
00616
00617
00618 solver.getSolver().set_output_context("inv");
00619
00620
00621
00622
00623 if ( N > 1 ) {
00624 TEST_FOR_EXCEPTION(
00625 !useOuterInverse, std::logic_error,
00626 "Error, if N > 1, you have to use the outer inverse objective function\n"
00627 "since each target vector will be different!" );
00628 RCP<const ProductVectorBase<Scalar> >
00629 x_opt_prod = rcp_dynamic_cast<const ProductVectorBase<Scalar> >(
00630 rcp_implicit_cast<const VectorBase<Scalar> >(x_opt), true
00631 );
00632 for ( int i = 0; i < N; ++i ) {
00633 rcp_dynamic_cast<Thyra::DefaultInverseModelEvaluator<Scalar> >(
00634 inverseThyraModels[i], true
00635 )->set_observationTarget(x_opt_prod->getVectorBlock(i));
00636 }
00637 }
00638 else if ( 1 == N ) {
00639 RCP<const ProductVectorBase<Scalar> >
00640 x_opt_prod = rcp_dynamic_cast<const ProductVectorBase<Scalar> >(
00641 rcp_implicit_cast<const VectorBase<Scalar> >(x_opt)
00642 );
00643 RCP<const VectorBase<Scalar> >
00644 x_opt_i =
00645 ( !is_null(x_opt_prod)
00646 ? x_opt_prod->getVectorBlock(0)
00647 : rcp_implicit_cast<const VectorBase<Scalar> >(x_opt)
00648 );
00649 if (useOuterInverse) {
00650 rcp_dynamic_cast<Thyra::DefaultInverseModelEvaluator<Scalar> >(
00651 inverseThyraModels[0], true
00652 )->set_observationTarget(x_opt_i);
00653 }
00654 else {
00655 epetraModel->set_q(
00656 Thyra::get_Epetra_Vector(*epetraModel->get_x_map(), x_opt_i)
00657 );
00658 }
00659 }
00660 else {
00661 TEST_FOR_EXCEPT("Error, should not get here!");
00662 }
00663
00664
00665 solver.setSolveMode(MoochoThyraSolver::SOLVE_MODE_OPTIMIZE);
00666
00667
00668 solver.setModel(thyraModel);
00669
00670
00671 {
00672 MEB::InArgs<Scalar> initialGuess = thyraModel->createInArgs();
00673 initialGuess.setArgs(thyraModel->getNominalValues());
00674 initialGuess.set_x(x_init);
00675 initialGuess.set_p(0,p_init);
00676
00677 solver.setInitialGuess(initialGuess);
00678 }
00679
00680
00681 solution_status = solver.solve();
00682 TEST_FOR_EXCEPT( solution_status != MoochoSolver::SOLVE_RETURN_SOLVED );
00683
00684
00685 *out << "\n***\n*** Testing the error in the inversion\n***\n";
00686
00687
00688
00689
00690 RCP<const VectorBase<Scalar> >
00691 x_inv = solver.getFinalPoint().get_x(),
00692 p_inv = solver.getFinalPoint().get_p(0);
00693
00694 *out << "\np_opt =\n" << Teuchos::describe(*p_opt,Teuchos::VERB_EXTREME);
00695 *out << "\np_inv =\n" << Teuchos::describe(*p_inv,Teuchos::VERB_EXTREME);
00696
00697 const Scalar
00698 x_err = Thyra::relVectorErr( *x_inv, *x_opt ),
00699 p_err = Thyra::relVectorErr( *p_inv, *p_opt );
00700
00701 const bool
00702 x_test_passed = ( x_err <= stateInvError ),
00703 p_test_passed = ( p_err <= paramInvError );
00704
00705 *out
00706 << "\nrelVectorErr(x_inv,x_opt) = " << x_err << " <= " << stateInvError
00707 << " : " << Thyra::passfail(x_test_passed)
00708 << "\nrelVectorErr(p_inv,p_opt) = " << p_err << " <= " << paramInvError
00709 << " : " << Thyra::passfail(p_test_passed)
00710 << "\n";
00711
00712
00713 solver.writeFinalSolution(out.get());
00714
00715
00716 lowsfCreator.writeParamsFile(*lowsFactory);
00717 solver.writeParamsFile();
00718
00719 TEST_FOR_EXCEPT(
00720 solution_status != MoochoSolver::SOLVE_RETURN_SOLVED
00721 );
00722
00723 }
00724 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success)
00725
00726 if(success)
00727 *out << "\nEnd Result: TEST PASSED" << endl;
00728 else
00729 *out << "\nEnd Result: TEST FAILED" << endl;
00730
00731 return ( success ? 0 : 1 );
00732
00733 }