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 <NewtonLineSearch.h>
00034 #include <AnalysisModel.h>
00035 #include <StaticAnalysis.h>
00036 #include <IncrementalIntegrator.h>
00037 #include <LinearSOE.h>
00038 #include <Channel.h>
00039 #include <FEM_ObjectBroker.h>
00040 #include <ConvergenceTest.h>
00041 #include <ID.h>
00042
00043 #define EquiALGORITHM_TAGS_NewtonLineSearch 2011
00044
00045
00046 NewtonLineSearch::NewtonLineSearch( )
00047 :EquiSolnAlgo(EquiALGORITHM_TAGS_NewtonLineSearch),
00048 theTest(0), tolerance(0.8), r0(0), x0(0), x(0), xOld(0)
00049 {
00050 }
00051
00052
00053
00054 NewtonLineSearch::NewtonLineSearch( ConvergenceTest &theT,
00055 double LineSearchTolerance = 0.8 )
00056 :EquiSolnAlgo(EquiALGORITHM_TAGS_NewtonLineSearch),
00057 theTest(&theT), tolerance(LineSearchTolerance), r0(0), x0(0), x(0), xOld(0)
00058 {
00059
00060 tolerance = fabs( LineSearchTolerance ) ;
00061
00062 if ( tolerance < 0.5 )
00063 tolerance = 0.5 ;
00064
00065 if ( tolerance > 0.8 )
00066 tolerance = 0.8 ;
00067 }
00068
00069
00070
00071 NewtonLineSearch::~NewtonLineSearch()
00072 {
00073 if (r0 != 0)
00074 delete r0 ;
00075
00076 if (x0 != 0)
00077 delete x0 ;
00078
00079 if (x != 0)
00080 delete x ;
00081
00082 if (xOld != 0)
00083 delete xOld ;
00084 }
00085
00086 void
00087 NewtonLineSearch::setTest(ConvergenceTest &newTest)
00088 {
00089 theTest = &newTest;
00090 }
00091
00092
00093 int
00094 NewtonLineSearch::solveCurrentStep(void)
00095 {
00096
00097
00098 AnalysisModel *theAnaModel = this->getAnalysisModelPtr();
00099 IncrementalIntegrator *theIntegrator = this->getIncrementalIntegratorPtr();
00100 LinearSOE *theSOE = this->getLinearSOEptr();
00101
00102 if ((theAnaModel == 0) || (theIntegrator == 0) || (theSOE == 0)
00103 || (theTest == 0)){
00104 cerr << "WARNING NewtonLineSearch::solveCurrentStep() - setLinks() has";
00105 cerr << " not been called - or no ConvergenceTest has been set\n";
00106 return -5;
00107 }
00108
00109
00110 int systemSize = ( theSOE->getB() ).Size();
00111 if ((r0 == 0) || (r0->Size() != systemSize)) {
00112
00113 if (r0 != 0) {
00114 delete r0 ;
00115 delete x ;
00116 delete x0 ;
00117 delete xOld ;
00118 }
00119
00120 r0 = new Vector(systemSize) ;
00121 x = new Vector(systemSize) ;
00122 x0 = new Vector(systemSize) ;
00123 xOld = new Vector(systemSize) ;
00124
00125 if (r0 == 0 || x == 0 || x0 == 0 || xOld == 0 ||
00126 r0->Size() != systemSize || x->Size() != systemSize ||
00127 x0->Size() != systemSize || xOld->Size() != systemSize) {
00128 cerr << "WARNING NewtonLineSearch::solveCurrentStep() - out of memory";
00129 cerr << " creating vectors of size " << systemSize << endl;
00130 if (r0 != 0)
00131 delete r0 ;
00132 if (x0 != 0)
00133 delete x0 ;
00134 if (x != 0)
00135 delete x ;
00136 if (xOld != 0)
00137 delete xOld ;
00138 return -5;
00139 }
00140
00141 }
00142
00143
00144
00145 theTest->setEquiSolnAlgo(*this);
00146 if (theTest->start() < 0) {
00147 cerr << "NewtonLineSearch::solveCurrentStep() -";
00148 cerr << "the ConvergenceTest object failed in start()\n";
00149 return -3;
00150 }
00151
00152 if (theIntegrator->formUnbalance() < 0) {
00153 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00154 cerr << "the Integrator failed in formUnbalance()\n";
00155 return -2;
00156 }
00157
00158
00159 Vector &Resid0 = *r0 ;
00160 Vector &dx0 = *x0 ;
00161 Vector &dx = *x ;
00162 Vector &dxOld = *xOld ;
00163
00164 int result = -1;
00165 do {
00166
00167
00168 Resid0 = theSOE->getB() ;
00169
00170
00171
00172 if (theIntegrator->formTangent() < 0){
00173 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00174 cerr << "the Integrator failed in formTangent()\n";
00175 return -1;
00176 }
00177
00178
00179 if (theSOE->solve() < 0) {
00180 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00181 cerr << "the LinearSysOfEqn failed in solve()\n";
00182 return -3;
00183 }
00184
00185
00186
00187 dx0 = theSOE->getX() ;
00188
00189
00190 double s0 = - (dx0 ^ Resid0) ;
00191
00192
00193
00194 if (theIntegrator->update(theSOE->getX()) < 0) {
00195 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00196 cerr << "the Integrator failed in update()\n";
00197 return -4;
00198 }
00199
00200 if (theIntegrator->formUnbalance() < 0) {
00201 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00202 cerr << "the Integrator failed in formUnbalance()\n";
00203 return -2;
00204 }
00205
00206
00207 const Vector &Resid = theSOE->getB() ;
00208
00209
00210 double s = - ( dx0 ^ Resid ) ;
00211
00212
00213 double r = 0.0 ;
00214 double r0 = 0.0 ;
00215
00216 if ( s0 != 0.0 )
00217 r = fabs( s / s0 ) ;
00218
00219 r0 = r ;
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 double eta = 1.0 ;
00232
00233 int count = 0 ;
00234
00235 dxOld = dx0 ;
00236
00237
00238 while ( r > tolerance && count < 10 ) {
00239
00240 count++ ;
00241
00242 eta *= -s0 / (s - s0) ;
00243
00244
00245 if ( eta > 10.0 ) eta = 10.0 ;
00246 if ( r > r0 ) eta = 1.0 ;
00247
00248
00249
00250 dx = dx0 ;
00251 dx *= eta ;
00252
00253
00254 if (theIntegrator->update( dx - dxOld ) < 0) {
00255 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00256 cerr << "the Integrator failed in update()\n";
00257 return -4;
00258 }
00259
00260 if (theIntegrator->formUnbalance() < 0) {
00261 cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00262 cerr << "the Integrator failed in formUnbalance()\n";
00263 return -2;
00264 }
00265
00266
00267 const Vector &ResidI = theSOE->getB() ;
00268
00269
00270 s = - ( dx0 ^ ResidI ) ;
00271
00272
00273 r = fabs( s / s0 ) ;
00274
00275 cerr << "Line Search, Iteration " << count
00276 << " : Ratio |s/s0| = " << r << endl ;
00277
00278
00279 dxOld = dx ;
00280
00281 if ( count == 10 )
00282 cerr << "Line Search Terminated After 10 Iterations" << endl ;
00283
00284 }
00285
00286 this->record(0);
00287 result = theTest->test();
00288
00289 } while (result == -1);
00290
00291 if (result == -2) {
00292 cerr << "NewtonLineSearch::solveCurrentStep() -";
00293 cerr << "the ConvergenceTest object failed in test()\n";
00294 return -3;
00295 }
00296
00297
00298
00299 return result;
00300 }
00301
00302 ConvergenceTest *
00303 NewtonLineSearch::getTest(void)
00304 {
00305 return theTest;
00306 }
00307
00308 int
00309 NewtonLineSearch::sendSelf(int cTag, Channel &theChannel)
00310 {
00311 int result = 0;
00312 int dataTag = this->getDbTag();
00313 ID data(2);
00314 data(0) = theTest->getClassTag();
00315 data(1) = theTest->getDbTag();
00316 result = theChannel.sendID(dataTag, cTag, data);
00317 if (result != 0) {
00318 cerr << "NewtonLineSearch::sendSelf() - failed to send ID\n";
00319 return result;
00320 }
00321
00322 Vector tol(1);
00323 tol(0) = tolerance;
00324 result = theChannel.sendVector(dataTag, cTag, tol);
00325 if (result != 0) {
00326 cerr << "NewtonLineSearch::sendSelf() - failed to send Vector\n";
00327 return result;
00328 }
00329
00330 result = theTest->sendSelf(cTag, theChannel);
00331 if (result != 0) {
00332 cerr << "NewtonRaphson::sendSelf() - failed to send CTest object\n";
00333 return result;
00334 }
00335
00336
00337
00338 return 0;
00339 }
00340
00341 int
00342 NewtonLineSearch::recvSelf(int cTag,
00343 Channel &theChannel,
00344 FEM_ObjectBroker &theBroker)
00345 {
00346 ID data(2);
00347 int result;
00348 int dataTag = this->getDbTag();
00349
00350 result = theChannel.recvID(dataTag, cTag, data);
00351 if (result != 0) {
00352 cerr << "NewtonLineSearch::recvSelf() - failed to receive ID\n";
00353 return result;
00354 }
00355 int ctType = data(0);
00356 int ctDb = data(1);
00357
00358
00359 Vector tol(1);
00360 result = theChannel.recvVector(dataTag, cTag, tol);
00361 if (result != 0) {
00362 cerr << "NewtonLineSearch::sendSelf() - failed to send Vector\n";
00363 return result;
00364 }
00365 tolerance = tol(0);
00366
00367 theTest = theBroker.getNewConvergenceTest(ctType);
00368 theTest->setDbTag(ctDb);
00369 result = theTest->recvSelf(cTag, theChannel, theBroker);
00370 if (result != 0) {
00371 cerr << "NewtonLineSearch::recvSelf() - failed to recv CTest object\n";
00372 return result;
00373 }
00374
00375 return 0;
00376 }
00377
00378
00379 void
00380 NewtonLineSearch::Print(ostream &s, int flag)
00381 {
00382 if (flag == 0)
00383 s << "NewtonLineSearch :: Line Search Tolerance = " << tolerance << endl ;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393