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 "Thyra_MLPreconditionerFactory.hpp"
00031
00032 #ifndef TRILINOS_6
00033
00034 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
00035 #include "Thyra_EpetraLinearOp.hpp"
00036 #include "Thyra_DefaultPreconditioner.hpp"
00037 #include "ml_MultiLevelPreconditioner.h"
00038 #include "ml_MultiLevelOperator.h"
00039 #include "Epetra_RowMatrix.h"
00040 #include "Teuchos_dyn_cast.hpp"
00041
00042 using namespace Thyra ;
00043
00044
00045
00046
00047 MLPreconditionerFactory
00048 ::MLPreconditionerFactory(const RCP<ParameterList>& params)
00049 :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00050 paramList_(params)
00051 {}
00052
00053 MLPreconditionerFactory
00054 ::MLPreconditionerFactory(const EMLProblemType& probType,
00055 const ParameterList& revisions)
00056 :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00057 paramList_(reviseDefaultList(*defaultParameters(probType), revisions))
00058 {}
00059
00060 MLPreconditionerFactory
00061 ::MLPreconditionerFactory(const std::string& probType,
00062 const ParameterList& revisions)
00063 : epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00064 paramList_(reviseDefaultList(*defaultParameters(probType), revisions))
00065 {}
00066
00067 std::string MLPreconditionerFactory
00068 ::probToString(const EMLProblemType& probType) const
00069 {
00070 switch(probType)
00071 {
00072 case ML_Maxwell:
00073 return "maxwell";
00074 case ML_DomainDecomposition:
00075 return "DD";
00076 case ML_DomainDecompositionML:
00077 return "DD-ML";
00078 default:
00079 return "SA";
00080 }
00081 }
00082
00083 RCP<ParameterList> MLPreconditionerFactory
00084 ::defaultParameters(const EMLProblemType& probType) const
00085 {
00086 return defaultParameters(probToString(probType));
00087 }
00088
00089
00090 RCP<ParameterList> MLPreconditionerFactory
00091 ::defaultParameters(const std::string& probType) const
00092 {
00093 RCP<ParameterList> rtn = rcp(new ParameterList());
00094 int err = ML_Epetra::SetDefaults(probType, *rtn);
00095 TEST_FOR_EXCEPTION(err != 0, std::runtime_error,
00096 "unable to find default parameters for problem type "
00097 << probType);
00098 return rtn;
00099 }
00100
00101
00102
00103
00104 bool MLPreconditionerFactory::isCompatible( const LinearOpBase<double> &fwdOp ) const
00105 {
00106 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
00107 EOpTransp epetraFwdOpTransp;
00108 EApplyEpetraOpAs epetraFwdOpApplyAs;
00109 EAdjointEpetraOp epetraFwdOpAdjointSupport;
00110 double epetraFwdOpScalar;
00111 epetraFwdOpViewExtractor_->getEpetraOpView(
00112 Teuchos::rcp(&fwdOp,false)
00113 ,&epetraFwdOp,&epetraFwdOpTransp,
00114 &epetraFwdOpApplyAs,
00115 &epetraFwdOpAdjointSupport,
00116 &epetraFwdOpScalar
00117 );
00118 if( !dynamic_cast<const Epetra_RowMatrix*>(&*epetraFwdOp) )
00119 return false;
00120 return true;
00121 }
00122
00123 bool MLPreconditionerFactory::applySupportsConj(EConj conj) const
00124 {
00125 return true;
00126 }
00127
00128 bool MLPreconditionerFactory::applyTransposeSupportsConj(EConj conj) const
00129 {
00130 return false;
00131 }
00132
00133 Teuchos::RCP<PreconditionerBase<double> >
00134 MLPreconditionerFactory::createPrec() const
00135 {
00136 return Teuchos::rcp(new DefaultPreconditioner<double>());
00137 }
00138
00139 void MLPreconditionerFactory::initializePrec(
00140 const Teuchos::RCP<const LinearOpBase<double> > &fwdOp
00141 ,PreconditionerBase<double> *prec
00142 ,const ESupportSolveUse supportSolveUse
00143 ) const
00144 {
00145 using Teuchos::OSTab;
00146 using Teuchos::dyn_cast;
00147 using Teuchos::RefCountPtr;
00148 using Teuchos::null;
00149 using Teuchos::rcp;
00150 using Teuchos::rcp_dynamic_cast;
00151 using Teuchos::rcp_const_cast;
00152 using Teuchos::set_extra_data;
00153 using Teuchos::get_optional_extra_data;
00154 Teuchos::Time totalTimer(""), timer("");
00155 totalTimer.start(true);
00156 const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
00157 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00158 Teuchos::OSTab tab(out);
00159 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00160 *out << "\nEntering Thyra::MLPreconditionerFactory::initializePrec(...) ...\n";
00161 #ifdef _DEBUG
00162 TEST_FOR_EXCEPT(fwdOp.get()==NULL);
00163 TEST_FOR_EXCEPT(prec==NULL);
00164 #endif
00165
00166
00167
00168 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
00169 EOpTransp epetraFwdOpTransp;
00170 EApplyEpetraOpAs epetraFwdOpApplyAs;
00171 EAdjointEpetraOp epetraFwdOpAdjointSupport;
00172 double epetraFwdOpScalar;
00173 epetraFwdOpViewExtractor_->getEpetraOpView(
00174 fwdOp,&epetraFwdOp,&epetraFwdOpTransp,&epetraFwdOpApplyAs,&epetraFwdOpAdjointSupport,&epetraFwdOpScalar
00175 );
00176
00177 RCP<const Epetra_RowMatrix>
00178 epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true);
00179 TEST_FOR_EXCEPTION(
00180 epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error
00181 ,"Error, incorrect apply mode for an Epetra_RowMatrix"
00182 );
00183
00184
00185
00186 DefaultPreconditioner<double>
00187 *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
00188
00189
00190
00191 RCP<EpetraLinearOp>
00192 epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true);
00193
00194
00195
00196 Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> ml_precOp;
00197 if(epetra_precOp.get())
00198 ml_precOp = rcp_dynamic_cast<ML_Epetra::MultiLevelPreconditioner>(epetra_precOp->epetra_op(),true);
00199
00200
00201
00202 if(ml_precOp.get()) {
00203
00204
00205 }
00206
00207
00208
00209 const bool startingOver = (ml_precOp.get() == NULL);
00210 if(startingOver)
00211 {
00212 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00213 *out << "\nCreating the initial ML_Epetra::MultiLevelPreconditioner object...\n";
00214 timer.start(true);
00215
00216 ml_precOp = rcp(new ML_Epetra::MultiLevelPreconditioner(*epetraFwdRowMat,
00217 *paramList_));
00218
00219 timer.stop();
00220 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00221 *OSTab(out).getOStream() <<"\n=> Creation time = "<<timer.totalElapsedTime()<<" sec\n";
00222
00223
00224
00225
00226
00227
00228
00229 if(paramList_.get())
00230 TEST_FOR_EXCEPT(0!=ml_precOp->SetParameterList(*paramList_));
00231
00232
00233 }
00234
00235
00236
00237 set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ml_precOp),
00238 Teuchos::POST_DESTROY, false);
00239
00240
00241
00242 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00243 *out << "\nComputing the factorization of the preconditioner ...\n";
00244 timer.start(true);
00245 TEST_FOR_EXCEPT(0!=ml_precOp->ComputePreconditioner());
00246 timer.stop();
00247 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00248 *OSTab(out).getOStream() <<"\n=> Factorization time = "<<timer.totalElapsedTime()<<" sec\n";
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 set_extra_data(fwdOp, "IFPF::fwdOp", Teuchos::inOutArg(ml_precOp),
00259 Teuchos::POST_DESTROY, false);
00260
00261
00262
00263 if(startingOver) {
00264 epetra_precOp = rcp(new EpetraLinearOp);
00265 }
00266 epetra_precOp->initialize(
00267 ml_precOp
00268 ,epetraFwdOpTransp
00269 ,EPETRA_OP_APPLY_APPLY_INVERSE
00270 ,EPETRA_OP_ADJOINT_UNSUPPORTED
00271 );
00272
00273
00274
00275 defaultPrec->initializeUnspecified(
00276 Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp)
00277 );
00278 totalTimer.stop();
00279 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00280 *out
00281 << "\nTotal time = "<<totalTimer.totalElapsedTime()<<" sec\n"
00282 << "\nLeaving Thyra::MLPreconditionerFactory::initializePrec(...) ...\n";
00283 }
00284
00285 void MLPreconditionerFactory::uninitializePrec(
00286 PreconditionerBase<double> *prec
00287 ,Teuchos::RCP<const LinearOpBase<double> > *fwdOp
00288 ,ESupportSolveUse *supportSolveUse
00289 ) const
00290 {
00291 TEST_FOR_EXCEPT(true);
00292 }
00293
00294
00295
00296 void MLPreconditionerFactory::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList)
00297 {
00298 TEST_FOR_EXCEPT(paramList.get()==NULL);
00299
00300
00301 paramList_ = paramList;
00302 }
00303
00304 Teuchos::RCP<Teuchos::ParameterList>
00305 MLPreconditionerFactory::getNonconstParameterList()
00306 {
00307 return paramList_;
00308 }
00309
00310 Teuchos::RCP<Teuchos::ParameterList>
00311 MLPreconditionerFactory::unsetParameterList()
00312 {
00313 Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_;
00314 paramList_ = Teuchos::null;
00315 return _paramList;
00316 }
00317
00318 Teuchos::RCP<const Teuchos::ParameterList>
00319 MLPreconditionerFactory::getParameterList() const
00320 {
00321 return paramList_;
00322 }
00323
00324
00325
00326
00327 std::string MLPreconditionerFactory::description() const
00328 {
00329 std::ostringstream oss;
00330 oss << "Thyra::MLPreconditionerFactory";
00331 return oss.str();
00332 }
00333
00334 RCP<ParameterList> MLPreconditionerFactory
00335 ::reviseDefaultList(const ParameterList& defaults, const ParameterList& revisions) const
00336 {
00337 RCP<ParameterList> rtn = rcp(new ParameterList(defaults));
00338
00339 for (ParameterList::ConstIterator i=revisions.begin(); i != revisions.end(); i++)
00340 {
00341 rtn->setEntry(revisions.name(i), revisions.entry(i));
00342 }
00343 return rtn;
00344 }
00345
00346 #endif