ArmijoStepSizeRule.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 2001, 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 ** Reliability module developed by:                                   **
00020 **   Terje Haukaas (haukaas@ce.berkeley.edu)                          **
00021 **   Armen Der Kiureghian (adk@ce.berkeley.edu)                       **
00022 **                                                                    **
00023 ** ****************************************************************** */
00024                                                                         
00025 // $Revision: 1.2 $
00026 // $Date: 2003/10/27 23:45:44 $
00027 // $Source: /usr/local/cvs/OpenSees/SRC/reliability/analysis/stepSize/ArmijoStepSizeRule.cpp,v $
00028 
00029 
00030 //
00031 // Written by Terje Haukaas (haukaas@ce.berkeley.edu)
00032 //
00033 
00034 #include <ArmijoStepSizeRule.h>
00035 #include <GFunEvaluator.h>
00036 #include <StepSizeRule.h>
00037 #include <ProbabilityTransformation.h>
00038 #include <MeritFunctionCheck.h>
00039 #include <RootFinding.h>
00040 #include <math.h>
00041 #include <Vector.h>
00042 
00043 #include <fstream>
00044 #include <iomanip>
00045 #include <iostream>
00046 using std::ifstream;
00047 using std::ios;
00048 using std::setw;
00049 using std::setprecision;
00050 using std::setiosflags;
00051 
00052 ArmijoStepSizeRule::ArmijoStepSizeRule( GFunEvaluator *passedGFunEvaluator,
00053                                                 ProbabilityTransformation *passedProbabilityTransformation,
00054                                                 MeritFunctionCheck *passedMeritFunctionCheck,
00055                                                 RootFinding *passedRootFindingAlgorithm, 
00056                                                 double Pbase,
00057                                                 int    PmaxNumReductions,
00058                                                 double Pb0,
00059                                                 int    PnumberOfShortSteps,
00060                                                 double Pradius,
00061                                                 double PsurfaceDistance,
00062                                                 double Pevolution,
00063                                                 int pprintFlag)
00064 :StepSizeRule()
00065 {
00066         theGFunEvaluator = passedGFunEvaluator;
00067         theProbabilityTransformation = passedProbabilityTransformation;
00068         theMeritFunctionCheck = passedMeritFunctionCheck;
00069         theRootFindingAlgorithm = passedRootFindingAlgorithm;
00070         gFunValue = 0;
00071         base = Pbase; 
00072         maxNumReductions = PmaxNumReductions; 
00073         b0 = Pb0; 
00074         numberOfShortSteps = PnumberOfShortSteps; 
00075         radius = Pradius; 
00076         surfaceDistance = PsurfaceDistance; 
00077         evolution = Pevolution; 
00078         isCloseToSphere = false;
00079         printFlag = pprintFlag;
00080 }
00081 
00082 ArmijoStepSizeRule::~ArmijoStepSizeRule()
00083 {
00084 }
00085 
00086 
00087 
00088 double 
00089 ArmijoStepSizeRule::getStepSize()
00090 {
00091         return stepSize;
00092 }
00093 
00094 
00095 
00096 double 
00097 ArmijoStepSizeRule::getInitialStepSize()
00098 {
00099         return b0;
00100 }
00101 
00102 
00103 
00104 double 
00105 ArmijoStepSizeRule::getGFunValue()
00106 {
00107         return gFunValue;
00108 }
00109 
00110 
00111 int
00112 ArmijoStepSizeRule::computeStepSize(Vector u_old, 
00113                                                                         Vector grad_G_old, 
00114                                                                         double g_old, 
00115                                                                         Vector dir_old,
00116                                                                         int stepNumber)
00117 {
00118 
00119         // Initial declarations
00120         bool isOutsideSphere;
00121         bool isSecondTime;
00122         bool FEconvergence;
00123         double result;
00124         Vector x_new;
00125         Matrix jacobian_x_u;
00126 
00127 
00128         // Inform user through log file
00129         static ofstream logfile( "ArmijoRuleLog.txt", ios::out );
00130         logfile << "Entering the Armijo rule to compute step size ..." << endln;
00131         logfile.flush();
00132         
00133         
00134         // Check that the norm of the gradient is not zero
00135         double gradNorm = grad_G_old.Norm();
00136         if (gradNorm == 0.0) {
00137                 opserr << "ArmijoStepSizeRule::computeStepSize() - the norm " << endln
00138                         << " of the gradient is zero. " << endln;
00139                 return -1;
00140         }
00141 
00142 
00143         // Check if this potentially could be the second time close to the surface
00144         if (isCloseToSphere) {
00145                 isSecondTime = true;
00146         }
00147         else {
00148                 isSecondTime = false;
00149         }
00150 
00151 
00152         // Set the first trial step size
00153         double lambda_new;
00154         if (stepNumber <= numberOfShortSteps) {
00155                 lambda_new = b0;
00156         }
00157         else {
00158                 lambda_new = 1.0;
00159         }
00160         
00161 
00162         // Take a trial step in standard normal space
00163         Vector u_new = u_old + dir_old * lambda_new;
00164 
00165 
00166         // Inform the user
00167         if (printFlag != 0) {
00168                 opserr << "Armijo starting gFun evaluation at distance " << u_new.Norm() << "..." << endln
00169                         << " .......: ";
00170         }
00171         logfile << "Armijo starting gFun evaluation at distance " << u_new.Norm() << "..." << endln;
00172         logfile.flush();
00173 
00174 
00175         double g_new;
00176         Vector grad_G_new;
00177         if (u_new.Norm()>radius) {
00178 
00179                 isOutsideSphere = true;
00180 
00181                 // Set some dummy values to 'g' and 'gradG'; it doesn't matter
00182                 // that the merit functions then will be 'wrong'; the step will
00183                 // fail in any case because it is outside the sphere. 
00184                 g_new = g_old;
00185                 grad_G_new = grad_G_old;
00186 
00187 
00188                 // Inform the user
00189                 if (printFlag != 0) {
00190                         opserr << "Armijo skipping gFun evaluation because of hyper sphere requirement..." << endln
00191                                 << " .......: ";
00192                 }
00193                 logfile << "Armijo skipping gFun evaluation because of hyper sphere requirement..." << endln;
00194                 logfile.flush();
00195 
00196 
00197         }
00198         else {
00199 
00200                 isOutsideSphere = false;
00201 
00202                 // Register where this u was close to the sphere surface
00203                 if (u_new.Norm() > radius-surfaceDistance  && 
00204                         u_new.Norm() < radius+surfaceDistance) {
00205                         isCloseToSphere = true;
00206                         if (isSecondTime) {
00207                                 radius = radius + evolution;
00208                         }
00209                 }
00210                 else {
00211                         isCloseToSphere = false;
00212                 }
00213 
00214 
00215                 // Transform the trial point into original space
00216                 result = theProbabilityTransformation->set_u(u_new);
00217                 if (result < 0) {
00218                         opserr << "ArmijoStepSizeRule::computeStepSize() - could not set " << endln
00219                                 << " vector u in the xu-transformation. " << endln;
00220                         return -1;
00221                 }
00222                 result = theProbabilityTransformation->transform_u_to_x_andComputeJacobian();
00223                 if (result < 0) {
00224                         opserr << "ArmijoStepSizeRule::computeStepSize() - could not  " << endln
00225                                 << " transform u to x. " << endln;
00226                         return -1;
00227                 }
00228                 x_new = theProbabilityTransformation->get_x();
00229                 jacobian_x_u = theProbabilityTransformation->getJacobian_x_u();
00230 
00231 
00232                 // Evaluate the limit-state function
00233                 FEconvergence = true;
00234                 result = theGFunEvaluator->runGFunAnalysis(x_new);
00235 /*              if (result < 0) {
00236                         // In this case the FE analysis did not converge
00237                         // In this case; do not accept the new point!
00238                         FEconvergence = false;
00239                         opserr << "step size rejected due to non-converged FE analysis ..." << endln
00240                                 << " .......: ";
00241                 }
00242 */              result = theGFunEvaluator->evaluateG(x_new);
00243                 if (result < 0) {
00244                         opserr << "ArmijoStepSizeRule::computeStepSize() - could not  " << endln
00245                                 << " tokenize the limit-state function. " << endln;
00246                         return -1;
00247                 }
00248                 g_new = theGFunEvaluator->getG();
00249 
00250         }
00251 
00252 
00254         // POSSIBLY START REDUCING THE STEP SIZE //
00256         int i = 1;
00257         bool mustGoOn = false;
00258 
00259         if (theMeritFunctionCheck->check(u_old, g_old, grad_G_old, lambda_new, dir_old, g_new)<0) {
00260                 mustGoOn = true;
00261         }
00262         if (!FEconvergence) {
00263                 mustGoOn = true;
00264         }
00265         if (isOutsideSphere) {
00266                 mustGoOn = true;
00267         }
00268         if (i>maxNumReductions) {
00269                 mustGoOn = false;
00270         }
00271 
00272 
00273         while ( mustGoOn ) {
00274 
00275                 
00276                 // Notify user that step sizes are being reduced
00277                 opserr << "Armijo trial point rejected; reducing step size..." << endln
00278                         << " .......: ";
00279                 logfile << "Armijo trial point rejected; reducing step size..." << endln;
00280                 logfile.flush();
00281                 
00282 
00283                 // Cut the step size in half (or whichever base the user has set) and try that instead
00284                 if (stepNumber <= numberOfShortSteps) {
00285                         lambda_new = b0 * pow(base,i);
00286                 }
00287                 else {
00288                         lambda_new = pow(base,i);
00289                 }
00290                 u_new = u_old + dir_old * lambda_new;
00291 
00292 
00293                 // Check if we are beyond the bounding sphere
00294                 if (u_new.Norm()>radius) {
00295 
00296                         isOutsideSphere = true;
00297 
00298                         // Inform the user
00299                         if (printFlag != 0) {
00300                                 opserr << "Armijo skipping gFun evaluation because of hyper sphere requirement..." << endln
00301                                         << " .......: ";
00302                         }
00303                         logfile << "Armijo skipping gFun evaluation because of hyper sphere requirement..." << endln;
00304                         logfile.flush();
00305                 }
00306                 else {
00307 
00308                         isOutsideSphere = false;
00309 
00310                         // Register where this u was close to the sphere surface
00311                         if (u_new.Norm() > radius-surfaceDistance  && 
00312                                 u_new.Norm() < radius+surfaceDistance) {
00313                                 isCloseToSphere = true;
00314                                 if (isSecondTime) {
00315                                         radius = radius + evolution;
00316                                 }
00317                         }
00318                         else {
00319                                 isCloseToSphere = false;
00320                         }
00321                 
00322                         if (printFlag != 0) {
00323                                 opserr << "Armijo starting gFun evaluation at distance " << u_new.Norm() << "..." << endln
00324                                         << " .......: ";
00325                         }
00326                         logfile << "Armijo starting gFun evaluation at distance " << u_new.Norm() << "..." << endln;
00327 
00328                         // Transform the trial point into original space
00329                         double result = theProbabilityTransformation->set_u(u_new);
00330                         if (result < 0) {
00331                                 opserr << "ArmijoStepSizeRule::computeStepSize() - could not set " << endln
00332                                         << " vector u in the xu-transformation. " << endln;
00333                                 return -1;
00334                         }
00335                         result = theProbabilityTransformation->transform_u_to_x_andComputeJacobian();
00336                         if (result < 0) {
00337                                 opserr << "ArmijoStepSizeRule::computeStepSize() - could not  " << endln
00338                                         << " transform u to x. " << endln;
00339                                 return -1;
00340                         }
00341                         x_new = theProbabilityTransformation->get_x();
00342                         jacobian_x_u = theProbabilityTransformation->getJacobian_x_u();
00343 
00344 
00345                         // Evaluate the limit-state function
00346                         FEconvergence = true;
00347                         result = theGFunEvaluator->runGFunAnalysis(x_new);
00348 /*                      if (result < 0) {
00349                                 // In this case the FE analysis did not converge
00350                                 // May still accept the new point!
00351                                 FEconvergence = false;
00352                                 opserr << "step size rejected due to non-converged FE analysis ..." << endln
00353                                         << " .......: ";
00354                                 logfile << "step size rejected due to non-converged FE analysis ..." << endln;
00355                         }
00356 */                      result = theGFunEvaluator->evaluateG(x_new);
00357                         if (result < 0) {
00358                                 opserr << "ArmijoStepSizeRule::computeStepSize() - could not  " << endln
00359                                         << " tokenize the limit-state function. " << endln;
00360                                 return -1;
00361                         }
00362                         g_new = theGFunEvaluator->getG();
00363 
00364 
00365                         // Possibly project the point onto the limit-state surface
00366                         // (it is assumed that the user has provided a projection object 
00367                         // if this is to be done)
00368                         // Note that this has effect on the previously computed search direction
00369                         // because the new values of the performance function and its gradient
00370                         // is being used...
00371                         // Q: Is the u_new point also being kept in the orchestrating algorithm?
00372                         if (theRootFindingAlgorithm != 0) {
00373                                 theRootFindingAlgorithm->findLimitStateSurface(2,g_new, grad_G_old, u_new);
00374                         }
00375                 }
00376 
00377                 // Increment counter
00378                 i++;
00379 
00380                 // Check if we need to go on
00381                 mustGoOn = false;
00382 
00383                 if (theMeritFunctionCheck->check(u_old, g_old, grad_G_old, lambda_new, dir_old, g_new)<0) {
00384                         mustGoOn = true;
00385                 }
00386                 if (!FEconvergence) {
00387                         mustGoOn = true;
00388                 }
00389                 if (isOutsideSphere) {
00390                         mustGoOn = true;
00391                 }
00392                 if (i>maxNumReductions) {
00393                         mustGoOn = false;
00394                 }
00395 
00396         
00397         }
00398 
00399         stepSize = lambda_new;
00400         gFunValue = g_new;
00401 
00402         return 1;
00403 
00404 }

Generated on Mon Oct 23 15:05:25 2006 for OpenSees by doxygen 1.5.0