SQPsearchDirectionMeritFunctionAndHessian.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.3 $
00026 // $Date: 2003/10/27 23:45:42 $
00027 // $Source: /usr/local/cvs/OpenSees/SRC/reliability/analysis/direction/SQPsearchDirectionMeritFunctionAndHessian.cpp,v $
00028 
00029 
00030 //
00031 // Written by Terje Haukaas (haukaas@ce.berkeley.edu) 
00032 //
00033 
00034 #include <SQPsearchDirectionMeritFunctionAndHessian.h>
00035 #include <SearchDirection.h>
00036 #include <MeritFunctionCheck.h>
00037 #include <HessianApproximation.h>
00038 #include <MatrixOperations.h>
00039 #include <Vector.h>
00040 
00041 
00042 SQPsearchDirectionMeritFunctionAndHessian::SQPsearchDirectionMeritFunctionAndHessian(
00043                                                                                                                         double pc_bar, 
00044                                                                                                                         double pe_bar)
00045 :SearchDirection(), MeritFunctionCheck(), HessianApproximation()
00046 {
00047         theHessianApproximation = 0;
00048 
00049         // Parameters
00050         alpha = 0.0;
00051         c_bar = pc_bar;
00052         e_bar = pe_bar;
00053 
00054 
00055         // History variables
00056         B = 0;
00057         delta = 1.0;
00058         c = c_bar;
00059         lambda = 1.0;
00060 
00061 
00062         // Check parameters
00063         if (c_bar < 1.0) {
00064                 opserr << "ERROR: Parameter c_bar in SQP algorithm is invalid." << endln;
00065         }
00066         if (e_bar > 1.0) {
00067                 opserr << "ERROR: Parameter e_bar in SQP algorithm is invalid." << endln;
00068         }
00069 }
00070 
00071 SQPsearchDirectionMeritFunctionAndHessian::~SQPsearchDirectionMeritFunctionAndHessian()
00072 {
00073         if (B != 0) 
00074                 delete B;
00075 }
00076 
00077 
00078 int
00079 SQPsearchDirectionMeritFunctionAndHessian::setHessianApproximation(HessianApproximation *passedHessianApproximation)
00080 {
00081         theHessianApproximation = passedHessianApproximation;
00082         return 0;
00083 }
00084 
00085 
00086 
00087 
00088 // SEARCH DIRECTION METHODS
00089 Vector
00090 SQPsearchDirectionMeritFunctionAndHessian::getSearchDirection()
00091 {
00092         return searchDirection;
00093 }
00094 
00095 int
00096 SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection(
00097                                                         int stepNumber,
00098                                                         Vector u, 
00099                                                         double g, 
00100                                                         Vector gradG )
00101 {
00102         // Initial declarations
00103         int i,j;
00104 
00105 
00106         // Number of random variables in the problem
00107         int nrv = u.Size();
00108 
00109 
00110         // If it's the first step; set the Hessian approximation to unity
00111         // and initialize history parameters. 
00112         if (stepNumber == 1) {
00113                 if (theHessianApproximation != 0) {
00114                         theHessianApproximation->setHessianToIdentity(nrv);
00115                 }
00116                 else {
00117                         opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection() -- " << endln
00118                                 << "theHessianApproximation has not been set! " << endln;
00119                 }
00120                 delta = 1.0;
00121                 c = c_bar;
00122                 lambda = 1.0;
00123         }
00124 
00125 
00126         // Get the Hessian approximation
00127         Matrix Hessian;
00128         if (theHessianApproximation != 0) {
00129                 Hessian = theHessianApproximation->getHessianApproximation();
00130         }
00131         else {
00132                 opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection() -- " << endln
00133                         << "theHessianApproximation has not been set! " << endln;
00134         }
00135 
00136         
00137         // Establish coefficient matrix
00138         Matrix A((nrv+1),(nrv+1));
00139         for (i=0; i<(nrv+1); i++) {
00140                 for (j=0; j<(nrv+1); j++) {
00141                         if (i==nrv && j==nrv) {
00142                                 A(i,j) = 0.0;
00143                         }
00144                         else {
00145                                 if (i<nrv && j<nrv) {
00146                                         A(i,j) = Hessian(i,j);
00147                                 }
00148                                 else if (i==nrv) {
00149                                         A(i,j) = gradG(j);
00150                                 }
00151                                 else {
00152                                         A(i,j) = gradG(i);
00153                                 }
00154                         }
00155                 }
00156         }
00157 
00158 
00159         // Establish right-hand side vector
00160         Vector b(nrv+1);
00161         for (i=0; i<nrv; i++) {
00162                 b(i) = -u(i);
00163         }
00164         b(nrv) = -g;
00165 
00166 
00167         // Solve the system of equations by computing inverse (this should be done more efficiently!)
00168         MatrixOperations theMatrixOperations(A);
00169         theMatrixOperations.computeInverse();
00170         Matrix invA = theMatrixOperations.getInverse();
00171         Vector dAndKappa = invA ^ b;
00172 
00173 
00174         // Separate out direction vector and kappa value
00175         Vector d(nrv);
00176         for (i=0; i<nrv; i++) {
00177                 d(i) = dAndKappa(i);
00178         }
00179         kappa = dAndKappa(nrv);
00180         searchDirection = d;
00181         
00182 
00183 
00184 
00185 
00186 
00187         // Compute product d*B*d and dd
00188         Vector temp2 = Hessian ^ searchDirection;
00189         double dBd = temp2 ^ searchDirection;
00190         double dd = searchDirection^searchDirection;
00191 
00192 
00193         // Update the history parameter 'delta'
00194         double term1 = dBd/dd;
00195         if ( term1 < delta ) {
00196                 delta = term1;
00197         }
00198 
00199 
00200         // Compute 'e' (needed to compute 'i')
00201         double e;
00202         if ( fabs(kappa-lambda)<1.0e-9 ) {
00203                 e = e_bar;
00204         }
00205         else {
00206                 e = dd / ((kappa-lambda)*(kappa-lambda));
00207         }
00208 
00209 
00210         // Compute 'i' (needed to compute 'c')
00211         double iii = -ceil(log(0.25*e*delta*(1-0.25*delta))/log(c_bar));
00212         if (iii < 0) {
00213                 iii = 0;
00214         }
00215 
00216 
00217         // Update history parameter 'c'
00218         term1 = pow(c_bar,iii);
00219         if ( c < term1 ) {
00220                 c = term1;
00221         }
00222 
00223         return 0;
00224 }
00225 
00226 
00227 double 
00228 SQPsearchDirectionMeritFunctionAndHessian::getMeritFunctionValue(Vector u, double g, Vector grad_G)
00229 {
00230         opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::getMeritFunctionValue() --" << endln
00231                 << " no explicit merit function value is computed." << endln;
00232         return 0.0;
00233 }
00234 
00235 
00236 
00237 int
00238 SQPsearchDirectionMeritFunctionAndHessian::updateMeritParameters(Vector u, double g, Vector grad_G)
00239 {
00240         opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::updateMeritParameters() --" << endln
00241                 << " no explicit merit function value is computed." << endln;
00242 
00243         return 0;
00244 }
00245 
00246 
00247 
00248 int
00249 SQPsearchDirectionMeritFunctionAndHessian::check(Vector u_old, 
00250                                                                                   double g_old, 
00251                                                                                   Vector grad_G_old, 
00252                                                                                   double stepSize,
00253                                                                                   Vector stepDirection,
00254                                                                                   double g_new)
00255 {
00256         // Have 'c' and 'delta' and 'lambda' as history parameters
00257         // and 'kappa' stored to be used in this method
00258 
00259 
00260         // Initial declarations
00261         int i;
00262 
00263         // Problem size
00264         int nrv = u_old.Size();
00265 
00266 
00267         // New point in standard normal space
00268         Vector u_new = u_old + stepSize*stepDirection;
00269 
00270 
00271         // Check that the factor alpha is set (since this is a dual purpose class...)
00272         if (alpha == 0.0) {
00273                 opserr << "ERROR: SQPsearchDirectionMeritFunctionAndHessian::check()" << endln
00274                         << " the alpha factor is not set! " << endln;
00275         }
00276 
00277 
00278         // Left side of merit function check
00279         double tempNewLambda = lambda+stepSize*(kappa-lambda);
00280         double LHS = 0.5*(u_new^u_new) + tempNewLambda*g_new + 0.5*c*g_new*g_new;
00281 
00282 
00283         // Right side of merit function check
00284         double term1 = 0.5*(u_old^u_old) + lambda*g_old + 0.5*c*g_old*g_old;
00285         Vector gradient = u_old + lambda*grad_G_old + (c*g_old)*grad_G_old;
00286         Vector extendedGradient(nrv+1);
00287         for (i=0; i<nrv; i++) {
00288                 extendedGradient(i) = gradient(i);
00289         }
00290         extendedGradient(nrv) = g_old;
00291         Vector extendedDirection(nrv+1);
00292         for (i=0; i<nrv; i++) {
00293                 extendedDirection(i) = stepDirection(i);
00294         }
00295         extendedDirection(nrv) = (kappa-lambda);
00296 //      double RHS = term1 + alpha*stepSize*(extendedGradient^extendedDirection);
00297 //      (Maybe use absolute value of 'g' and 'kappa-lambda'?)
00298         double RHS = term1 + alpha*stepSize*(gradient^stepDirection);
00299 
00300         // Do the check
00301         if (  LHS  <=  RHS ) {
00302                 return 0;  // ok
00303         }
00304         else {
00305                 return -1; // not ok
00306         }
00307 
00308 }
00309 
00310 
00311 
00312 
00313 
00314 int
00315 SQPsearchDirectionMeritFunctionAndHessian::setAlpha(double palpha)
00316 {
00317         alpha = palpha;
00318 
00319         if (alpha > 0.5) {
00320                 opserr << "ERROR: Parameter alpha in SQP algorithm is invalid." << endln;
00321         }
00322 
00323         return 0;
00324 }
00325 
00326 
00327 
00328 Matrix
00329 SQPsearchDirectionMeritFunctionAndHessian::getHessianApproximation()
00330 {
00331         return (*B);
00332 }
00333 
00334 int
00335 SQPsearchDirectionMeritFunctionAndHessian::updateHessianApproximation(Vector u_old,
00336                                                                                                           double g_old,
00337                                                                                                           Vector gradG_old,
00338                                                                                                           double stepSize,
00339                                                                                                           Vector searchDirection,
00340                                                                                                           double g_new,
00341                                                                                                           Vector gradG_new)
00342 {
00343         if (B == 0) {
00344                 this->setHessianToIdentity(u_old.Size());
00345         }
00346 
00347         // Initial declarations
00348         int i,j;
00349 
00350         // Re-compute the new point in the standard normal space
00351         Vector u_new = u_old + stepSize * searchDirection;
00352 
00353 
00354         // The gradient of the Lagrangian (the old one)
00355         Vector gradL_old = u_old + lambda*gradG_old;
00356 
00357 
00358         // At this point we should update the lambda (the Lagrangian multiplier)
00359         lambda = lambda + stepSize * (kappa-lambda);
00360 
00361 
00362         // The gradient of the Lagrangian (the new one)
00363         Vector gradL_new = u_new + lambda*gradG_new;
00364 
00365 
00366         // Computations to obtain the vector 'q'
00367         Vector qPrime = gradL_new - gradL_old;
00368         
00369         Vector temp2 = (*B) ^ searchDirection;
00370 
00371         double dBd = temp2 ^ searchDirection ;
00372 
00373         double dqPrime = searchDirection ^ qPrime;
00374 
00375         double theta;
00376         if (dqPrime >= 0.2*stepSize*dBd) {
00377                 theta = 1.0;
00378         }
00379         else {
00380                 theta = (0.8*stepSize*dBd) / (stepSize*dBd-dqPrime);
00381         }
00382         Vector q = theta*qPrime + (1-theta)*stepSize*((*B)^searchDirection);
00383 
00384 
00385         // Update the Hessian approximation
00386         Vector Bd = (*B)^searchDirection;
00387         int nrv = Bd.Size();
00388         Matrix Bdd(nrv,nrv);
00389         for (i=0; i<nrv; i++) {
00390                 for (j=0; j<nrv; j++) {
00391                         Bdd(i,j) = Bd(i)*searchDirection(j);
00392                 }
00393         }
00394         Matrix BddB = Bdd*(*B);
00395         Matrix qq(nrv,nrv);
00396         for (i=0; i<nrv; i++) {
00397                 for (j=0; j<nrv; j++) {
00398                         qq(i,j) = q(i)*q(j);
00399                 }
00400         }
00401         Matrix newB = (*B) + 1.0/(stepSize*(q^searchDirection))*(qq) - (1.0/(dBd))*(BddB);
00402         (*B) = newB;
00403 
00404 
00405         return 0;
00406 }
00407 
00408 
00409 
00410 
00411 int
00412 SQPsearchDirectionMeritFunctionAndHessian::setHessianToIdentity(int size)
00413 {
00414 
00415         // Check that is exists
00416         if (B == 0) {
00417                 B = new Matrix(size,size);
00418         }
00419 
00420         // Set it to unity
00421         for (int i=0; i<size; i++) {
00422                 for (int j=0; j<size; j++) {
00423                         if (i==j) {
00424                                 (*B)(i,j) = 1.0;
00425                         }
00426                         else {
00427                                 (*B)(i,j) = 0.0;
00428                         }
00429                 }
00430         }
00431 
00432         return 0;
00433 }

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