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 <BFGS.h>
00031 #include <AnalysisModel.h>
00032 #include <StaticAnalysis.h>
00033 #include <IncrementalIntegrator.h>
00034 #include <LinearSOE.h>
00035 #include <Channel.h>
00036 #include <FEM_ObjectBroker.h>
00037 #include <ConvergenceTest.h>
00038 #include <ID.h>
00039
00040
00041 BFGS::BFGS(int theTangentToUse, int n )
00042 :EquiSolnAlgo(EquiALGORITHM_TAGS_BFGS),
00043 theTest(0), tangent(theTangentToUse), numberLoops(n)
00044 {
00045 s = new Vector*[numberLoops+3];
00046
00047 z = new Vector*[numberLoops+3];
00048
00049
00050
00051 residOld = 0;
00052 residNew = 0;
00053 du = 0;
00054 b = 0;
00055
00056 temp = 0;
00057
00058 rdotz = 0;
00059 sdotr = 0;
00060
00061 for ( int i =0; i < numberLoops+3; i++ ) {
00062 s[i] = 0;
00063 z[i] = 0;
00064 }
00065
00066 localTest = 0;
00067
00068 }
00069
00070
00071 BFGS::BFGS(ConvergenceTest &theT, int theTangentToUse, int n)
00072 :EquiSolnAlgo(EquiALGORITHM_TAGS_BFGS),
00073 theTest(&theT), tangent(theTangentToUse), numberLoops(n)
00074 {
00075 s = new Vector*[numberLoops+3];
00076
00077 z = new Vector*[numberLoops+3];
00078
00079 residOld = 0;
00080 residNew = 0;
00081 du = 0;
00082 b = 0;
00083 temp = 0;
00084
00085 rdotz = 0;
00086 sdotr = 0;
00087
00088 for ( int i =0; i < numberLoops+3; i++ ) {
00089 s[i] = 0;
00090 z[i] = 0;
00091
00092 }
00093
00094 localTest = theTest->getCopy( this->numberLoops );
00095
00096 }
00097
00098
00099 BFGS::~BFGS()
00100 {
00101
00102 if (temp != 0) delete temp;
00103 temp = 0;
00104
00105 if (residOld != 0 ) delete residOld;
00106 residOld = 0;
00107
00108 if (residNew != 0) delete residNew;
00109 residNew = 0;
00110
00111 if (du != 0) delete du;
00112 du = 0;
00113
00114 if (b != 0 ) delete b;
00115 b = 0;
00116
00117 if (rdotz != 0 ) delete [] rdotz;
00118 rdotz = 0;
00119
00120 if (sdotr != 0 ) delete [] sdotr;
00121 sdotr = 0;
00122
00123 for ( int i =0; i < numberLoops+3; i++ ) {
00124 if ( s[i] != 0 ) delete s[i];
00125 if ( z[i] != 0 ) delete z[i];
00126
00127 s[i] = 0;
00128 z[i] = 0;
00129
00130 }
00131
00132 if ( s != 0 ) delete[] s;
00133 if ( z != 0 ) delete[] z;
00134 s = 0;
00135 z = 0;
00136
00137 if ( localTest != 0 )
00138 delete localTest;
00139 localTest = 0;
00140
00141
00142 }
00143
00144
00145 int
00146 BFGS::setConvergenceTest(ConvergenceTest *newTest)
00147 {
00148 theTest = newTest;
00149
00150 if ( localTest != 0 )
00151 delete localTest;
00152
00153 localTest = theTest->getCopy( this->numberLoops );
00154 if (localTest != 0) {
00155 opserr << "BFGS::setConvergenceTest() - could not get copy for local test\n";
00156 return -1;
00157 } else
00158 return 0;
00159 }
00160
00161
00162
00163 int
00164 BFGS::solveCurrentStep(void)
00165 {
00166
00167
00168
00169
00170 AnalysisModel *theAnaModel = this->getAnalysisModelPtr();
00171
00172 IncrementalIntegrator *theIntegrator = this->getIncrementalIntegratorPtr();
00173
00174 LinearSOE *theSOE = this->getLinearSOEptr();
00175
00176 if ((theAnaModel == 0) || (theIntegrator == 0) || (theSOE == 0)
00177 || (theTest == 0)){
00178 opserr << "WARNING BFGS::solveCurrentStep() - setLinks() has";
00179 opserr << " not been called - or no ConvergenceTest has been set\n";
00180 return -5;
00181 }
00182
00183
00184 theTest->setEquiSolnAlgo(*this);
00185 if (theTest->start() < 0) {
00186 opserr << "BFGS::solveCurrentStep() -";
00187 opserr << "the ConvergenceTest object failed in start()\n";
00188 return -3;
00189 }
00190
00191 localTest->setEquiSolnAlgo(*this);
00192
00193 if (rdotz == 0)
00194 rdotz = new double[numberLoops+3];
00195
00196 if (sdotr == 0)
00197 sdotr = new double[numberLoops+3];
00198
00199
00200 int result = -1;
00201 int count = 0;
00202 do {
00203
00204
00205
00206
00207 if (theIntegrator->formTangent(tangent) < 0){
00208 opserr << "WARNING BFGS::solveCurrentStep() -";
00209 opserr << "the Integrator failed in formTangent()\n";
00210 return -1;
00211 }
00212
00213
00214 if (theIntegrator->formUnbalance() < 0) {
00215 opserr << "WARNING BFGS::solveCurrentStep() -";
00216 opserr << "the Integrator failed in formUnbalance()\n";
00217 }
00218
00219
00220 if (theSOE->solve() < 0) {
00221 opserr << "WARNING BFGS::solveCurrentStep() -";
00222 opserr << "the LinearSysOfEqn failed in solve()\n";
00223 return -3;
00224 }
00225
00226
00227 if ( theIntegrator->update(theSOE->getX() ) < 0) {
00228 opserr << "WARNING BFGS::solveCurrentStep() -";
00229 opserr << "the Integrator failed in update()\n";
00230 return -4;
00231 }
00232
00233
00234
00235 int systemSize = theSOE->getNumEqn( );
00236
00237
00238 if (temp == 0 )
00239 temp = new Vector(systemSize);
00240
00241
00242 if ( s[1] == 0 )
00243 s[1] = new Vector(systemSize);
00244
00245 *s[1] = theSOE->getX( );
00246
00247 if ( residOld == 0 )
00248 residOld = new Vector(systemSize);
00249
00250 *residOld = theSOE->getB( ) ;
00251 *residOld *= (-1.0 );
00252
00253
00254 if (theIntegrator->formUnbalance() < 0) {
00255 opserr << "WARNING BFGS::solveCurrentStep() -";
00256 opserr << "the Integrator failed in formUnbalance()\n";
00257 }
00258
00259 if ( residNew == 0 )
00260 residNew = new Vector(systemSize);
00261
00262 if ( du == 0 )
00263 du = new Vector(systemSize);
00264
00265 if ( b == 0 )
00266 b = new Vector(systemSize);
00267
00268 localTest->start();
00269
00270 int nBFGS = 1;
00271 do {
00272
00273
00274 *residNew = theSOE->getB( );
00275 *residNew *= (-1.0 );
00276
00277
00278
00279 if (theSOE->solve() < 0) {
00280 opserr << "WARNING BFGS::solveCurrentStep() -";
00281 opserr << "the LinearSysOfEqn failed in solve()\n";
00282 return -3;
00283 }
00284
00285
00286 *b = theSOE->getB( );
00287
00288
00289 *du = theSOE->getX( );
00290
00291
00292 BFGSUpdate( theIntegrator, theSOE, *du, *b, nBFGS ) ;
00293
00294 if ( theIntegrator->update( *du ) < 0 ) {
00295 opserr << "WARNING BFGS::solveCurrentStep() -";
00296 opserr << "the Integrator failed in update()\n";
00297 return -4;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 nBFGS += 1;
00307
00308
00309 if ( s[nBFGS] == 0 )
00310 s[nBFGS] = new Vector(systemSize);
00311
00312 *s[nBFGS] = *du;
00313
00314
00315 *residOld = *residNew;
00316
00317
00318 if (theIntegrator->formUnbalance() < 0) {
00319 opserr << "WARNING BFGS::solveCurrentStep() -";
00320 opserr << "the Integrator failed in formUnbalance()\n";
00321 }
00322
00323 result = localTest->test();
00324
00325
00326 } while ( result == -1 && nBFGS <= numberLoops );
00327
00328
00329 result = theTest->test();
00330 this->record(count++);
00331
00332 } while (result == -1);
00333
00334
00335 if (result == -2) {
00336 opserr << "BFGS::solveCurrentStep() -";
00337 opserr << "the ConvergenceTest object failed in test()\n";
00338 return -3;
00339 }
00340
00341
00342
00343 return result;
00344 }
00345
00346
00347
00348 void BFGS::BFGSUpdate(IncrementalIntegrator *theIntegrator,
00349 LinearSOE *theSOE,
00350 Vector &du,
00351 Vector &b,
00352 int nBFGS)
00353 {
00354
00355 static const double eps = 1.0e-16;
00356
00357
00358 int systemSize = theSOE->getNumEqn( );
00359
00360
00361
00362
00363
00364 *temp = *residNew;
00365 *temp -= *residOld;
00366 theSOE->setB(*temp);
00367
00368
00369 if (theSOE->solve() < 0) {
00370 opserr << "WARNING BFGS::solveCurrentStep() -";
00371 opserr << "the LinearSysOfEqn failed in solve()\n";
00372 }
00373
00374 if ( z[nBFGS] == 0 )
00375 z[nBFGS] = new Vector(systemSize);
00376
00377 *z[nBFGS] = theSOE->getX();
00378
00379
00380 int i;
00381 for ( i=1; i<=(nBFGS-1); i++ ) {
00382
00383 if ( sdotr[i] < eps )
00384 break;
00385
00386 double fact1 = 1.0 + ( rdotz[i] / sdotr[i] );
00387
00388 fact1 /= sdotr[i];
00389
00390 double pdotb = (*s[i]) ^ ( theSOE->getB() );
00391
00392
00393 fact1 *= pdotb;
00394
00395
00396 *temp = *s[i];
00397 *temp *= fact1;
00398 *z[nBFGS] += *temp;
00399
00400
00401 double bdotz = (*z[i]) ^ ( theSOE->getB() );
00402
00403
00404
00405 *temp = *s[i];
00406 *temp *= bdotz;
00407 *temp /= sdotr[i];
00408 *z[nBFGS] -= *temp;
00409
00410 *temp = *z[i];
00411 *temp *= pdotb;
00412 *temp /= sdotr[i];
00413 *z[nBFGS] -= *temp;
00414
00415 }
00416
00417
00418
00419
00420
00421
00422 *temp = *residNew;
00423 *temp -= *residOld;
00424
00425 sdotr[nBFGS] = *s[nBFGS] ^ (*temp);
00426
00427 rdotz[nBFGS] = *z[nBFGS] ^ (*temp);
00428
00429
00430
00431 for ( i=1; i<=nBFGS; i++ ) {
00432
00433 if ( sdotr[i] < eps )
00434 break;
00435
00436 double fact1 = 1.0 + ( rdotz[i] / sdotr[i] );
00437
00438 fact1 /= sdotr[i];
00439
00440 double sdotb = (*s[i]) ^ b;
00441
00442 fact1 *= sdotb;
00443
00444
00445 *temp = *s[i];
00446 *temp *= fact1;
00447 du += *temp;
00448
00449
00450 double bdotz = (*z[i]) ^ b;
00451
00452
00453
00454 *temp = *s[i];
00455 *temp *= bdotz;
00456 *temp /= sdotr[i];
00457 du -= *temp;
00458
00459 *temp = *z[i];
00460 *temp *= sdotb;
00461 *temp /= sdotr[i];
00462 du -= *temp;
00463
00464
00465 }
00466
00467 }
00468
00469
00470 ConvergenceTest *
00471 BFGS::getConvergenceTest(void)
00472 {
00473 return theTest;
00474 }
00475
00476 int
00477 BFGS::sendSelf(int cTag, Channel &theChannel)
00478 {
00479 return -1;
00480 }
00481
00482 int
00483 BFGS::recvSelf(int cTag,
00484 Channel &theChannel,
00485 FEM_ObjectBroker &theBroker)
00486 {
00487 return -1;
00488 }
00489
00490
00491 void
00492 BFGS::Print(OPS_Stream &s, int flag)
00493 {
00494 if (flag == 0) {
00495 s << "BFGS" << endln;
00496 s << " Number of Iterations = " << numberLoops << endln;
00497 }
00498 }