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 <PolakHeSearchDirectionAndMeritFunction.h>
00035 #include <SearchDirection.h>
00036 #include <MeritFunctionCheck.h>
00037 #include <Vector.h>
00038
00039
00040 PolakHeSearchDirectionAndMeritFunction::PolakHeSearchDirectionAndMeritFunction(double pgamma, double pdelta)
00041 :SearchDirection(), MeritFunctionCheck()
00042 {
00043 gamma = pgamma;
00044 delta = pdelta;
00045 alpha = 0.0;
00046 }
00047
00048 PolakHeSearchDirectionAndMeritFunction::~PolakHeSearchDirectionAndMeritFunction()
00049 {
00050 }
00051
00052
00053
00054
00055 Vector
00056 PolakHeSearchDirectionAndMeritFunction::getSearchDirection()
00057 {
00058 return searchDirection;
00059 }
00060
00061
00062 int
00063 PolakHeSearchDirectionAndMeritFunction::setAlpha(double palpha)
00064 {
00065 alpha = palpha;
00066
00067 return 0;
00068 }
00069
00070
00071
00072 int
00073 PolakHeSearchDirectionAndMeritFunction::computeSearchDirection(
00074 int stepNumber,
00075 Vector u,
00076 double gFunctionValue,
00077 Vector gradientInStandardNormalSpace)
00078 {
00079
00080
00081 if (stepNumber == 1) {
00082 if (gFunctionValue > 15.0 || gFunctionValue < 2.0) {
00083 opserr << "WARNING: The start value of the limit-state function is outside " << endln
00084 << " the ideal range for fastest convergence of the Polak-He algorithm. " << endln;
00085 }
00086 }
00087
00088
00089 double oneOverDelta = 1.0/delta;
00090 double a11 = oneOverDelta * (u ^ u);
00091 double a22 = oneOverDelta * (gradientInStandardNormalSpace ^ gradientInStandardNormalSpace);
00092 double a12 = oneOverDelta * (u ^ gradientInStandardNormalSpace);
00093
00094
00095
00096 double b1;
00097 if (gFunctionValue <= 0.0) {
00098 b1 = 0.0;
00099 }
00100 else {
00101 b1 = gFunctionValue;
00102 }
00103 double b2 = b1 - gFunctionValue;
00104 b1 = gamma*b1;
00105
00106
00107
00108 double a = 0.5*a11 + 0.5*a22 - a12;
00109 double b = b1 - b2 + a12 - a22;
00110 double c = 0.5*a22 + b2;
00111
00112
00113
00114 double z1, z2;
00115 if (a<0.0) {
00116 opserr << "ERROR: PolakHeSearchDirectionAndMeritFunction::computeSearchDirection() " << endln
00117 << " the quadratic term is negative! " << endln;
00118 return -1;
00119 }
00120 else if (a < 1.0e-9) {
00121
00122
00123 double Fend1 = c;
00124 double Fend2 = a+b+c;
00125
00126 if (Fend1 < Fend2) {
00127 z1 = 0.0;
00128 z2 = 1.0;
00129 thetaFunction = -Fend1;
00130 }
00131 else {
00132 z1 = 1.0;
00133 z2 = 0.0;
00134 thetaFunction = -Fend2;
00135 }
00136 }
00137 else {
00138
00139
00140 double x = -b/(2.0*a);
00141 z1 = x;
00142 z2 = 1.0 - x;
00143 thetaFunction = -(a*x*x + b*x + c);
00144
00145
00146
00147
00148 if (z1 < 0.0 || z1 > 1.0 || z2 < 0.0 || z2 > 1.0 ) {
00149
00150
00151 double Fend1 = c;
00152 double Fend2 = a+b+c;
00153
00154 if (Fend1 < Fend2) {
00155 z1 = 0.0;
00156 z2 = 1.0;
00157 thetaFunction = -Fend1;
00158 }
00159 else {
00160 z1 = 1.0;
00161 z2 = 0.0;
00162 thetaFunction = -Fend2;
00163 }
00164 }
00165 }
00166
00167
00168
00169 searchDirection = -z1*u - z2*gradientInStandardNormalSpace;
00170
00171 return 0;
00172 }
00173
00174
00175
00176
00177 double
00178 PolakHeSearchDirectionAndMeritFunction::getMeritFunctionValue(Vector u, double g, Vector grad_G)
00179 {
00180 opserr << "WARNING: PolakHeSearchDirectionAndMeritFunction::getMeritFunctionValue() --" << endln
00181 << " no explicit merit function value is computed." << endln;
00182 return 0.0;
00183 }
00184
00185
00186
00187 int
00188 PolakHeSearchDirectionAndMeritFunction::updateMeritParameters(Vector u, double g, Vector grad_G)
00189 {
00190 opserr << "WARNING: PolakHeSearchDirectionAndMeritFunction::updateMeritParameters() --" << endln
00191 << " no explicit merit function value is computed." << endln;
00192
00193 return 0;
00194 }
00195
00196
00197
00198
00199 int
00200 PolakHeSearchDirectionAndMeritFunction::check(Vector u_old,
00201 double g_old,
00202 Vector grad_G_old,
00203 double stepSize,
00204 Vector stepDirection,
00205 double g_new)
00206 {
00207
00208 Vector u_new = u_old + stepSize*stepDirection;
00209
00210
00211 if (alpha == 0.0) {
00212 opserr << "ERROR: PolakHeSearchDirectionAndMeritFunction::check()" << endln
00213 << " the alpha factor is not set! " << endln;
00214 }
00215
00216
00217
00218 double g_old_plus;
00219 if (g_old <= 0.0 ) {
00220 g_old_plus = 0.0;
00221 }
00222 else {
00223 g_old_plus = g_old;
00224 }
00225
00226
00227
00228 double term1 = 0.5*(u_new^u_new) - 0.5*(u_old^u_old) - gamma * g_old_plus;
00229 double term2 = g_new - g_old_plus;
00230 double F;
00231 if (term1 > term2) {
00232 F = term1;
00233 }
00234 else {
00235 F = term2;
00236 }
00237
00238
00239
00240 if ( F <= (alpha*stepSize*thetaFunction) ) {
00241 return 0;
00242 }
00243 else {
00244 return -1;
00245 }
00246
00247 }