Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

NewtonLineSearch.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.2 $
00022 // $Date: 2000/12/14 08:39:40 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/algorithm/equiSolnAlgo/NewtonLineSearch.cpp,v $
00024 
00025 // Written: fmk 
00026 // Created: 11/96 
00027 // Modified: Ed "C++" Love 10/00 to perform the line search
00028 //
00029 // Description: This file contains the implementation for NewtonLineSearch. 
00030 // 
00031 // What: "@(#)NewtonLineSearch.h, revA"
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 //Null Constructor
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 //Constructor 
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 // Destructor
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     // set up some pointers and check they are valid
00097     // NOTE this could be taken away if we set Ptrs as protecetd in superclass
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     // check that the vectors we have are of correct size
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       } // end if 
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       } // end if
00140 
00141   } // end if 
00142 
00143 
00144     // set itself as the ConvergenceTest objects EquiSolnAlgo
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     // create some references to the vector pointers
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  //residual at this iteration before next solve 
00168  Resid0 = theSOE->getB() ;
00169 
00170  
00171  //form the tangent
00172         if (theIntegrator->formTangent() < 0){
00173      cerr << "WARNING NewtonLineSearch::solveCurrentStep() -";
00174      cerr << "the Integrator failed in formTangent()\n";
00175      return -1;
00176  }      
00177  
00178  //solve 
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  //line search direction 
00187  dx0 = theSOE->getX() ;
00188 
00189  //intial value of s
00190  double s0 = - (dx0 ^ Resid0) ; //what is this bullshit 
00191                                 //inner product notation ?
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  //new residual 
00207         const Vector &Resid = theSOE->getB() ;
00208 
00209  //new value of s 
00210  double s = - ( dx0 ^ Resid ) ;
00211 
00212  //intialize r = ratio of residuals 
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  if  ( r <= tolerance )
00223      cerr << "Line Search Not Required : ";
00224      cerr << "Residual Decrease Less Than Tolerance" << endl;
00225         else
00226      cerr << "Line Search, Iteration " << 0 
00227           << " : Ratio |s/s0| = " << r 
00228           << endl ;
00229  ***************************************/
00230  
00231  double eta = 1.0 ; //initial value of line search parameter
00232 
00233  int count = 0 ; //intial value of iteration counter 
00234 
00235  dxOld = dx0 ;
00236 
00237        
00238  while ( r > tolerance  &&  count < 10 ) {
00239  
00240      count++ ;
00241 
00242      eta *=  -s0 / (s - s0) ; 
00243 
00244             //-- I don't know if these should be here-----
00245      if ( eta > 10.0 )  eta = 10.0 ;
00246      if (   r > r0   )  eta =  1.0 ;
00247      //--------------------------------------------
00248      
00249      //dx = ( eta * dx0 ) ; 
00250      dx = dx0 ; 
00251      dx *= eta ;
00252      //Dr. Francis Thomas McKenna wants to save one Vector constructor call
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      //new residual
00267      const Vector &ResidI = theSOE->getB() ;
00268 
00269      //new value of s
00270      s = - ( dx0 ^ ResidI ) ;
00271 
00272      //new value of r 
00273      r = fabs( s / s0 ) ; 
00274 
00275      cerr << "Line Search, Iteration " << count 
00276    << " : Ratio |s/s0| = " << r << endl ;
00277 
00278      //swap increments 
00279      dxOld = dx ; 
00280 
00281      if ( count == 10 ) 
00282   cerr << "Line Search Terminated After 10 Iterations" << endl ;
00283      
00284  } //end while
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     // note - if postive result we are returning what the convergence test returned
00298     // which should be the number of iterations
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 
Copyright Contact Us