00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00120 bool isOutsideSphere;
00121 bool isSecondTime;
00122 bool FEconvergence;
00123 double result;
00124 Vector x_new;
00125 Matrix jacobian_x_u;
00126
00127
00128
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
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
00144 if (isCloseToSphere) {
00145 isSecondTime = true;
00146 }
00147 else {
00148 isSecondTime = false;
00149 }
00150
00151
00152
00153 double lambda_new;
00154 if (stepNumber <= numberOfShortSteps) {
00155 lambda_new = b0;
00156 }
00157 else {
00158 lambda_new = 1.0;
00159 }
00160
00161
00162
00163 Vector u_new = u_old + dir_old * lambda_new;
00164
00165
00166
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
00182
00183
00184 g_new = g_old;
00185 grad_G_new = grad_G_old;
00186
00187
00188
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
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
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
00233 FEconvergence = true;
00234 result = theGFunEvaluator->runGFunAnalysis(x_new);
00235
00236
00237
00238
00239
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
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
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
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
00294 if (u_new.Norm()>radius) {
00295
00296 isOutsideSphere = true;
00297
00298
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
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
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
00346 FEconvergence = true;
00347 result = theGFunEvaluator->runGFunAnalysis(x_new);
00348
00349
00350
00351
00352
00353
00354
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
00366
00367
00368
00369
00370
00371
00372 if (theRootFindingAlgorithm != 0) {
00373 theRootFindingAlgorithm->findLimitStateSurface(2,g_new, grad_G_old, u_new);
00374 }
00375 }
00376
00377
00378 i++;
00379
00380
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 }