BisectionLineSearch.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.3 $
00022 // $Date: 2003/04/02 22:02:33 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/algorithm/equiSolnAlgo/BisectionLineSearch.cpp,v $
00024 
00025 // Written: fmk 
00026 // Created: 11/01
00027 // 
00028 // What: "@(#)BisectionLineSearch.h, revA"
00029 
00030 #include <BisectionLineSearch.h>
00031 #include <IncrementalIntegrator.h>
00032 #include <LinearSOE.h>
00033 #include <Channel.h>
00034 #include <FEM_ObjectBroker.h>
00035 #include <Vector.h>
00036 #include <math.h>
00037 
00038 BisectionLineSearch::BisectionLineSearch(double tol, int mIter, double mnEta, double mxEta, int pFlag)
00039 :LineSearch(LINESEARCH_TAGS_BisectionLineSearch),
00040  x(0), tolerance(tol), maxIter(mIter), minEta(mnEta), maxEta(mxEta), printFlag(pFlag)
00041 {   
00042 
00043 }
00044 
00045 BisectionLineSearch::~BisectionLineSearch()
00046 {
00047   if (x != 0)
00048     delete x;
00049 }
00050 
00051 
00052 int 
00053 BisectionLineSearch::newStep(LinearSOE &theSOE)
00054 {
00055   const Vector &dU = theSOE.getX();
00056 
00057   if (x == 0)
00058     x = new Vector(dU);
00059 
00060   if (x->Size() != dU.Size()) {
00061     delete x;
00062     x = new Vector(dU);
00063   }
00064 
00065   return 0;
00066 }
00067 
00068 int 
00069 BisectionLineSearch::search(double s0, 
00070                               double s1, 
00071                               LinearSOE &theSOE, 
00072                               IncrementalIntegrator &theIntegrator)
00073 {
00074   double r0 = 0.0;
00075 
00076   if ( s0 != 0.0 ) 
00077     r0 = fabs( s1 / s0 );
00078         
00079   if  (r0 <= tolerance )
00080     return 0; // Line Search Not Required Residual Decrease Less Than Tolerance
00081 
00082   if (s1 == s0)
00083     return 0;  // Bisection will have a divide-by-zero error if continue
00084 
00085   // set some variables
00086   double eta    = 1.0;
00087   double s      = s1;
00088   double etaU   = 1.0;
00089   double etaL   = 0.0;
00090   double sU     = s1;
00091   double sL     = s0;
00092   double r      = r0;
00093   double etaJ   = 1.0;
00094 
00095   const Vector &dU = theSOE.getX();
00096 
00097   if (printFlag == 0) {
00098     opserr << "Bisection Line Search - initial: " 
00099          << "     eta(0) : " << eta << " , Ratio |sj/s0| = " << r0 << endln;
00100   }
00101 
00102   // we first search for a bracket to a solution, i.e. we want sU * sL < 0.0
00103   int count = 0;
00104   while ((sU * sL > 0.0) && (etaU < maxEta)) {
00105     
00106     count++;
00107     etaU *= 2.0;
00108 
00109     //update the incremental difference in response and determine new unbalance
00110     *x = dU;
00111     *x *= etaU-etaJ;
00112             
00113     if (theIntegrator.update(*x) < 0) {
00114       opserr << "WARNING BisectionLineSearch::search() -";
00115       opserr << "the Integrator failed in update()\n";  
00116       return -1;
00117     }
00118     
00119     if (theIntegrator.formUnbalance() < 0) {
00120       opserr << "WARNING BisectionLineSearch::search() -";
00121       opserr << "the Integrator failed in formUnbalance()\n";   
00122       return -2;
00123     }   
00124 
00125     //new residual
00126     const Vector &ResidJ = theSOE.getB();
00127     
00128     //new value of sU
00129     sU = dU ^ ResidJ;
00130 
00131     // check if we have a solution we are happy with
00132     r = fabs( sU / s0 ); 
00133     if (r < tolerance)
00134       return 0;
00135 
00136     if (printFlag == 0) {
00137       opserr << "Bisection Line Search - bracketing: " << count 
00138            << " , eta(j) : " << etaU << " , Ratio |sj/s0| = " << r << endln;
00139     }
00140 
00141     etaJ = etaU;
00142   }
00143 
00144   // return if no bracket for a solution found, resetting to initial values
00145   if (sU * sL > 0.0) {
00146     *x = dU;
00147     theSOE.setX(*x);
00148     theIntegrator.update(*x);
00149     theIntegrator.formUnbalance();
00150     return 0; 
00151   }
00152 
00153   // perform the secant iterations:
00154   //
00155   //                eta(j+1) = eta(l) + eta(u)
00156   //                           ---------------
00157   //                                2.0
00158 
00159   count = 0; //intial value of iteration counter 
00160   while ( r > tolerance  &&  count < maxIter ) {
00161     
00162     count++;
00163 
00164     eta = (etaU + etaL) * 0.5;
00165 
00166     //-- want to put limits on eta(i)
00167     if (r   > r0    )  eta =  1.0;
00168     
00169     //update the incremental difference in response and determine new unbalance
00170     *x = dU;
00171     *x *= eta-etaJ;
00172             
00173     if (theIntegrator.update(*x) < 0) {
00174       opserr << "WARNING BisectionLineSearch::search() -";
00175       opserr << "the Integrator failed in update()\n";  
00176       return -1;
00177     }
00178     
00179     if (theIntegrator.formUnbalance() < 0) {
00180       opserr << "WARNING BisectionLineSearch::search() -";
00181       opserr << "the Integrator failed in formUnbalance()\n";   
00182       return -2;
00183     }   
00184 
00185     //new residual
00186     const Vector &ResidJ = theSOE.getB();
00187     
00188     //new value of s
00189     s = dU ^ ResidJ;
00190     
00191     //new value of r 
00192     r = fabs( s / s0 ); 
00193 
00194     // set variables for next iteration
00195     etaJ = eta;
00196     
00197     if (s*sU < 0.0) {
00198       etaL = eta;
00199       sL   = s;
00200     } else if (s*sU == 0.0)
00201       count = maxIter;
00202     else {
00203       etaU = eta;
00204       sU   = s;
00205     } 
00206 
00207     if (sL == sU)
00208       count = maxIter;
00209 
00210     if (printFlag == 0) {
00211       opserr << "Bisection Line Search - iteration: " << count 
00212            << " , eta(j) : " << eta << " , Ratio |sj/s0| = " << r << endln;
00213     }
00214     
00215   } //end while
00216 
00217   // set X in the SOE for the revised dU, needed for convergence tests
00218   *x = dU;
00219   *x *= eta;
00220   theSOE.setX(*x);
00221   
00222   return 0;
00223 }
00224 
00225 
00226 int
00227 BisectionLineSearch::sendSelf(int cTag, Channel &theChannel)
00228 {
00229   return 0;
00230 }
00231 
00232 int
00233 BisectionLineSearch::recvSelf(int cTag, 
00234                               Channel &theChannel, 
00235                               FEM_ObjectBroker &theBroker)
00236 {
00237   return 0;
00238 }
00239 
00240 
00241 void
00242 BisectionLineSearch::Print(OPS_Stream &s, int flag)
00243 {
00244   if (flag == 0) {
00245     s << "BisectionLineSearch :: Line Search Tolerance = " << tolerance << endln;
00246     s << "                         max num Iterations = " << maxIter << endln;
00247     s << "                         max value on eta = " << maxEta << endln;
00248   }
00249 }
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 

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