BFGS.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.5 $
00022 // $Date: 2005/11/29 22:42:41 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/algorithm/equiSolnAlgo/BFGS.cpp,v $
00024                                                                         
00025 // Written: Ed Love
00026 // Created: 06/01
00027 
00028 // What: "@(#)BFGS.cpp, revA"
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 // Constructor
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   //  r  = new (Vector*)[numberLoops+3];
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 //Constructor
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     //r[i] = 0;
00092   }
00093 
00094   localTest = theTest->getCopy( this->numberLoops );
00095 
00096 }
00097 
00098 // Destructor
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     //delete r[i];
00127     s[i] = 0;
00128     z[i] = 0;
00129     //r[i] = 0;
00130   } //end for i
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     // set up some pointers and check they are valid
00168     // NOTE this could be taken away if we set Ptrs as protecetd in superclass
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     // set itself as the ConvergenceTest objects EquiSolnAlgo
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       // opserr << "      BFGS -- Forming New Tangent" << endln;
00205 
00206       //form the initial tangent
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       //form the initial residual 
00214       if (theIntegrator->formUnbalance() < 0) {
00215         opserr << "WARNING BFGS::solveCurrentStep() -";
00216         opserr << "the Integrator failed in formUnbalance()\n"; 
00217       }     
00218 
00219       //solve
00220       if (theSOE->solve() < 0) {
00221           opserr << "WARNING BFGS::solveCurrentStep() -";
00222           opserr << "the LinearSysOfEqn failed in solve()\n";   
00223           return -3;
00224         }           
00225 
00226       //update
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       //    int systemSize = ( theSOE->getB() ).Size();
00235       int systemSize = theSOE->getNumEqn( );
00236 
00237       //temporary vector
00238       if (temp == 0 )
00239         temp = new Vector(systemSize);
00240 
00241       //initial displacement increment
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       //form the residual again
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         //save residual
00274         *residNew =  theSOE->getB( ); 
00275         *residNew *= (-1.0 );
00276 
00277       
00278         //solve
00279         if (theSOE->solve() < 0) {
00280             opserr << "WARNING BFGS::solveCurrentStep() -";
00281             opserr << "the LinearSysOfEqn failed in solve()\n"; 
00282             return -3;
00283         }           
00284 
00285         //save right hand side
00286         *b = theSOE->getB( );
00287 
00288         //save displacement increment
00289         *du = theSOE->getX( );
00290 
00291         //BFGS modifications to du
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         /* opserr << "        BFGS Iteration " << nBFGS 
00301             << " Residual Norm = " 
00302             << sqrt( (*residNew) ^ (*residNew) ) << endln;
00303         */
00304         
00305         //increment broyden counter
00306         nBFGS += 1;
00307 
00308         //save displacement increment
00309         if ( s[nBFGS] == 0 ) 
00310           s[nBFGS] = new Vector(systemSize);
00311 
00312         *s[nBFGS] = *du;
00313 
00314         //swap residuals
00315         *residOld = *residNew;
00316 
00317         //form the residual again
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     // note - if postive result we are returning what the convergence test returned
00342     // which should be the number of iterations
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   //  int systemSize = ( theSOE->getB() ).Size();
00358       int systemSize = theSOE->getNumEqn( );
00359 
00360 
00361   //compute z
00362   //  theSOE->setB( (*r[nBFGS]) - (*r[nBFGS-1]) );
00363   //    theSOE->setB( (*residNew) - (*residOld) );
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   //  *z[nBFGS] *= (-1.0);
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     //    *z[nBFGS] +=  fact1 * ( *s[i] );
00396     *temp = *s[i];
00397     *temp *= fact1;
00398     *z[nBFGS] += *temp;
00399 
00400 
00401     double bdotz = (*z[i]) ^ ( theSOE->getB() );  
00402 
00403     //    *z[nBFGS] -= (1.0/sdotr[i]) * 
00404     //             ( bdotz * (*s[i])   +  pdotb * (*z[i]) );   
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   } //end for i
00416 
00417 
00418   //sdotr[nBFGS] = *s[nBFGS] ^ ( *residNew - *residOld );
00419 
00420   //rdotz[nBFGS] = *z[nBFGS] ^ ( *residNew - *residOld );   
00421 
00422   *temp = *residNew;
00423   *temp -= *residOld;
00424 
00425   sdotr[nBFGS] = *s[nBFGS] ^ (*temp);
00426 
00427   rdotz[nBFGS] = *z[nBFGS] ^ (*temp);
00428 
00429 
00430   //BFGS modifications to du
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     //du +=  fact1 * ( *s[i] );
00445     *temp = *s[i];
00446     *temp *= fact1;
00447     du += *temp;
00448 
00449 
00450     double bdotz = (*z[i]) ^ b;  
00451 
00452     //du -= (1.0/sdotr[i]) * 
00453     //             ( bdotz * (*s[i])   +  sdotb * (*z[i]) );   
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   } //end for i
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 }

Generated on Mon Oct 23 15:04:57 2006 for OpenSees by doxygen 1.5.0