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