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 #include <BisectionLineSearch.h>
00031 #include <IncrementalIntegrator.h>
00032 #include <LinearSOE.h>
00033 #include <Channel.h>
00034 #include <FEM_ObjectBroker.h>
00035 #include <Vector.h>
00036 #include <math.h>
00037
00038 BisectionLineSearch::BisectionLineSearch(double tol, int mIter, double mnEta, double mxEta, int pFlag)
00039 :LineSearch(LINESEARCH_TAGS_BisectionLineSearch),
00040 x(0), tolerance(tol), maxIter(mIter), minEta(mnEta), maxEta(mxEta), printFlag(pFlag)
00041 {
00042
00043 }
00044
00045 BisectionLineSearch::~BisectionLineSearch()
00046 {
00047 if (x != 0)
00048 delete x;
00049 }
00050
00051
00052 int
00053 BisectionLineSearch::newStep(LinearSOE &theSOE)
00054 {
00055 const Vector &dU = theSOE.getX();
00056
00057 if (x == 0)
00058 x = new Vector(dU);
00059
00060 if (x->Size() != dU.Size()) {
00061 delete x;
00062 x = new Vector(dU);
00063 }
00064
00065 return 0;
00066 }
00067
00068 int
00069 BisectionLineSearch::search(double s0,
00070 double s1,
00071 LinearSOE &theSOE,
00072 IncrementalIntegrator &theIntegrator)
00073 {
00074 double r0 = 0.0;
00075
00076 if ( s0 != 0.0 )
00077 r0 = fabs( s1 / s0 );
00078
00079 if (r0 <= tolerance )
00080 return 0;
00081
00082 if (s1 == s0)
00083 return 0;
00084
00085
00086 double eta = 1.0;
00087 double s = s1;
00088 double etaU = 1.0;
00089 double etaL = 0.0;
00090 double sU = s1;
00091 double sL = s0;
00092 double r = r0;
00093 double etaJ = 1.0;
00094
00095 const Vector &dU = theSOE.getX();
00096
00097 if (printFlag == 0) {
00098 opserr << "Bisection Line Search - initial: "
00099 << " eta(0) : " << eta << " , Ratio |sj/s0| = " << r0 << endln;
00100 }
00101
00102
00103 int count = 0;
00104 while ((sU * sL > 0.0) && (etaU < maxEta)) {
00105
00106 count++;
00107 etaU *= 2.0;
00108
00109
00110 *x = dU;
00111 *x *= etaU-etaJ;
00112
00113 if (theIntegrator.update(*x) < 0) {
00114 opserr << "WARNING BisectionLineSearch::search() -";
00115 opserr << "the Integrator failed in update()\n";
00116 return -1;
00117 }
00118
00119 if (theIntegrator.formUnbalance() < 0) {
00120 opserr << "WARNING BisectionLineSearch::search() -";
00121 opserr << "the Integrator failed in formUnbalance()\n";
00122 return -2;
00123 }
00124
00125
00126 const Vector &ResidJ = theSOE.getB();
00127
00128
00129 sU = dU ^ ResidJ;
00130
00131
00132 r = fabs( sU / s0 );
00133 if (r < tolerance)
00134 return 0;
00135
00136 if (printFlag == 0) {
00137 opserr << "Bisection Line Search - bracketing: " << count
00138 << " , eta(j) : " << etaU << " , Ratio |sj/s0| = " << r << endln;
00139 }
00140
00141 etaJ = etaU;
00142 }
00143
00144
00145 if (sU * sL > 0.0) {
00146 *x = dU;
00147 theSOE.setX(*x);
00148 theIntegrator.update(*x);
00149 theIntegrator.formUnbalance();
00150 return 0;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 count = 0;
00160 while ( r > tolerance && count < maxIter ) {
00161
00162 count++;
00163
00164 eta = (etaU + etaL) * 0.5;
00165
00166
00167 if (r > r0 ) eta = 1.0;
00168
00169
00170 *x = dU;
00171 *x *= eta-etaJ;
00172
00173 if (theIntegrator.update(*x) < 0) {
00174 opserr << "WARNING BisectionLineSearch::search() -";
00175 opserr << "the Integrator failed in update()\n";
00176 return -1;
00177 }
00178
00179 if (theIntegrator.formUnbalance() < 0) {
00180 opserr << "WARNING BisectionLineSearch::search() -";
00181 opserr << "the Integrator failed in formUnbalance()\n";
00182 return -2;
00183 }
00184
00185
00186 const Vector &ResidJ = theSOE.getB();
00187
00188
00189 s = dU ^ ResidJ;
00190
00191
00192 r = fabs( s / s0 );
00193
00194
00195 etaJ = eta;
00196
00197 if (s*sU < 0.0) {
00198 etaL = eta;
00199 sL = s;
00200 } else if (s*sU == 0.0)
00201 count = maxIter;
00202 else {
00203 etaU = eta;
00204 sU = s;
00205 }
00206
00207 if (sL == sU)
00208 count = maxIter;
00209
00210 if (printFlag == 0) {
00211 opserr << "Bisection Line Search - iteration: " << count
00212 << " , eta(j) : " << eta << " , Ratio |sj/s0| = " << r << endln;
00213 }
00214
00215 }
00216
00217
00218 *x = dU;
00219 *x *= eta;
00220 theSOE.setX(*x);
00221
00222 return 0;
00223 }
00224
00225
00226 int
00227 BisectionLineSearch::sendSelf(int cTag, Channel &theChannel)
00228 {
00229 return 0;
00230 }
00231
00232 int
00233 BisectionLineSearch::recvSelf(int cTag,
00234 Channel &theChannel,
00235 FEM_ObjectBroker &theBroker)
00236 {
00237 return 0;
00238 }
00239
00240
00241 void
00242 BisectionLineSearch::Print(OPS_Stream &s, int flag)
00243 {
00244 if (flag == 0) {
00245 s << "BisectionLineSearch :: Line Search Tolerance = " << tolerance << endln;
00246 s << " max num Iterations = " << maxIter << endln;
00247 s << " max value on eta = " << maxEta << endln;
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258