GLpApp_AdvDiffReactOptModel.cpp

Go to the documentation of this file.
00001 #include "GLpApp_AdvDiffReactOptModel.hpp"
00002 #include "Epetra_SerialComm.h"
00003 #include "Epetra_CrsMatrix.h"
00004 #include "Teuchos_ScalarTraits.hpp"
00005 #include "Teuchos_VerboseObject.hpp"
00006 #include "Teuchos_TimeMonitor.hpp"
00007 
00008 #ifdef HAVE_EPETRAEXT_THYRA
00009 // For orthogonalization of the basis B_bar
00010 #include "sillyModifiedGramSchmidt.hpp" // This is just an example!
00011 #include "Thyra_EpetraThyraWrappers.hpp"
00012 #include "Thyra_MultiVectorStdOps.hpp"
00013 #include "Thyra_SpmdVectorSpaceBase.hpp"
00014 #endif // HAVE_EPETRAEXT_THYRA
00015 
00016 //#define GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00017 
00018 namespace {
00019 
00020 Teuchos::RefCountPtr<Teuchos::Time>
00021   initalizationTimer    = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Init"),
00022   evalTimer             = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval"),
00023   p_bar_Timer           = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:p_bar"),
00024   R_p_bar_Timer         = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:R_p_bar"),
00025   f_Timer               = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:f"),
00026   g_Timer               = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:g"),
00027   W_Timer               = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:W"),
00028   DfDp_Timer            = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:DfDp"),
00029   DgDx_Timer            = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:DgDx"),
00030   DgDp_Timer            = Teuchos::TimeMonitor::getNewTimer("AdvDiffReact:Eval:DgDp");
00031 
00032 inline double sqr( const double& s ) { return s*s; }
00033 
00034 inline double dot( const Epetra_Vector &x, const Epetra_Vector &y )
00035 {
00036   double dot[1];
00037   x.Dot(y,dot);
00038   return dot[0];
00039 }
00040 
00041 } // namespace
00042 
00043 namespace GLpApp {
00044 
00045 AdvDiffReactOptModel::AdvDiffReactOptModel(
00046   const Teuchos::RefCountPtr<const Epetra_Comm>  &comm
00047   ,const double                                  beta
00048   ,const double                                  len_x     // Ignored if meshFile is *not* empty
00049   ,const double                                  len_y     // Ignored if meshFile is *not* empty
00050   ,const int                                     local_nx  // Ignored if meshFile is *not* empty
00051   ,const int                                     local_ny  // Ignored if meshFile is *not* empty
00052   ,const char                                    meshFile[]
00053   ,const int                                     np
00054   ,const double                                  x0
00055   ,const double                                  p0
00056   ,const double                                  reactionRate
00057   ,const bool                                    normalizeBasis
00058   )
00059   :np_(np)
00060 {
00061   Teuchos::TimeMonitor initalizationTimerMonitor(*initalizationTimer);
00062 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00063   Teuchos::RefCountPtr<Teuchos::FancyOStream>
00064     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00065   Teuchos::OSTab tab(out);
00066   *out << "\nEntering AdvDiffReactOptModel::AdvDiffReactOptModel(...) ...\n";
00067 #endif
00068   //
00069   // Initalize the data pool object
00070   //
00071   dat_ = Teuchos::rcp(new GLpApp::GLpYUEpetraDataPool(comm,beta,len_x,len_y,local_nx,local_ny,meshFile,false));
00072   //
00073   // Get the maps
00074   //
00075   map_x_ = Teuchos::rcp(new Epetra_Map(dat_->getA()->OperatorDomainMap()));
00076   map_p_.resize(Np_);
00077   map_p_[p_rx_idx] = Teuchos::rcp(new Epetra_Map(1,1,0,*comm));
00078   map_p_bar_ = Teuchos::rcp(new Epetra_Map(dat_->getB()->OperatorDomainMap()));
00079   map_f_ = Teuchos::rcp(new Epetra_Map(dat_->getA()->OperatorRangeMap()));
00080   map_g_ = Teuchos::rcp(new Epetra_Map(1,1,0,*comm));
00081   //
00082   // Initialize the basis matrix for p such that p_bar = B_bar * p
00083   //
00084   if( np_ > 0 ) {
00085     //
00086     // Create a sine series basis for y (the odd part of a Fourier series basis)
00087     //
00088     const Epetra_SerialDenseMatrix &ipcoords = *dat_->getipcoords();
00089     const Epetra_IntSerialDenseVector &pindx = *dat_->getpindx();
00090     Epetra_Map overlapmap(-1,pindx.M(),const_cast<int*>(pindx.A()),1,*comm);
00091     const double pi = 2.0 * std::asin(1.0);
00092 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00093     *out << "\npi="<<pi<<"\n";
00094 #endif
00095     map_p_[p_bndy_idx] = Teuchos::rcp(new Epetra_Map(np_,np_,0,*comm));
00096     B_bar_ = Teuchos::rcp(new Epetra_MultiVector(*map_p_bar_,np_));
00097     (*B_bar_)(0)->PutScalar(1.0); // First column is all ones!
00098     if( np_ > 1 ) {
00099       const int numBndyNodes        = map_p_bar_->NumMyElements();
00100       const int *bndyNodeGlobalIDs  = map_p_bar_->MyGlobalElements();
00101       for( int i = 0; i < numBndyNodes; ++i ) {
00102         const int global_id = bndyNodeGlobalIDs[i];
00103         const int local_id = overlapmap.LID(bndyNodeGlobalIDs[i]);
00104         const double x = ipcoords(local_id,0), y = ipcoords(local_id,1);
00105         double z = -1.0, L = -1.0;
00106         if( x < 1e-10 || len_x - 1e-10 < x ) {
00107           z = y;
00108           L = len_y;
00109         }
00110         else {
00111           z = x;
00112           L = len_x;
00113         }
00114 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00115         *out << "\ni="<<i<<",global_id="<<global_id<<",local_id="<<local_id<<",x="<<x<<",y="<<y<<",z="<<z<<"\n";
00116 #endif
00117         for( int j = 1; j < np_; ++j ) {
00118           (*B_bar_)[j][i] = std::sin(j*pi*z/L);
00119 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00120           *out << "\nB("<<i<<","<<j<<")="<<(*B_bar_)[j][i]<<"\n";
00121 #endif
00122         }
00123       }
00124       if(normalizeBasis) {
00125 #ifdef HAVE_EPETRAEXT_THYRA
00126         //
00127         // Use modified Gram-Schmidt to create an orthonormal version of B_bar!
00128         //
00129         Teuchos::RefCountPtr<Thyra::MultiVectorBase<double> >
00130           thyra_B_bar = Thyra::create_MultiVector(
00131             B_bar_
00132             ,Thyra::create_VectorSpace(Teuchos::rcp(new Epetra_Map(*map_p_bar_)))
00133             ,Thyra::create_VectorSpace(Teuchos::rcp(new Epetra_Map(*map_p_[p_bndy_idx])))
00134             ),
00135           thyra_fact_R;
00136         sillyModifiedGramSchmidt(&*thyra_B_bar,&thyra_fact_R);
00137         Thyra::scale(double(numBndyNodes)/double(np_),&*thyra_B_bar); // Each row should sum to around one!
00138         // We just discard the "R" factory thyra_fact_R ...
00139 #else // HAVE_EPETRAEXT_THYRA
00140         TEST_FOR_EXCEPTION(
00141           true,std::logic_error
00142           ,"Error, can not normalize basis since we do not have Thyra support enabled!"
00143           );
00144 #endif // HAVE_EPETRAEXT_THYRA
00145       }
00146     }
00147 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00148     *out << "\nB_bar =\n\n";
00149     B_bar_->Print(*Teuchos::OSTab(out).getOStream());
00150 #endif
00151   }
00152   else {
00153     // B_bar = I implicitly!
00154     map_p_[p_bndy_idx] = map_p_bar_;
00155   }
00156   //
00157   // Create vectors
00158   //
00159   x0_ = Teuchos::rcp(new Epetra_Vector(*map_x_));
00160   //xL_ = Teuchos::rcp(new Epetra_Vector(*map_x_));
00161   //xU_ = Teuchos::rcp(new Epetra_Vector(*map_x_));
00162   p0_.resize(Np_);
00163   p0_[p_bndy_idx] = Teuchos::rcp(new Epetra_Vector(*map_p_[p_bndy_idx]));
00164   p0_[p_rx_idx] = Teuchos::rcp(new Epetra_Vector(*map_p_[p_rx_idx]));
00165   pL_.resize(Np_);
00166   pU_.resize(Np_);
00167   //pL_ = Teuchos::rcp(new Epetra_Vector(*map_p_));
00168   //pU_ = Teuchos::rcp(new Epetra_Vector(*map_p_));
00169   //
00170   // Initialize the vectors
00171   //
00172   x0_->PutScalar(x0);
00173   p0_[p_bndy_idx]->PutScalar(p0);
00174   p0_[p_rx_idx]->PutScalar(reactionRate);
00175   //
00176   // Initialize the graph for W
00177   //
00178   dat_->computeNpy(x0_);
00179   //if(dumpAll) { *out << "\nA =\n"; { Teuchos::OSTab tab(out); dat_->getA()->Print(*out); } }
00180   //if(dumpAll) { *out << "\nNpy =\n"; {  Teuchos::OSTab tab(out); dat_->getNpy()->Print(*out); } }
00181   W_graph_ = Teuchos::rcp(new Epetra_CrsGraph(dat_->getA()->Graph())); // Assume A and Npy have same graph!
00182   //
00183   // Get default objective matching vector q
00184   //
00185   q_ = Teuchos::rcp(new Epetra_Vector(*(*dat_->getq())(0))); // From Epetra_FEVector to Epetra_Vector!
00186   //
00187   isInitialized_ = true;
00188 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00189   *out << "\nLeaving AdvDiffReactOptModel::AdvDiffReactOptModel(...) ...\n";
00190 #endif
00191 }
00192 
00193 void AdvDiffReactOptModel::set_q( Teuchos::RefCountPtr<const Epetra_Vector> const& q )
00194 {
00195   q_ = q;
00196 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00197   Teuchos::RefCountPtr<Teuchos::FancyOStream>
00198     dout = Teuchos::VerboseObjectBase::getDefaultOStream();
00199   Teuchos::OSTab dtab(dout);
00200   *dout << "\nIn AdvDiffReactOptModel::set_q(q):  q =\n\n";
00201   q_->Print(*Teuchos::OSTab(dout).getOStream());
00202 #endif
00203 }
00204 
00205 // Overridden from EpetraExt::ModelEvaluator
00206 
00207 Teuchos::RefCountPtr<const Epetra_Map>
00208 AdvDiffReactOptModel::get_x_map() const
00209 {
00210   return map_x_;
00211 }
00212 
00213 Teuchos::RefCountPtr<const Epetra_Map>
00214 AdvDiffReactOptModel::get_f_map() const
00215 {
00216   return map_x_;
00217 }
00218 
00219 Teuchos::RefCountPtr<const Epetra_Map>
00220 AdvDiffReactOptModel::get_p_map(int l) const
00221 {
00222   TEST_FOR_EXCEPT(!(0<=l<=Np_));
00223   return map_p_[l];
00224 }
00225 
00226 Teuchos::RefCountPtr<const Epetra_Map>
00227 AdvDiffReactOptModel::get_g_map(int j) const
00228 {
00229   TEST_FOR_EXCEPT(j!=0);
00230   return map_g_;
00231 }
00232 
00233 Teuchos::RefCountPtr<const Epetra_Vector>
00234 AdvDiffReactOptModel::get_x_init() const
00235 {
00236   return x0_;
00237 }
00238 
00239 Teuchos::RefCountPtr<const Epetra_Vector>
00240 AdvDiffReactOptModel::get_p_init(int l) const
00241 {
00242   TEST_FOR_EXCEPT(!(0<=l<=Np_));
00243   return p0_[l];
00244 }
00245 
00246 Teuchos::RefCountPtr<const Epetra_Vector>
00247 AdvDiffReactOptModel::get_x_lower_bounds() const
00248 {
00249   return xL_;
00250 }
00251 
00252 Teuchos::RefCountPtr<const Epetra_Vector>
00253 AdvDiffReactOptModel::get_x_upper_bounds() const
00254 {
00255   return xU_;
00256 }
00257 
00258 Teuchos::RefCountPtr<const Epetra_Vector>
00259 AdvDiffReactOptModel::get_p_lower_bounds(int l) const
00260 {
00261   TEST_FOR_EXCEPT(!(0<=l<=Np_));
00262   return pL_[l];
00263 }
00264 
00265 Teuchos::RefCountPtr<const Epetra_Vector>
00266 AdvDiffReactOptModel::get_p_upper_bounds(int l) const
00267 {
00268   TEST_FOR_EXCEPT(!(0<=l<=Np_));
00269   return pU_[l];
00270 }
00271 
00272 Teuchos::RefCountPtr<Epetra_Operator>
00273 AdvDiffReactOptModel::create_W() const
00274 {
00275   return Teuchos::rcp(new Epetra_CrsMatrix(::Copy,*W_graph_));
00276 }
00277 
00278 Teuchos::RefCountPtr<Epetra_Operator>
00279 AdvDiffReactOptModel::create_DfDp_op(int l) const
00280 {
00281   TEST_FOR_EXCEPT(l!=0);
00282   return Teuchos::rcp(new Epetra_CrsMatrix(::Copy,dat_->getB()->Graph()));
00283   // See DfDp in evalModel(...) below for details
00284 }
00285 
00286 EpetraExt::ModelEvaluator::InArgs
00287 AdvDiffReactOptModel::createInArgs() const
00288 {
00289   InArgsSetup inArgs;
00290   inArgs.setModelEvalDescription(this->description());
00291   inArgs.set_Np(2);
00292   inArgs.setSupports(IN_ARG_x,true);
00293   return inArgs;
00294 }
00295 
00296 EpetraExt::ModelEvaluator::OutArgs
00297 AdvDiffReactOptModel::createOutArgs() const
00298 {
00299   OutArgsSetup outArgs;
00300   outArgs.setModelEvalDescription(this->description());
00301   outArgs.set_Np_Ng(2,1);
00302   outArgs.setSupports(OUT_ARG_f,true);
00303   outArgs.setSupports(OUT_ARG_W,true);
00304   outArgs.set_W_properties(
00305     DerivativeProperties(
00306       DERIV_LINEARITY_NONCONST
00307       ,DERIV_RANK_FULL
00308       ,true // supportsAdjoint
00309       )
00310     );
00311   outArgs.setSupports(
00312     OUT_ARG_DfDp,0
00313     ,( np_ > 0
00314        ? DerivativeSupport(DERIV_MV_BY_COL)
00315        : DerivativeSupport(DERIV_LINEAR_OP,DERIV_MV_BY_COL)
00316       )
00317     );
00318   outArgs.set_DfDp_properties(
00319     0,DerivativeProperties(
00320       DERIV_LINEARITY_CONST
00321       ,DERIV_RANK_DEFICIENT
00322       ,true // supportsAdjoint
00323       )
00324     );
00325   outArgs.setSupports(OUT_ARG_DgDx,0,DERIV_TRANS_MV_BY_ROW);
00326   outArgs.set_DgDx_properties(
00327     0,DerivativeProperties(
00328       DERIV_LINEARITY_NONCONST
00329       ,DERIV_RANK_DEFICIENT
00330       ,true // supportsAdjoint
00331       )
00332     );
00333   outArgs.setSupports(OUT_ARG_DgDp,0,0,DERIV_TRANS_MV_BY_ROW);
00334   outArgs.set_DgDp_properties(
00335     0,0,DerivativeProperties(
00336       DERIV_LINEARITY_NONCONST
00337       ,DERIV_RANK_DEFICIENT
00338       ,true // supportsAdjoint
00339       )
00340     );
00341   return outArgs;
00342 }
00343 
00344 void AdvDiffReactOptModel::evalModel( const InArgs& inArgs, const OutArgs& outArgs ) const
00345 {
00346   Teuchos::TimeMonitor evalTimerMonitor(*evalTimer);
00347 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00348   Teuchos::RefCountPtr<Teuchos::FancyOStream>
00349     dout = Teuchos::VerboseObjectBase::getDefaultOStream();
00350   Teuchos::OSTab dtab(dout);
00351   *dout << "\nEntering AdvDiffReactOptModel::evalModel(...) ...\n";
00352 #endif
00353   using Teuchos::dyn_cast;
00354   using Teuchos::rcp_dynamic_cast;
00355   //
00356   Teuchos::RefCountPtr<Teuchos::FancyOStream> out = this->getOStream();
00357   const bool trace = ( static_cast<int>(this->getVerbLevel()) >= static_cast<int>(Teuchos::VERB_LOW) );
00358   const bool dumpAll = ( static_cast<int>(this->getVerbLevel()) >= static_cast<int>(Teuchos::VERB_EXTREME) );
00359   //
00360   Teuchos::OSTab tab(out);
00361   if(out.get() && trace) *out << "\n*** Entering AdvDiffReactOptModel::evalModel(...) ...\n"; 
00362   //
00363   // Get the input arguments
00364   //
00365   const Epetra_Vector *p_in = inArgs.get_p(p_bndy_idx).get();
00366   const Epetra_Vector &p = (p_in ? *p_in : *p0_[p_bndy_idx]);
00367   const Epetra_Vector *rx_vec_in = inArgs.get_p(p_rx_idx).get();
00368   const double        reactionRate = ( rx_vec_in ? (*rx_vec_in)[0] : (*p0_[p_rx_idx])[0] );
00369   const Epetra_Vector &x = *inArgs.get_x();
00370 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00371     *dout << "\nx =\n\n";
00372     x.Print(*Teuchos::OSTab(dout).getOStream());
00373     *dout << "\np =\n\n";
00374     p.Print(*Teuchos::OSTab(dout).getOStream());
00375 #endif
00376   //
00377   // Get the output arguments
00378   //
00379   Epetra_Vector       *f_out = outArgs.get_f().get();
00380   Epetra_Vector       *g_out = outArgs.get_g(0).get();
00381   Epetra_Operator     *W_out = outArgs.get_W().get();
00382   Derivative          DfDp_out = outArgs.get_DfDp(0);
00383   Epetra_MultiVector  *DgDx_trans_out = get_DgDx_mv(0,outArgs,DERIV_TRANS_MV_BY_ROW).get();
00384   Epetra_MultiVector  *DgDp_trans_out = get_DgDp_mv(0,0,outArgs,DERIV_TRANS_MV_BY_ROW).get();
00385   //
00386   // Precompute some shared quantities
00387   //
00388   // p_bar = B_bar*p
00389   Teuchos::RefCountPtr<const Epetra_Vector> p_bar;
00390   if(np_ > 0) {
00391     Teuchos::TimeMonitor p_bar_TimerMonitor(*p_bar_Timer);
00392     Teuchos::RefCountPtr<Epetra_Vector> _p_bar;
00393     _p_bar = Teuchos::rcp(new Epetra_Vector(*map_p_bar_));
00394     _p_bar->Multiply('N','N',1.0,*B_bar_,p,0.0);
00395     p_bar = _p_bar;
00396   }
00397   else {
00398     p_bar = Teuchos::rcp(&p,false);
00399   }
00400   // R_p_bar = R*p_bar = R*(B_bar*p)
00401   Teuchos::RefCountPtr<const Epetra_Vector> R_p_bar;
00402   if( g_out || DgDp_trans_out ) {
00403     Teuchos::TimeMonitor R_p_bar_TimerMonitor(*R_p_bar_Timer);
00404       Teuchos::RefCountPtr<Epetra_Vector>
00405       _R_p_bar = Teuchos::rcp(new Epetra_Vector(*map_p_bar_));
00406     dat_->getR()->Multiply(false,*p_bar,*_R_p_bar);
00407     R_p_bar = _R_p_bar;
00408   }
00409   //
00410   // Compute the functions
00411   //
00412   if(f_out) {
00413     //
00414     // f = A*x + reationRate*Ny(x) + B*(B_bar*p)
00415     //
00416     Teuchos::TimeMonitor f_TimerMonitor(*f_Timer);
00417     Epetra_Vector &f = *f_out;
00418     Epetra_Vector Ax(*map_f_);
00419     dat_->getA()->Multiply(false,x,Ax);
00420     f.Update(1.0,Ax,0.0);
00421     if(reactionRate!=0.0) {
00422       dat_->computeNy(Teuchos::rcp(&x,false));
00423       f.Update(reactionRate,*dat_->getNy(),1.0);
00424     }
00425     Epetra_Vector Bp(*map_f_);
00426     dat_->getB()->Multiply(false,*p_bar,Bp);
00427     f.Update(1.0,Bp,-1.0,*dat_->getb(),1.0);
00428   }
00429   if(g_out) {
00430     //
00431     // g = 0.5 * (x-q)'*H*(x-q) + 0.5*regBeta*(B_bar*p)'*R*(B_bar*p)
00432     //
00433     Teuchos::TimeMonitor g_TimerMonitor(*g_Timer);
00434     Epetra_Vector &g = *g_out;
00435     Epetra_Vector xq(x);
00436     xq.Update(-1.0, *q_, 1.0);
00437     Epetra_Vector Hxq(x);
00438     dat_->getH()->Multiply(false,xq,Hxq);
00439     g[0] = 0.5*dot(xq,Hxq) + 0.5*dat_->getbeta()*dot(*p_bar,*R_p_bar);
00440 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00441     *dout << "q =\n\n";
00442     q_->Print(*Teuchos::OSTab(dout).getOStream());
00443     *dout << "x =\n\n";
00444     x.Print(*Teuchos::OSTab(dout).getOStream());
00445     *dout << "x-q =\n\n";
00446     xq.Print(*Teuchos::OSTab(dout).getOStream());
00447     *dout << "H*(x-q) =\n\n";
00448     Hxq.Print(*Teuchos::OSTab(dout).getOStream());
00449     *dout << "0.5*dot(xq,Hxq) = " << (0.5*dot(xq,Hxq)) << "\n";
00450     *dout << "0.5*regBeta*(B_bar*p)'*R*(B_bar*p) = " << (0.5*dat_->getbeta()*dot(*p_bar,*R_p_bar)) << "\n";
00451 #endif
00452   }
00453   if(W_out) {
00454     //
00455     // W = A + reationRate*Npy(x)
00456     //
00457     Teuchos::TimeMonitor W_TimerMonitor(*W_Timer);
00458     Epetra_CrsMatrix &DfDx = dyn_cast<Epetra_CrsMatrix>(*W_out);
00459     if(reactionRate!=0.0)
00460       dat_->computeNpy(Teuchos::rcp(&x,false));
00461     Teuchos::RefCountPtr<Epetra_CrsMatrix>
00462       dat_A = dat_->getA(),
00463       dat_Npy = dat_->getNpy();
00464     const int numMyRows = dat_A->NumMyRows();
00465     for( int i = 0; i < numMyRows; ++i ) {
00466       int dat_A_num_row_entries=0; double *dat_A_row_vals=0; int *dat_A_row_inds=0;
00467       dat_A->ExtractMyRowView(i,dat_A_num_row_entries,dat_A_row_vals,dat_A_row_inds);
00468       int DfDx_num_row_entries=0; double *DfDx_row_vals=0; int *DfDx_row_inds=0;
00469       DfDx.ExtractMyRowView(i,DfDx_num_row_entries,DfDx_row_vals,DfDx_row_inds);
00470 #ifdef TEUCHOS_DEBUG
00471       TEST_FOR_EXCEPT(DfDx_num_row_entries!=dat_A_num_row_entries);
00472 #endif
00473       if(reactionRate!=0.0) {
00474         int dat_Npy_num_row_entries=0; double *dat_Npy_row_vals=0; int *dat_Npy_row_inds=0;
00475         dat_Npy->ExtractMyRowView(i,dat_Npy_num_row_entries,dat_Npy_row_vals,dat_Npy_row_inds);
00476 #ifdef TEUCHOS_DEBUG
00477         TEST_FOR_EXCEPT(dat_A_num_row_entries!=dat_Npy_num_row_entries);
00478 #endif
00479         for(int k = 0; k < DfDx_num_row_entries; ++k) {
00480 #ifdef TEUCHOS_DEBUG
00481           TEST_FOR_EXCEPT(dat_A_row_inds[k]!=dat_Npy_row_inds[k]||dat_A_row_inds[k]!=DfDx_row_inds[k]);
00482 #endif
00483           DfDx_row_vals[k] = dat_A_row_vals[k] + reactionRate * dat_Npy_row_vals[k];
00484         }
00485       }
00486       else {
00487         for(int k = 0; k < DfDx_num_row_entries; ++k) {
00488 #ifdef TEUCHOS_DEBUG
00489           TEST_FOR_EXCEPT(dat_A_row_inds[k]!=DfDx_row_inds[k]);
00490 #endif
00491           DfDx_row_vals[k] = dat_A_row_vals[k];
00492         }
00493       }
00494     }
00495   }
00496   if(!DfDp_out.isEmpty()) {
00497     if(out.get() && trace) *out << "\nComputing DfDp ...\n"; 
00498     //
00499     // DfDp = B*B_bar
00500     //
00501     Teuchos::TimeMonitor DfDp_TimerMonitor(*DfDp_Timer);
00502     Epetra_CrsMatrix   *DfDp_op = NULL;
00503     Epetra_MultiVector *DfDp_mv = NULL;
00504     if(out.get() && dumpAll)
00505     { *out << "\nB =\n"; { Teuchos::OSTab tab(out); dat_->getB()->Print(*out); } }
00506     if(DfDp_out.getLinearOp().get()) {
00507       DfDp_op = &dyn_cast<Epetra_CrsMatrix>(*DfDp_out.getLinearOp());
00508     }
00509     else {
00510       DfDp_mv = &*DfDp_out.getDerivativeMultiVector().getMultiVector();
00511       DfDp_mv->PutScalar(0.0);
00512     }
00513     Teuchos::RefCountPtr<Epetra_CrsMatrix>
00514       dat_B = dat_->getB();
00515     if(np_ > 0) {
00516       //
00517       // We only support a Multi-vector form when we have a non-idenity basis
00518       // matrix B_bar for p!
00519       //
00520       TEST_FOR_EXCEPT(DfDp_mv==NULL);
00521       dat_B->Multiply(false,*B_bar_,*DfDp_mv);
00522     }
00523     else {
00524       //
00525       // Note: We copy from B every time in order to be safe.  Note that since
00526       // the client knows that B is constant (sense we told them so in
00527       // createOutArgs()) then it should only compute this matrix once and keep
00528       // it if it is smart.
00529       //
00530       // Note: We support both the CrsMatrix and MultiVector form of this object
00531       // to make things easier for the client.
00532       //
00533       if(DfDp_op) {
00534         const int numMyRows = dat_B->NumMyRows();
00535         for( int i = 0; i < numMyRows; ++i ) {
00536           int dat_B_num_row_entries=0; double *dat_B_row_vals=0; int *dat_B_row_inds=0;
00537           dat_B->ExtractMyRowView(i,dat_B_num_row_entries,dat_B_row_vals,dat_B_row_inds);
00538           int DfDp_num_row_entries=0; double *DfDp_row_vals=0; int *DfDp_row_inds=0;
00539           DfDp_op->ExtractMyRowView(i,DfDp_num_row_entries,DfDp_row_vals,DfDp_row_inds);
00540 #ifdef TEUCHOS_DEBUG
00541           TEST_FOR_EXCEPT(DfDp_num_row_entries!=dat_B_num_row_entries);
00542 #endif
00543           for(int k = 0; k < DfDp_num_row_entries; ++k) {
00544 #ifdef TEUCHOS_DEBUG
00545             TEST_FOR_EXCEPT(dat_B_row_inds[k]!=DfDp_row_inds[k]);
00546 #endif
00547             DfDp_row_vals[k] = dat_B_row_vals[k];
00548           }
00549           // ToDo: The above code should be put in a utility function called copyValues(...)!
00550         }
00551       }
00552       else if(DfDp_mv) {
00553         // We must do a mat-vec to get this since we can't just copy out the
00554         // matrix entries since the domain map may be different from the
00555         // column map!  I learned this the very very hard way!  I am using
00556         // Thyra wrappers here since I can't figure out for the life of me how
00557         // to do this cleanly with Epetra alone!
00558         Teuchos::RefCountPtr<Epetra_Vector>
00559           etaVec = Teuchos::rcp(new Epetra_Vector(*map_p_bar_));
00560         Teuchos::RefCountPtr<const Thyra::SpmdVectorSpaceBase<double> >
00561           space_p_bar = Thyra::create_VectorSpace(Teuchos::rcp(new Epetra_Map(*map_p_bar_)));
00562         Teuchos::RefCountPtr<Thyra::VectorBase<double> >
00563           thyra_etaVec = Thyra::create_Vector(etaVec,space_p_bar);
00564         for( int i = 0; i < map_p_bar_->NumGlobalElements(); ++i ) {
00565           Thyra::assign(&*thyra_etaVec,0.0);
00566           Thyra::set_ele(i,1.0,&*thyra_etaVec);
00567           dat_B->Multiply(false,*etaVec,*(*DfDp_mv)(i));
00568         };
00569       }
00570     }
00571 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00572     if(DfDp_op) {
00573       *dout << "\nDfDp_op =\n\n";
00574       DfDp_op->Print(*Teuchos::OSTab(dout).getOStream());
00575     }
00576     if(DfDp_mv) {
00577       *dout << "\nDfDp_mv =\n\n";
00578       DfDp_mv->Print(*Teuchos::OSTab(dout).getOStream());
00579     }
00580 #endif
00581   }
00582   if(DgDx_trans_out) {
00583     //
00584     // DgDx' = H*(x-q)
00585     //
00586     Teuchos::TimeMonitor DgDx_TimerMonitor(*DgDx_Timer);
00587     Epetra_Vector &DgDx_trans = *(*DgDx_trans_out)(0);
00588     Epetra_Vector xq(x);
00589     xq.Update(-1.0,*q_,1.0);
00590     dat_->getH()->Multiply(false,xq,DgDx_trans);
00591 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00592     *dout << "q =\n\n";
00593     q_->Print(*Teuchos::OSTab(dout).getOStream());
00594     *dout << "x =\n\n";
00595     x.Print(*Teuchos::OSTab(dout).getOStream());
00596     *dout << "x-q =\n\n";
00597     xq.Print(*Teuchos::OSTab(dout).getOStream());
00598     *dout << "DgDx_trans = H*(x-q) =\n\n";
00599     DgDx_trans.Print(*Teuchos::OSTab(dout).getOStream());
00600 #endif
00601   }
00602   if(DgDp_trans_out) {
00603     //
00604     // DgDp' = regBeta*B_bar'*(R*(B_bar*p))
00605     //
00606     Teuchos::TimeMonitor DgDp_TimerMonitor(*DgDp_Timer);
00607     Epetra_Vector &DgDp_trans = *(*DgDp_trans_out)(0);
00608     if(np_ > 0) {
00609       DgDp_trans.Multiply('T','N',dat_->getbeta(),*B_bar_,*R_p_bar,0.0);
00610     }
00611     else {
00612       DgDp_trans.Update(dat_->getbeta(),*R_p_bar,0.0);
00613     }
00614 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00615     *dout << "\nR_p_bar =\n\n";
00616     R_p_bar->Print(*Teuchos::OSTab(dout).getOStream());
00617     if(B_bar_.get()) {
00618       *dout << "\nB_bar =\n\n";
00619       B_bar_->Print(*Teuchos::OSTab(dout).getOStream());
00620     }
00621     *dout << "\nDgDp_trans =\n\n";
00622     DgDp_trans.Print(*Teuchos::OSTab(dout).getOStream());
00623 #endif
00624   }
00625   if(out.get() && trace) *out << "\n*** Leaving AdvDiffReactOptModel::evalModel(...) ...\n"; 
00626 #ifdef GLPAPP_ADVDIFFREACT_OPTMODEL_DUMP_STUFF
00627   *dout << "\nLeaving AdvDiffReactOptModel::evalModel(...) ...\n";
00628 #endif
00629 }
00630 
00631 } // namespace GLpApp

Generated on Thu Sep 18 12:31:44 2008 for EpetraExt by doxygen 1.3.9.1