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