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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "Teuchos_TestForException.hpp"
00043 #include "Teuchos_ParameterList.hpp"
00044 #ifdef HAVE_TEUCHOS_EXTENDED
00045 #include "Teuchos_XMLParameterListHelpers.hpp"
00046 #endif
00047
00048 #include "NOX_Common.H"
00049 #include "NOX_StatusTest_Generic.H"
00050 #include "NOX_StatusTest_Factory.H"
00051 #include "NOX_Utils.H"
00052 #include "NOX_Abstract_Vector.H"
00053 #include "NOX_Abstract_Group.H"
00054
00055
00056 #include "NOX_StatusTest_Combo.H"
00057 #include "NOX_StatusTest_NormF.H"
00058 #include "NOX_StatusTest_NormWRMS.H"
00059 #include "NOX_StatusTest_NormUpdate.H"
00060 #include "NOX_StatusTest_MaxIters.H"
00061 #include "NOX_StatusTest_FiniteValue.H"
00062 #include "NOX_StatusTest_Divergence.H"
00063 #include "NOX_StatusTest_Stagnation.H"
00064
00065 using namespace Teuchos;
00066
00067
00068
00069 NOX::StatusTest::Factory::Factory()
00070 { }
00071
00072
00073
00074 NOX::StatusTest::Factory::~Factory()
00075 { }
00076
00077
00078
00079 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00080 buildStatusTests(const std::string& file_name , const NOX::Utils& u,
00081 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00082 tagged_tests) const
00083 {
00084 Teuchos::RCP<NOX::StatusTest::Generic> status_tests;
00085
00086 #ifdef HAVE_TEUCHOS_EXTENDED
00087 Teuchos::ParameterList param_list;
00088 Teuchos::updateParametersFromXmlFile("input.xml", ¶m_list);
00089 status_tests = this->buildStatusTests(param_list, u, tagged_tests);
00090 #else
00091 std::string msg = "Error - Teuchos Extended Support must be enabled to use the xml reader for parameter lists. Please rebuild the Trilinos Teuchos library with --enable-teuchos-extended in teh configure script.";
00092 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00093 #endif
00094
00095 return status_tests;
00096 }
00097
00098
00099
00100 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00101 buildStatusTests(Teuchos::ParameterList& p, const NOX::Utils& u,
00102 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00103 tagged_tests) const
00104 {
00105 Teuchos::RCP<NOX::StatusTest::Generic> status_test;
00106
00107 std::string test_type = "???";
00108
00109 if (isParameterType<std::string>(p, "Test Type"))
00110 test_type = get<std::string>(p, "Test Type");
00111 else {
00112 std::string msg = "Error - The \"Test Type\" is a required parameter in the NOX::StatusTest::Factory!";
00113 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00114 }
00115
00116 if (test_type == "Combo")
00117 status_test = this->buildComboTest(p, u, tagged_tests);
00118 else if (test_type == "NormF")
00119 status_test = this->buildNormFTest(p, u);
00120 else if (test_type == "NormUpdate")
00121 status_test = this->buildNormUpdateTest(p, u);
00122 else if (test_type == "NormWRMS")
00123 status_test = this->buildNormWRMSTest(p, u);
00124 else if (test_type == "FiniteValue")
00125 status_test = this->buildFiniteValueTest(p, u);
00126 else if (test_type == "MaxIters")
00127 status_test = this->buildMaxItersTest(p, u);
00128 else if (test_type == "Divergence")
00129 status_test = this->buildDivergenceTest(p, u);
00130 else if (test_type == "Stagnation")
00131 status_test = this->buildStagnationTest(p, u);
00132 else if (test_type == "User Defined")
00133 status_test = this->buildUserDefinedTest(p, u);
00134 else {
00135 std::ostringstream msg;
00136 msg << "Error - the test type \"" << test_type << "\" is invalid!";
00137 TEST_FOR_EXCEPTION(true, std::logic_error, msg.str());
00138 }
00139
00140 this->checkAndTagTest(p, status_test, tagged_tests);
00141
00142 return status_test;
00143 }
00144
00145
00146
00147 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00148 buildComboTest(Teuchos::ParameterList& p, const NOX::Utils& u,
00149 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00150 tagged_tests) const
00151 {
00152
00153 int number_of_tests = get<int>(p, "Number of Tests");
00154
00155 std::string combo_type_string = get<std::string>(p, "Combo Type");
00156 NOX::StatusTest::Combo::ComboType combo_type;
00157 if (combo_type_string == "AND")
00158 combo_type = NOX::StatusTest::Combo::AND;
00159 else if (combo_type_string == "OR")
00160 combo_type = NOX::StatusTest::Combo::OR;
00161 else{
00162 std::string msg =
00163 "Error - The \"Combo Type\" must be \"AND\" or \"OR\"!";
00164 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00165 }
00166
00167 RCP<NOX::StatusTest::Combo> combo_test =
00168 rcp(new NOX::StatusTest::Combo(combo_type, &u));
00169
00170 for (int i=0; i < number_of_tests; ++i) {
00171 ostringstream subtest_name;
00172 subtest_name << "Test " << i;
00173 ParameterList& subtest_list = p.sublist(subtest_name.str(), true);
00174
00175 RCP<NOX::StatusTest::Generic> subtest =
00176 this->buildStatusTests(subtest_list, u, tagged_tests);
00177
00178 combo_test->addStatusTest(subtest);
00179 }
00180
00181 return combo_test;
00182 }
00183
00184
00185
00186 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00187 buildNormFTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00188 {
00189 double tolerance = p.get("Tolerance", 1.0e-8);
00190
00191
00192 std::string norm_type_string = p.get("Norm Type", "Two Norm");
00193 NOX::Abstract::Vector::NormType norm_type = NOX::Abstract::Vector::TwoNorm;
00194 if (norm_type_string == "Two Norm")
00195 norm_type = NOX::Abstract::Vector::TwoNorm;
00196 else if (norm_type_string == "One Norm")
00197 norm_type = NOX::Abstract::Vector::OneNorm;
00198 else if (norm_type_string == "Max Norm")
00199 norm_type = NOX::Abstract::Vector::MaxNorm;
00200 else {
00201 std::string msg = "\"Norm Type\" must be either \"Two Norm\", \"One Norm\", or \"Max Norm\"!";
00202 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00203 }
00204
00205
00206 std::string scale_type_string = p.get("Scale Type", "Unscaled");
00207 NOX::StatusTest::NormF::ScaleType scale_type =
00208 NOX::StatusTest::NormF::Unscaled;
00209 if (scale_type_string == "Unscaled")
00210 scale_type = NOX::StatusTest::NormF::Unscaled;
00211 else if (scale_type_string == "Scaled")
00212 scale_type = NOX::StatusTest::NormF::Scaled;
00213 else {
00214 std::string msg = "\"Scale Type\" must be either \"Unscaled\" or \"Scaled\"!";
00215 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00216 }
00217
00218
00219 bool use_relative_tolerance = false;
00220 Teuchos::RCP<NOX::Abstract::Group> group;
00221 if (isParameterType< RCP<NOX::Abstract::Group> >(p, "Initial Guess")) {
00222 group = get< RCP<NOX::Abstract::Group> >(p, "Initial Guess");
00223 use_relative_tolerance = true;
00224 }
00225
00226 RCP<NOX::StatusTest::NormF> status_test;
00227
00228 if (use_relative_tolerance)
00229 status_test = rcp(new NOX::StatusTest::NormF(*group,
00230 tolerance,
00231 norm_type,
00232 scale_type,
00233 &u));
00234 else
00235 status_test = rcp(new NOX::StatusTest::NormF(tolerance,
00236 norm_type,
00237 scale_type,
00238 &u));
00239
00240
00241 return status_test;
00242 }
00243
00244
00245
00246 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00247 buildNormUpdateTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00248 {
00249 double tolerance = p.get("Tolerance", 1.0e-3);
00250
00251
00252 std::string norm_type_string = p.get("Norm Type", "Two Norm");
00253 NOX::Abstract::Vector::NormType norm_type = NOX::Abstract::Vector::TwoNorm;
00254 if (norm_type_string == "Two Norm")
00255 norm_type = NOX::Abstract::Vector::TwoNorm;
00256 else if (norm_type_string == "One Norm")
00257 norm_type = NOX::Abstract::Vector::OneNorm;
00258 else if (norm_type_string == "Max Norm")
00259 norm_type = NOX::Abstract::Vector::MaxNorm;
00260 else {
00261 std::string msg = "\"Norm Type\" must be either \"Two Norm\", \"One Norm\", or \"Max Norm\"!";
00262 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00263 }
00264
00265
00266 std::string scale_type_string = p.get("Scale Type", "Unscaled");
00267 NOX::StatusTest::NormUpdate::ScaleType scale_type =
00268 NOX::StatusTest::NormUpdate::Unscaled;
00269 if (scale_type_string == "Unscaled")
00270 scale_type = NOX::StatusTest::NormUpdate::Unscaled;
00271 else if (scale_type_string == "Scaled")
00272 scale_type = NOX::StatusTest::NormUpdate::Scaled;
00273 else {
00274 std::string msg = "\"Scale Type\" must be either \"Unscaled\" or \"Scaled\"!";
00275 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00276 }
00277
00278 Teuchos::RCP<NOX::StatusTest::NormUpdate> status_test =
00279 Teuchos::rcp(new NOX::StatusTest::NormUpdate(tolerance, norm_type,
00280 scale_type));
00281
00282 return status_test;
00283 }
00284
00285
00286
00287 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00288 buildNormWRMSTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00289 {
00290 double bdf_multiplier = p.get("BDF Multiplier", 1.0);
00291 double tolerance = p.get("Tolerance", 1.0);
00292 double alpha = p.get("Alpha", 1.0);
00293 double beta = p.get("Beta", 0.5);
00294 double rel_tol = p.get("Relative Tolerance", 1.0e-5);
00295
00296 bool abs_tol_is_vector = false;
00297 Teuchos::RCP<const NOX::Abstract::Vector> abs_tol_vector;
00298 double abs_tol = 1.0;
00299 if (isParameterType< RCP<const NOX::Abstract::Vector> >
00300 (p, "Absolute Tolerance")) {
00301 abs_tol_vector = get< Teuchos::RCP<const NOX::Abstract::Vector> >
00302 (p, "Absolute Tolerance");
00303 abs_tol_is_vector = true;
00304 }
00305 else {
00306 abs_tol = p.get("Absolute Tolerance", 1.0e-8);
00307 }
00308
00309 RCP<NOX::StatusTest::NormWRMS> status_test;
00310
00311 if (abs_tol_is_vector)
00312 status_test = rcp(new NOX::StatusTest::NormWRMS(rel_tol,
00313 abs_tol_vector,
00314 bdf_multiplier,
00315 tolerance,
00316 alpha,
00317 beta)
00318 );
00319 else
00320 status_test = rcp(new NOX::StatusTest::NormWRMS(rel_tol,
00321 abs_tol,
00322 bdf_multiplier,
00323 tolerance,
00324 alpha,
00325 beta)
00326 );
00327
00328 return status_test;
00329 }
00330
00331
00332
00333 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00334 buildFiniteValueTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00335 {
00336 std::string vector_type_string = p.get("Vector Type","F Vector");
00337 std::string norm_type_string = p.get("Norm Type", "Two Norm");
00338
00339 NOX::StatusTest::FiniteValue::VectorType vector_type =
00340 NOX::StatusTest::FiniteValue::FVector;
00341 NOX::Abstract::Vector::NormType norm_type = NOX::Abstract::Vector::TwoNorm;
00342
00343 if (vector_type_string == "F Vector")
00344 vector_type = NOX::StatusTest::FiniteValue::FVector;
00345 else if (vector_type_string == "Solution Vector")
00346 vector_type = NOX::StatusTest::FiniteValue::SolutionVector;
00347 else {
00348 std::string msg = "\"Vector Type\" must be either \"F Vector\" or \"Solution Vector\"!";
00349 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00350 }
00351
00352 if (norm_type_string == "Two Norm")
00353 norm_type = NOX::Abstract::Vector::TwoNorm;
00354 else if (vector_type_string == "One Norm")
00355 norm_type = NOX::Abstract::Vector::OneNorm;
00356 else if (vector_type_string == "Max Norm")
00357 norm_type = NOX::Abstract::Vector::MaxNorm;
00358 else {
00359 std::string msg = "\"Norm Type\" must be either \"Two Norm\", \"One Norm\", or \"Max Norm\"!";
00360 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00361 }
00362
00363 RCP<NOX::StatusTest::FiniteValue> status_test =
00364 rcp(new NOX::StatusTest::FiniteValue(vector_type, norm_type));
00365
00366 return status_test;
00367 }
00368
00369
00370
00371 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00372 buildDivergenceTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00373 {
00374 double tolerance = p.get("Tolerance", 1.0e+12);
00375 int iterations = p.get("Consecutive Iterations", 1);
00376
00377 RCP<NOX::StatusTest::Divergence> status_test =
00378 rcp(new NOX::StatusTest::Divergence(tolerance, iterations));
00379
00380 return status_test;
00381 }
00382
00383
00384
00385 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00386 buildStagnationTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00387 {
00388 double tolerance = p.get("Tolerance", 1.0e+12);
00389 int iterations = p.get("Consecutive Iterations", 1);
00390
00391 RCP<NOX::StatusTest::Stagnation> status_test =
00392 rcp(new NOX::StatusTest::Stagnation(iterations, tolerance));
00393
00394 return status_test;
00395 }
00396
00397
00398
00399 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00400 buildMaxItersTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00401 {
00402 int max_iters = get<int>(p, "Maximum Iterations");
00403
00404 RCP<NOX::StatusTest::MaxIters> status_test =
00405 rcp(new NOX::StatusTest::MaxIters(max_iters, &u));
00406
00407 return status_test;
00408 }
00409
00410
00411
00412 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::Factory::
00413 buildUserDefinedTest(Teuchos::ParameterList& p, const NOX::Utils& u) const
00414 {
00415 RCP<NOX::StatusTest::Generic> status_test;
00416
00417 if (isParameterType< RCP<NOX::StatusTest::Generic> >(p, "User Status Test"))
00418 status_test = get< RCP<NOX::StatusTest::Generic> >(p, "User Status Test");
00419 else {
00420 std::string msg = "Error - NOX::StatusTest::Factory::buildUserDefinedTest() - a user defined status test has been selected, but the test has not been supplied as an RCP<NOX::StatusTest::Generic> in the parameter list. please make sure it is set as a \"Generic\" object in the parameter list.";
00421 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00422 }
00423
00424 return status_test;
00425 }
00426
00427
00428
00429 bool NOX::StatusTest::Factory::
00430 checkAndTagTest(const Teuchos::ParameterList& p,
00431 const Teuchos::RCP<NOX::StatusTest::Generic>& test,
00432 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00433 tagged_tests) const
00434 {
00435 if ( (isParameterType<std::string>(p, "Tag")) && (tagged_tests != NULL) ) {
00436 (*tagged_tests)[getParameter<std::string>(p, "Tag")] = test;
00437 return true;
00438 }
00439
00440 return false;
00441 }
00442
00443
00444
00445
00446 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::
00447 buildStatusTests(const std::string& file_name, const NOX::Utils& utils,
00448 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00449 tagged_tests)
00450 {
00451 NOX::StatusTest::Factory factory;
00452 return factory.buildStatusTests(file_name, utils, tagged_tests);
00453 }
00454
00455
00456
00457
00458 Teuchos::RCP<NOX::StatusTest::Generic> NOX::StatusTest::
00459 buildStatusTests(Teuchos::ParameterList& p, const NOX::Utils& utils,
00460 std::map<std::string, Teuchos::RCP<NOX::StatusTest::Generic> >*
00461 tagged_tests)
00462 {
00463 NOX::StatusTest::Factory factory;
00464 return factory.buildStatusTests(p, utils, tagged_tests);
00465 }
00466
00467
00468