FiniteDifferenceGradGEvaluator.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/sensitivity/FiniteDifferenceGradGEvaluator.cpp,v $
00028 
00029 
00030 //
00031 // Written by Terje Haukaas (haukaas@ce.berkeley.edu)
00032 //
00033 
00034 #include <FiniteDifferenceGradGEvaluator.h>
00035 #include <Vector.h>
00036 #include <Matrix.h>
00037 #include <GradGEvaluator.h>
00038 #include <ReliabilityDomain.h>
00039 #include <LimitStateFunction.h>
00040 #include <GFunEvaluator.h>
00041 #include <RandomVariable.h>
00042 #include <tcl.h>
00043 
00044 #include <fstream>
00045 #include <iomanip>
00046 #include <iostream>
00047 using std::ifstream;
00048 using std::ios;
00049 using std::setw;
00050 using std::setprecision;
00051 using std::setiosflags;
00052 
00053 
00054 FiniteDifferenceGradGEvaluator::FiniteDifferenceGradGEvaluator(
00055                                         GFunEvaluator *passedGFunEvaluator,
00056                                         ReliabilityDomain *passedReliabilityDomain,
00057                                         Tcl_Interp *passedTclInterp,
00058                                         double passedPerturbationFactor,
00059                                         bool PdoGradientCheck,
00060                                         bool pReComputeG)
00061 :GradGEvaluator(passedReliabilityDomain, passedTclInterp)
00062 {
00063         theGFunEvaluator = passedGFunEvaluator;
00064         perturbationFactor = passedPerturbationFactor;
00065         doGradientCheck = PdoGradientCheck;
00066         reComputeG = pReComputeG;
00067 
00068         int nrv = passedReliabilityDomain->getNumberOfRandomVariables();
00069         grad_g = new Vector(nrv);
00070         grad_g_matrix = 0;
00071 
00072         DgDdispl = 0;
00073         DgDpar = 0;
00074 }
00075 
00076 FiniteDifferenceGradGEvaluator::~FiniteDifferenceGradGEvaluator()
00077 {
00078         delete grad_g;
00079 
00080         if (DgDdispl != 0)
00081                 delete DgDdispl;
00082         if (DgDpar != 0)
00083                 delete DgDpar;
00084         if (grad_g_matrix != 0)
00085                 delete grad_g_matrix;
00086 }
00087 
00088 
00089 
00090 Vector
00091 FiniteDifferenceGradGEvaluator::getGradG()
00092 {
00093         return (*grad_g);
00094 }
00095 
00096 
00097 
00098 
00099 Matrix
00100 FiniteDifferenceGradGEvaluator::getAllGradG()
00101 {
00102         if (grad_g_matrix==0) {
00103                 Matrix dummy(1,1);
00104                 return dummy;
00105         }
00106         else {
00107                 return (*grad_g_matrix);
00108         }
00109 }
00110 
00111 int
00112 FiniteDifferenceGradGEvaluator::computeGradG(double gFunValue, Vector passed_x)
00113 {
00114         // Call base class method
00115         computeParameterDerivatives(gFunValue);
00116 
00117 
00118         // Possibly re-compute limit-state function value
00119         int result;
00120         if (reComputeG) {
00121                 result = theGFunEvaluator->runGFunAnalysis(passed_x);
00122                 if (result < 0) {
00123                         opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00124                                 << " could not run analysis to evaluate limit-state function. " << endln;
00125                         return -1;
00126                 }
00127                 result = theGFunEvaluator->evaluateG(passed_x);
00128                 if (result < 0) {
00129                         opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00130                                 << " could not tokenize limit-state function. " << endln;
00131                         return -1;
00132                 }
00133                 gFunValue = theGFunEvaluator->getG();
00134         }
00135 
00136 
00137         // Initial declarations
00138         int numberOfRandomVariables = passed_x.Size();
00139         Vector perturbed_x(numberOfRandomVariables);
00140         RandomVariable *theRandomVariable;
00141         int i;
00142         double h;
00143         double gFunValueAStepAhead;
00144         double stdv;
00145 
00146 
00147         // For each random variable: perturb and run analysis again
00148         for ( i=0 ; i<numberOfRandomVariables ; i++ )
00149         {
00150                 // Get random variable from domain
00151                 theRandomVariable = theReliabilityDomain->getRandomVariablePtr(i+1);
00152 
00153 
00154                 // Get the standard deviation
00155                 stdv = theRandomVariable->getStdv();
00156 
00157 
00158                 // Compute perturbation
00159                 h = stdv/perturbationFactor;
00160 
00161 
00162                 // Compute perturbed vector of random variables realization
00163                 perturbed_x = passed_x;
00164                 perturbed_x(i) = perturbed_x(i) + h;
00165 
00166 
00167                 // Evaluate limit-state function
00168                 result = theGFunEvaluator->runGFunAnalysis(perturbed_x);
00169                 if (result < 0) {
00170                         opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00171                                 << " could not run analysis to evaluate limit-state function. " << endln;
00172                         return -1;
00173                 }
00174                 result = theGFunEvaluator->evaluateG(perturbed_x);
00175                 if (result < 0) {
00176                         opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00177                                 << " could not tokenize limit-state function. " << endln;
00178                         return -1;
00179                 }
00180                 gFunValueAStepAhead = theGFunEvaluator->getG();
00181 
00182 
00183                 // Compute the derivative by finite difference
00184                 (*grad_g)(i) = (gFunValueAStepAhead - gFunValue) / h;
00185         }
00186 
00187 
00188         if (doGradientCheck) {
00189                 char myString[100];
00190                 ofstream outputFile( "FFDgradients.out", ios::out );
00191                 opserr << endln;
00192                 for (int ffd=0; ffd<grad_g->Size(); ffd++) {
00193                         opserr << "FFD("<< (ffd+1) << ") = " << (*grad_g)(ffd) << endln;
00194                         sprintf(myString,"%20.16e ",(*grad_g)(ffd));
00195                         outputFile << myString << endln;
00196                 }
00197                 outputFile.close();
00198                 opserr << "PRESS Ctrl+C TO TERMINATE APPLICATION!" << endln;
00199                 while(true) {
00200                 }
00201         }
00202 
00203         return 0;
00204 }
00205 
00206 
00207 
00208 
00209 int
00210 FiniteDifferenceGradGEvaluator::computeAllGradG(Vector gFunValues, Vector passed_x)
00211 {
00212 
00213         // Get number of random variables and performance functions
00214         int nrv = theReliabilityDomain->getNumberOfRandomVariables();
00215         int lsf = theReliabilityDomain->getNumberOfLimitStateFunctions();
00216 
00217 
00218         // Allocate result matrix
00219         if (grad_g_matrix == 0) {
00220                 grad_g_matrix = new Matrix(nrv,lsf);
00221         }
00222         else {
00223                 grad_g_matrix->Zero();
00224         }
00225 
00226 
00227         // Initial declarations
00228         Vector perturbed_x(nrv);
00229         RandomVariable *theRandomVariable;
00230         double h;
00231         double gFunValueAStepAhead;
00232         double stdv;
00233         int result;
00234 
00235 
00236         // For each random variable: perturb and run analysis again
00237 
00238         for (int i=1; i<=nrv; i++) {
00239 
00240                 // Get random variable from domain
00241                 theRandomVariable = theReliabilityDomain->getRandomVariablePtr(i);
00242 
00243 
00244                 // Get the standard deviation
00245                 stdv = theRandomVariable->getStdv();
00246 
00247 
00248                 // Compute perturbation
00249                 h = stdv/perturbationFactor;
00250 
00251 
00252                 // Compute perturbed vector of random variables realization
00253                 perturbed_x = passed_x;
00254                 perturbed_x(i-1) = perturbed_x(i-1) + h;
00255 
00256 
00257                 // Evaluate limit-state function
00258                 result = theGFunEvaluator->runGFunAnalysis(perturbed_x);
00259                 if (result < 0) {
00260                         opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00261                                 << " could not run analysis to evaluate limit-state function. " << endln;
00262                         return -1;
00263                 }
00264 
00265                 
00266                 // Now loop over limit-state functions
00267                 for (int j=1; j<=lsf; j++) {
00268 
00269                         // Set tag of active limit-state function
00270                         theReliabilityDomain->setTagOfActiveLimitStateFunction(j);
00271 
00272                         // Limit-state function value
00273                         result = theGFunEvaluator->evaluateG(perturbed_x);
00274                         if (result < 0) {
00275                                 opserr << "FiniteDifferenceGradGEvaluator::evaluate_grad_g() - " << endln
00276                                         << " could not tokenize limit-state function. " << endln;
00277                                 return -1;
00278                         }
00279                         gFunValueAStepAhead = theGFunEvaluator->getG();
00280 
00281                         // Compute the derivative by finite difference
00282                         (*grad_g_matrix)(i-1,j-1) = (gFunValueAStepAhead - gFunValues(j-1)) / h;
00283 
00284                 }
00285         }
00286 
00287         return 0;
00288 }
00289 
00290 
00291 
00292 
00293 
00294 Matrix
00295 FiniteDifferenceGradGEvaluator::getDgDdispl()
00296 {
00297         // This method is implemented solely for the purpose of mean 
00298         // out-crossing rate analysis using "two searches". Then the 
00299         // derivative of the limit-state function wrt. the displacement
00300         // is needed to expand the limit-state funciton expression
00301 
00302         // Result matrix
00303         Matrix *DgDdispl = 0;
00304 
00305 
00306         // Initial declaractions
00307         double perturbationFactor = 0.001; // (is multiplied by stdv and added to others...)
00308         char tclAssignment[500];
00309         char *dollarSign = "$";
00310         char *underscore = "_";
00311         char lsf_expression[500] = "";
00312         char separators[5] = "}{";
00313         char tempchar[100]="";
00314         char newSeparators[5] = "_";
00315         double g, g_perturbed;
00316         int i;
00317 
00318         // "Download" limit-state function from reliability domain
00319         int lsf = theReliabilityDomain->getTagOfActiveLimitStateFunction();
00320         LimitStateFunction *theLimitStateFunction = 
00321                 theReliabilityDomain->getLimitStateFunctionPtr(lsf);
00322         char *theExpression = theLimitStateFunction->getExpression();
00323         char *lsf_copy = new char[500];
00324         strcpy(lsf_copy,theExpression);
00325 
00326 
00327         // Tokenize the limit-state function and COMPUTE GRADIENTS
00328         char *tokenPtr = strtok( lsf_copy, separators); 
00329         while ( tokenPtr != NULL ) {
00330 
00331                 strcpy(tempchar,tokenPtr);
00332 
00333                 // If a nodal displacement is detected
00334                 if ( strncmp(tokenPtr, "u", 1) == 0) {
00335 
00336                         // Get node number and dof number
00337                         int nodeNumber, direction;
00338                         sscanf(tempchar,"u_%i_%i", &nodeNumber, &direction);
00339 
00340                         // Evaluate the limit-state function again
00341                         char *theTokenizedExpression = theLimitStateFunction->getTokenizedExpression();
00342                         Tcl_ExprDouble( theTclInterp, theTokenizedExpression, &g );
00343                         
00344                         // Keep the original displacement value
00345                         double originalValue;
00346                         sprintf(tclAssignment,"$u_%d_%d", nodeNumber, direction);
00347                         Tcl_ExprDouble( theTclInterp, tclAssignment, &originalValue);
00348 
00349                         // Set perturbed value in the Tcl workspace
00350                         double newValue = originalValue*(1.0+perturbationFactor);
00351                         sprintf(tclAssignment,"set u_%d_%d %35.20f", nodeNumber, direction, newValue);
00352                         Tcl_Eval( theTclInterp, tclAssignment);
00353 
00354                         // Evaluate the limit-state function again
00355                         Tcl_ExprDouble( theTclInterp, theTokenizedExpression, &g_perturbed );
00356 
00357                         // Compute gradient
00358                         double onedgdu = (g_perturbed-g)/(originalValue*perturbationFactor);
00359 
00360                         // Store the DgDdispl in a matrix
00361                         if (DgDdispl == 0) {
00362                                 DgDdispl = new Matrix(1, 3);
00363                                 (*DgDdispl)(0,0) = (double)nodeNumber;
00364                                 (*DgDdispl)(0,1) = (double)direction;
00365                                 (*DgDdispl)(0,2) = onedgdu;
00366                         }
00367                         else {
00368                                 int oldSize = DgDdispl->noRows();
00369                                 Matrix tempMatrix = *DgDdispl;
00370                                 delete DgDdispl;
00371                                 DgDdispl = new Matrix(oldSize+1, 3);
00372                                 for (i=0; i<oldSize; i++) {
00373                                         (*DgDdispl)(i,0) = tempMatrix(i,0);
00374                                         (*DgDdispl)(i,1) = tempMatrix(i,1);
00375                                         (*DgDdispl)(i,2) = tempMatrix(i,2);
00376                                 }
00377                                 (*DgDdispl)(oldSize,0) = (double)nodeNumber;
00378                                 (*DgDdispl)(oldSize,1) = (double)direction;
00379                                 (*DgDdispl)(oldSize,2) = onedgdu;
00380                         }
00381 
00382 
00383                         // Make assignment back to its original value
00384                         sprintf(tclAssignment,"set u_%d_%d %35.20f", nodeNumber, direction, originalValue);
00385                         Tcl_Eval( theTclInterp, tclAssignment);
00386 
00387 
00388                 }
00389 
00390                 tokenPtr = strtok( NULL, separators);  // read next token and go up and check the while condition again
00391         } 
00392 
00393         delete [] lsf_copy;
00394 
00395         return (*DgDdispl);
00396 }
00397 

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