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
00043
00044
00045
00046
00047
00048
00049
00050 #include "NOX_Common.H"
00051 #include "NOX_Playa_Group.hpp"
00052 #include "PlayaMPIComm.hpp"
00053 #include "PlayaOut.hpp"
00054 #include "PlayaTabs.hpp"
00055
00056 using Playa::Out;
00057 using Playa::Tabs;
00058 using Teuchos::RCP;
00059
00060 using std::ostream;
00061 using std::cout;
00062 using std::runtime_error;
00063
00064
00065
00066 NOX::NOXPlaya::Group::Group(const Playa::Vector<double>& initcond,
00067 const Playa::NonlinearOperator<double>& nonlinOp,
00068 const Playa::LinearSolver<double>& linsolver)
00069 :
00070 precision(3),
00071 xVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, DeepCopy))),
00072 fVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00073 newtonVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00074 gradientVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00075 solver(linsolver),
00076 jacobian(),
00077 nonlinearOp(nonlinOp),
00078 normF(0.0)
00079 {
00080 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00081 resetIsValid();
00082 }
00083
00084 NOX::NOXPlaya::Group::Group(const Playa::NonlinearOperator<double>& nonlinOp,
00085 const Playa::LinearSolver<double>& linsolver)
00086 :
00087 precision(3),
00088 xVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, DeepCopy))),
00089 fVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00090 newtonVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00091 gradientVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00092 solver(linsolver),
00093 jacobian(),
00094 nonlinearOp(nonlinOp),
00095 normF(0.0)
00096 {
00097 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00098 resetIsValid();
00099 }
00100
00101 NOX::NOXPlaya::Group::Group(const Playa::Vector<double>& initcond,
00102 const Playa::NonlinearOperator<double>& nonlinOp,
00103 const Playa::LinearSolver<double>& linsolver,
00104 int numdigits)
00105 :
00106 precision(numdigits),
00107 xVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, DeepCopy))),
00108 fVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00109 newtonVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00110 gradientVector(rcp(new NOX::NOXPlaya::Vector(initcond, precision, ShapeCopy))),
00111 solver(linsolver),
00112 jacobian(),
00113 nonlinearOp(nonlinOp),
00114 normF(0.0)
00115 {
00116 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00117 resetIsValid();
00118 }
00119
00120 NOX::NOXPlaya::Group::Group(const Playa::NonlinearOperator<double>& nonlinOp,
00121 const Playa::LinearSolver<double>& linsolver,
00122 int numdigits)
00123 :
00124 precision(numdigits),
00125 xVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, DeepCopy))),
00126 fVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00127 newtonVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00128 gradientVector(rcp(new NOX::NOXPlaya::Vector(nonlinOp.getInitialGuess(), precision, ShapeCopy))),
00129 solver(linsolver),
00130 jacobian(),
00131 nonlinearOp(nonlinOp),
00132 normF(0.0)
00133 {
00134 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00135 resetIsValid();
00136 }
00137
00138
00139 NOX::NOXPlaya::Group::Group(const NOX::NOXPlaya::Group& source, NOX::CopyType type) :
00140 precision(source.precision),
00141 xVector(rcp(new NOX::NOXPlaya::Vector(*(source.xVector), precision, type))),
00142 fVector(rcp(new NOX::NOXPlaya::Vector(*(source.fVector), precision, type))),
00143 newtonVector(rcp(new NOX::NOXPlaya::Vector(*(source.newtonVector), precision, type))),
00144 gradientVector(rcp(new NOX::NOXPlaya::Vector(*(source.gradientVector), precision, type))),
00145 solver(source.solver),
00146 jacobian(source.jacobian),
00147 nonlinearOp(source.nonlinearOp),
00148 isValidF(false),
00149 isValidJacobian(false),
00150 isValidGradient(false),
00151 isValidNewton(false),
00152 normF(0.0)
00153 {
00154 switch (type)
00155 {
00156
00157 case NOX::DeepCopy:
00158
00159 isValidF = source.isValidF;
00160 isValidGradient = source.isValidGradient;
00161 isValidNewton = source.isValidNewton;
00162 isValidJacobian = source.isValidJacobian;
00163 normF = source.normF;
00164 break;
00165
00166 case NOX::ShapeCopy:
00167 resetIsValid();
00168 normF = 0.0;
00169 break;
00170
00171 default:
00172 Out::os() << "NOX:Playa::Group - invalid CopyType for copy constructor." << std::endl;
00173 throw "NOX Playa Error";
00174 }
00175
00176 }
00177
00178 NOX::NOXPlaya::Group::~Group()
00179 {
00180 }
00181
00182 void NOX::NOXPlaya::Group::resetIsValid()
00183 {
00184 isValidF = false;
00185 isValidJacobian = false;
00186 isValidGradient = false;
00187 isValidNewton = false;
00188 }
00189
00190
00191 RCP<NOX::Abstract::Group> NOX::NOXPlaya::Group::clone(NOX::CopyType type) const
00192 {
00193 return rcp(new NOX::NOXPlaya::Group(*this, type));
00194 }
00195
00196 NOX::Abstract::Group& NOX::NOXPlaya::Group::operator=(const NOX::Abstract::Group& source)
00197 {
00198 return operator=(dynamic_cast<const NOX::NOXPlaya::Group&> (source));
00199 }
00200
00201 NOX::Abstract::Group& NOX::NOXPlaya::Group::operator=(const NOX::NOXPlaya::Group& source)
00202 {
00203 if (this != &source)
00204 {
00205
00206
00207 *xVector = *(source.xVector);
00208 nonlinearOp = source.nonlinearOp;
00209 solver = source.solver;
00210 jacobian = source.jacobian;
00211 precision = source.precision;
00212
00213
00214 isValidF = source.isValidF;
00215 isValidGradient = source.isValidGradient;
00216 isValidNewton = source.isValidNewton;
00217 isValidJacobian = source.isValidJacobian;
00218
00219
00220 if (isValidF)
00221 {
00222 *fVector = *(source.fVector);
00223 normF = source.normF;
00224 }
00225
00226 if (isValidGradient)
00227 *gradientVector = *(source.gradientVector);
00228
00229 if (isValidNewton)
00230 *newtonVector = *(source.newtonVector);
00231
00232 if (isValidJacobian)
00233 jacobian = source.jacobian;
00234 }
00235 return *this;
00236 }
00237
00238 void NOX::NOXPlaya::Group::setX(const NOX::Abstract::Vector& y)
00239 {
00240 setX(dynamic_cast<const NOX::NOXPlaya::Vector&> (y));
00241 }
00242
00243 void NOX::NOXPlaya::Group::setX(const NOX::NOXPlaya::Vector& y)
00244 {
00245 resetIsValid();
00246 nonlinearOp.setEvalPt(y.getPlayaVector());
00247 *xVector = y;
00248 }
00249
00250 void NOX::NOXPlaya::Group::computeX(const NOX::Abstract::Group& grp,
00251 const NOX::Abstract::Vector& d,
00252 double step)
00253 {
00254
00255 const Group& tsfgrp = dynamic_cast<const NOX::NOXPlaya::Group&> (grp);
00256 const Vector& tsfd = dynamic_cast<const NOX::NOXPlaya::Vector&> (d);
00257 computeX(tsfgrp, tsfd, step);
00258 }
00259
00260 void NOX::NOXPlaya::Group::computeX(const Group& grp, const Vector& d, double step)
00261 {
00262 Tabs tab;
00263 resetIsValid();
00264 xVector->update(1.0, *(grp.xVector), step, d);
00265 }
00266
00267 NOX::Abstract::Group::ReturnType NOX::NOXPlaya::Group::computeF()
00268 {
00269
00270 if (nonlinearOp.verb() > 2)
00271 {
00272 Out::os() << "calling computeF()" << std::endl;
00273 }
00274
00275 if (isValidF)
00276 {
00277 if (nonlinearOp.verb() > 2)
00278 {
00279 Out::os() << "reusing F" << std::endl;
00280 }
00281 return NOX::Abstract::Group::Ok;
00282 }
00283 else
00284 {
00285 if (nonlinearOp.verb() > 2)
00286 {
00287 Out::os() << "computing new F" << std::endl;
00288 }
00289 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00290 *fVector = nonlinearOp.getFunctionValue();
00291 isValidF = true;
00292 normF = fVector->norm();
00293 }
00294
00295 return (isValidF) ? (NOX::Abstract::Group::Ok) : (NOX::Abstract::Group::Failed);
00296 }
00297
00298 NOX::Abstract::Group::ReturnType NOX::NOXPlaya::Group::computeJacobian()
00299 {
00300
00301 if (nonlinearOp.verb() > 2)
00302 {
00303 Out::os() << "calling computeJ()" << std::endl;
00304 }
00305
00306
00307 if (isValidJacobian)
00308 {
00309 return NOX::Abstract::Group::Ok;
00310 }
00311 else
00312 {
00313 nonlinearOp.setEvalPt(xVector->getPlayaVector());
00314 jacobian = nonlinearOp.getJacobian();
00315
00316 isValidJacobian = true;
00317 }
00318 return (isValidJacobian) ? (NOX::Abstract::Group::Ok) : (NOX::Abstract::Group::Failed);
00319 }
00320
00321 NOX::Abstract::Group::ReturnType NOX::NOXPlaya::Group::computeGradient()
00322 {
00323 if (nonlinearOp.verb() > 2)
00324 {
00325 Out::os() << "calling computeGrad()" << std::endl;
00326 }
00327 if (isValidGradient)
00328 {
00329 return NOX::Abstract::Group::Ok;
00330 }
00331 else
00332 {
00333 if (!isF())
00334 {
00335 Out::os() << "ERROR: NOX::NOXPlaya::Group::computeGrad() - F is out of date wrt X!" << std::endl;
00336 return NOX::Abstract::Group::BadDependency;
00337 }
00338
00339 if (!isJacobian())
00340 {
00341 Out::os() << "ERROR: NOX::NOXPlaya::Group::computeGrad() - Jacobian is out of date wrt X!" << std::endl;
00342 return NOX::Abstract::Group::BadDependency;
00343 }
00344
00345
00346
00347 NOX::Abstract::Group::ReturnType status
00348 = applyJacobianTranspose(*fVector,*gradientVector);
00349 isValidGradient = (status == NOX::Abstract::Group::Ok);
00350
00351
00352 return status;
00353 }
00354 }
00355
00356 NOX::Abstract::Group::ReturnType
00357 NOX::NOXPlaya::Group::computeNewton(Teuchos::ParameterList& p)
00358 {
00359 if (isNewton())
00360 {
00361 return NOX::Abstract::Group::Ok;
00362 }
00363 else
00364 {
00365 if (!isF())
00366 {
00367 Out::os() << "ERROR: NOX::Example::Group::computeNewton() - invalid F"
00368 << std::endl;
00369 throw "NOX Error";
00370 }
00371
00372 if (!isJacobian())
00373 {
00374 Out::os() << "ERROR: NOX::Example::Group::computeNewton() - invalid Jacobian" << std::endl;
00375 throw "NOX Error";
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 NOX::Abstract::Group::ReturnType status
00387 = applyJacobianInverse(p, *fVector, *newtonVector);
00388 isValidNewton = (status == NOX::Abstract::Group::Ok);
00389
00390
00391
00392 newtonVector->scale(-1.0);
00393
00394 if (nonlinearOp.verb() > 0)
00395 {
00396 Out::os() << "newton step" << std::endl;
00397 newtonVector->getPlayaVector().print(Out::os());
00398 }
00399
00400
00401 return status;
00402 }
00403 }
00404
00405
00406 NOX::Abstract::Group::ReturnType
00407 NOX::NOXPlaya::Group::applyJacobian(const Abstract::Vector& input,
00408 NOX::Abstract::Vector& result) const
00409 {
00410 const NOX::NOXPlaya::Vector& tsfinput = dynamic_cast<const NOX::NOXPlaya::Vector&> (input);
00411 NOX::NOXPlaya::Vector& tsfresult = dynamic_cast<NOX::NOXPlaya::Vector&> (result);
00412 return applyJacobian(tsfinput, tsfresult);
00413 }
00414
00415 NOX::Abstract::Group::ReturnType
00416 NOX::NOXPlaya::Group::applyJacobian(const NOX::NOXPlaya::Vector& input,
00417 NOX::NOXPlaya::Vector& result) const
00418 {
00419
00420 if (!isJacobian())
00421 {
00422 return NOX::Abstract::Group::BadDependency;
00423 }
00424 else
00425 {
00426
00427 jacobian.apply(input.getPlayaVector(),result.getPlayaVector());
00428 return NOX::Abstract::Group::Ok;
00429 }
00430 }
00431
00432 NOX::Abstract::Group::ReturnType
00433 NOX::NOXPlaya::Group::applyJacobianTranspose(const NOX::Abstract::Vector& input,
00434 NOX::Abstract::Vector& result) const
00435 {
00436 const NOX::NOXPlaya::Vector& tsfinput = dynamic_cast<const NOX::NOXPlaya::Vector&> (input);
00437 NOX::NOXPlaya::Vector& tsfresult = dynamic_cast<NOX::NOXPlaya::Vector&> (result);
00438 return applyJacobianTranspose(tsfinput, tsfresult);
00439 }
00440
00441 NOX::Abstract::Group::ReturnType
00442 NOX::NOXPlaya::Group::applyJacobianTranspose(const NOX::NOXPlaya::Vector& input, NOX::NOXPlaya::Vector& result) const
00443 {
00444
00445 if (!isJacobian())
00446 {
00447 return NOX::Abstract::Group::BadDependency;
00448 }
00449 else
00450 {
00451
00452 jacobian.applyTranspose(input.getPlayaVector(), result.getPlayaVector());
00453
00454 return NOX::Abstract::Group::Ok;
00455 }
00456 }
00457
00458 NOX::Abstract::Group::ReturnType
00459 NOX::NOXPlaya::Group::applyJacobianInverse(Teuchos::ParameterList& p,
00460 const Abstract::Vector& input,
00461 NOX::Abstract::Vector& result) const
00462 {
00463 const NOX::NOXPlaya::Vector& tsfinput = dynamic_cast<const NOX::NOXPlaya::Vector&> (input);
00464 NOX::NOXPlaya::Vector& tsfresult = dynamic_cast<NOX::NOXPlaya::Vector&> (result);
00465 return applyJacobianInverse(p, tsfinput, tsfresult);
00466 }
00467
00468 NOX::Abstract::Group::ReturnType
00469 NOX::NOXPlaya::Group::applyJacobianInverse(Teuchos::ParameterList& p,
00470 const NOX::NOXPlaya::Vector& input,
00471 NOX::NOXPlaya::Vector& result) const
00472 {
00473
00474 if (!isJacobian())
00475 {
00476 Out::os() << "ERROR: NOX::NOXPlaya::Group::applyJacobianInverse() - invalid Jacobian" << std::endl;
00477 throw "NOX Error";
00478
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 if (nonlinearOp.verb() > 4)
00488 {
00489 Out::os() << "---------------- applying J^-1 ------------------" << std::endl;
00490 Out::os() << "J=" << std::endl;
00491 jacobian.print(Out::os());
00492 Out::os() << "F=" << std::endl;
00493 input.getPlayaVector().print(Out::os());
00494 }
00495
00496 Playa::SolverState<double> status
00497 = solver.solve(jacobian, input.getPlayaVector(),
00498 result.getPlayaVector());
00499
00500 if (status.finalState() != Playa::SolveConverged)
00501 {
00502 return NOX::Abstract::Group::Failed;
00503 }
00504 else
00505 {
00506 if (nonlinearOp.verb() > 2)
00507 {
00508 Out::os() << "soln=" << std::endl;
00509 result.getPlayaVector().print(Out::os());
00510 }
00511 return NOX::Abstract::Group::Ok;
00512 }
00513
00514 }
00515
00516 bool NOX::NOXPlaya::Group::isF() const
00517 {
00518 return isValidF;
00519 }
00520
00521 bool NOX::NOXPlaya::Group::isJacobian() const
00522 {
00523 return isValidJacobian;
00524 }
00525
00526 bool NOX::NOXPlaya::Group::isGradient() const
00527 {
00528 return isValidGradient;
00529 }
00530
00531 bool NOX::NOXPlaya::Group::isNewton() const
00532 {
00533 return isValidNewton;
00534 }
00535
00536 const NOX::Abstract::Vector& NOX::NOXPlaya::Group::getX() const
00537 {
00538 return *xVector;
00539 }
00540
00541 const NOX::Abstract::Vector& NOX::NOXPlaya::Group::getF() const
00542 {
00543 if (nonlinearOp.verb() > 2)
00544 {
00545 Out::os() << "calling getF()" << std::endl;
00546 }
00547 TEUCHOS_TEST_FOR_EXCEPTION(!isF(), runtime_error,
00548 "calling getF() with invalid function value");
00549 return *fVector;
00550 }
00551
00552 double NOX::NOXPlaya::Group::getNormF() const
00553 {
00554 if (nonlinearOp.verb() > 2)
00555 {
00556 Out::os() << "normF = " << normF << std::endl;
00557 }
00558 TEUCHOS_TEST_FOR_EXCEPTION(!isF(), runtime_error,
00559 "calling normF() with invalid function value");
00560 return normF;
00561 }
00562
00563 const NOX::Abstract::Vector& NOX::NOXPlaya::Group::getGradient() const
00564 {
00565 return *gradientVector;
00566 }
00567
00568 const NOX::Abstract::Vector& NOX::NOXPlaya::Group::getNewton() const
00569 {
00570 return *newtonVector;
00571 }
00572
00573 void NOX::NOXPlaya::Group::print() const
00574 {
00575 cout << "x = " << *xVector << "\n";
00576
00577 if (isValidF) {
00578 cout << "F(x) = " << *fVector << "\n";
00579 cout << "|| F(x) || = " << normF << "\n";
00580 }
00581 else
00582 cout << "F(x) has not been computed" << "\n";
00583
00584 cout << std::endl;
00585 }
00586
00587
00588