Broyden.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.4 $
00022 // $Date: 2005/11/29 22:42:41 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/algorithm/equiSolnAlgo/Broyden.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: Ed C++ Love
00027 // Created: 04/01
00028 
00029 // Description: This file contains the class definition implementation of
00030 // Broyden.  
00031 // 
00032 // What: "@(#)Broyden.h, revA"
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 // Constructor
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     //r[i] = 0 ;
00063   }
00064 
00065   localTest = 0 ;
00066 
00067 }
00068 
00069 //Constructor
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 // Destructor
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   } //end for i
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     // set up some pointers and check they are valid
00153     // NOTE this could be taken away if we set Ptrs as protecetd in superclass
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     // set itself as the ConvergenceTest objects EquiSolnAlgo
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       // opserr << "      Broyden -- Forming New Tangent" << endln ;
00183 
00184       //form the initial tangent
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       //form the initial residual 
00192       if (theIntegrator->formUnbalance() < 0) {
00193         opserr << "WARNING Broyden::solveCurrentStep() -";
00194         opserr << "the Integrator failed in formUnbalance()\n"; 
00195       }     
00196 
00197       //solve
00198       if (theSOE->solve() < 0) {
00199           opserr << "WARNING Broyden::solveCurrentStep() -";
00200           opserr << "the LinearSysOfEqn failed in solve()\n";   
00201           return -3;
00202         }           
00203 
00204       //update
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       //    int systemSize = ( theSOE->getB() ).Size();
00212       int systemSize = theSOE->getNumEqn( ) ;
00213 
00214       //temporary vector
00215       if ( temp == 0 ) 
00216         temp = new Vector(systemSize) ;
00217 
00218       //initial displacement increment
00219       if ( s[1] == 0 ) 
00220         s[1] = new Vector(systemSize) ;
00221 
00222       *s[1] = theSOE->getX( ) ;
00223 
00224       //initial residual
00225       /* if ( r[0] == 0 ) r[0] = new Vector(systemSize) ;
00226       *r[0] = theSOE->getB( )  ;
00227       *r[0] *= (-1.0 ) ;
00228       */
00229 
00230       if ( residOld == 0 ) 
00231         residOld = new Vector(systemSize) ;
00232 
00233       *residOld = theSOE->getB( )  ;
00234       *residOld *= (-1.0 ) ;
00235 
00236       //form the residual again
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         //save residual
00255         /*        if ( r[nBroyden] == 0 ) r[nBroyden] = new Vector(systemSize) ;
00256         *r[nBroyden] =  theSOE->getB( ) ; 
00257         *r[nBroyden] *= (-1.0 ) ; 
00258         */
00259 
00260         *residNew =  theSOE->getB( ) ; 
00261         *residNew *= (-1.0 ) ;
00262       
00263         //solve
00264         if (theSOE->solve() < 0) {
00265             opserr << "WARNING Broyden::solveCurrentStep() -";
00266             opserr << "the LinearSysOfEqn failed in solve()\n"; 
00267             return -3;
00268         }           
00269 
00270         //save displacement increment
00271         *du = theSOE->getX( ) ;
00272 
00273         //broyden modifications to du
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         /*      opserr << "        Broyden Iteration " << nBroyden 
00284             << " Residual Norm = " 
00285             << sqrt( (*residNew) ^ (*residNew) ) << endln ;
00286         */
00287         
00288         //increment broyden counter
00289         nBroyden += 1 ;
00290 
00291         //save displacement increment
00292         if ( s[nBroyden] == 0 ) 
00293           s[nBroyden] = new Vector(systemSize) ;
00294 
00295         *s[nBroyden] = *du ;
00296 
00297         //swap residuals
00298         *residOld = *residNew ;
00299 
00300         //form the residual again
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     // note - if postive result we are returning what the convergence test returned
00325     // which should be the number of iterations
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   //  int systemSize = ( theSOE->getB() ).Size();
00340       int systemSize = theSOE->getNumEqn( ) ;
00341 
00342 
00343   //compute z
00344   //  theSOE->setB( (*r[nBroyden]) - (*r[nBroyden-1]) ) ;
00345   //    theSOE->setB( (*residNew) - (*residOld) ) ;
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     //*z[nBroyden] += (1.0/p) * sdotz * ( *s[i] + *z[i] ) ;
00371     *temp  = (*s[i]) ;
00372     *temp += (*z[i]) ;
00373     *temp *= ( (1.0/p) * sdotz ) ;
00374     *z[nBroyden] += (*temp) ;
00375 
00376 
00377   } //end for i
00378 
00379 
00380   //broyden modifications to du
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     //du += (1.0/p) * sdotdu * ( *s[i] + *z[i] ) ;
00390     *temp  = (*s[i]) ;
00391     *temp += (*z[i]) ;
00392     *temp *= ( (1.0/p) * sdotdu ) ;
00393     du += (*temp) ;
00394 
00395 
00396   } //end for i
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 //const Vector &pi = *p[i] ;
00433 
00434 //    //residual at this iteration before next solve 
00435 //    Resid0 = theSOE->getB() ;
00436 
00437 //    //line search direction 
00438 //    dx0 = theSOE->getX() ;
00439 
00440 
00441 
00442 
00443 
00444 /*
00445 
00446         //first solve step
00447 
00448         if (theIntegrator->formTangent(tangent) < 0){
00449             opserr << "WARNING Broyden::solveCurrentStep() -";
00450             opserr << "the Integrator failed in formTangent()\n";
00451             return -1;
00452         }                   
00453         
00454         if (theSOE->solve() < 0) {
00455             opserr << "WARNING Broyden::solveCurrentStep() -";
00456             opserr << "the LinearSysOfEqn failed in solve()\n"; 
00457             return -3;
00458         }           
00459 
00460 
00461         if (theIntegrator->update(theSOE->getX()) < 0) {
00462             opserr << "WARNING Broyden::solveCurrentStep() -";
00463             opserr << "the Integrator failed in update()\n";    
00464             return -4;
00465         }               
00466 
00467 
00468         if (theIntegrator->formUnbalance() < 0) {
00469             opserr << "WARNING Broyden::solveCurrentStep() -";
00470             opserr << "the Integrator failed in formUnbalance()\n";     
00471             return -2;
00472         }       
00473         
00474         result = theTest->test();
00475         this->record(nBroyden++);
00476 
00477       const Vector &du = BroydengetX( theIntegrator, theSOE, nBroyden )  ;
00478 
00479 */

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