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
00035
00036
00037
00038
00039
00040
00041
00042 #include <ArcLength.h>
00043 #include <AnalysisModel.h>
00044 #include <LinearSOE.h>
00045 #include <Vector.h>
00046 #include <Channel.h>
00047 #include <math.h>
00048
00049 ArcLength::ArcLength(double arcLength, double alpha)
00050 :StaticIntegrator(INTEGRATOR_TAGS_ArcLength),
00051 arcLength2(arcLength*arcLength), alpha2(alpha*alpha),
00052 deltaUhat(0), deltaUbar(0), deltaU(0), deltaUstep(0),
00053 phat(0), deltaLambdaStep(0.0), currentLambda(0.0),
00054 signLastDeltaLambdaStep(1)
00055 {
00056
00057 }
00058
00059 ArcLength::~ArcLength()
00060 {
00061
00062 if (deltaUhat != 0)
00063 delete deltaUhat;
00064 if (deltaU != 0)
00065 delete deltaU;
00066 if (deltaUstep != 0)
00067 delete deltaUstep;
00068 if (deltaUbar != 0)
00069 delete deltaUbar;
00070 if (phat != 0)
00071 delete phat;
00072 }
00073
00074 int
00075 ArcLength::newStep(void)
00076 {
00077
00078 AnalysisModel *theModel = this->getAnalysisModelPtr();
00079 LinearSOE *theLinSOE = this->getLinearSOEPtr();
00080 if (theModel == 0 || theLinSOE == 0) {
00081 opserr << "WARNING ArcLength::newStep() ";
00082 opserr << "No AnalysisModel or LinearSOE has been set\n";
00083 return -1;
00084 }
00085
00086
00087 currentLambda = theModel->getCurrentDomainTime();
00088
00089 if (deltaLambdaStep < 0)
00090 signLastDeltaLambdaStep = -1;
00091 else
00092 signLastDeltaLambdaStep = +1;
00093
00094
00095 this->formTangent();
00096 theLinSOE->setB(*phat);
00097 if (theLinSOE->solve() < 0) {
00098 opserr << "ArcLength::newStep(void) - failed in solver\n";
00099 return -1;
00100 }
00101
00102 (*deltaUhat) = theLinSOE->getX();
00103 Vector &dUhat = *deltaUhat;
00104
00105
00106 double dLambda = sqrt(arcLength2/((dUhat^dUhat)+alpha2));
00107 dLambda *= signLastDeltaLambdaStep;
00108
00109 deltaLambdaStep = dLambda;
00110 currentLambda += dLambda;
00111
00112
00113 (*deltaU) = dUhat;
00114 (*deltaU) *= dLambda;
00115 (*deltaUstep) = (*deltaU);
00116
00117
00118 theModel->incrDisp(*deltaU);
00119 theModel->applyLoadDomain(currentLambda);
00120 theModel->updateDomain();
00121
00122 return 0;
00123 }
00124
00125 int
00126 ArcLength::update(const Vector &dU)
00127 {
00128 AnalysisModel *theModel = this->getAnalysisModelPtr();
00129 LinearSOE *theLinSOE = this->getLinearSOEPtr();
00130 if (theModel == 0 || theLinSOE == 0) {
00131 opserr << "WARNING ArcLength::update() ";
00132 opserr << "No AnalysisModel or LinearSOE has been set\n";
00133 return -1;
00134 }
00135
00136 (*deltaUbar) = dU;
00137
00138
00139 theLinSOE->setB(*phat);
00140 theLinSOE->solve();
00141
00142 (*deltaUhat) = theLinSOE->getX();
00143
00144
00145 double a = alpha2 + ((*deltaUhat)^(*deltaUhat));
00146 double b = alpha2*deltaLambdaStep
00147 + ((*deltaUhat)^(*deltaUbar))
00148 + ((*deltaUstep)^(*deltaUhat));
00149 b *= 2.0;
00150 double c = 2*((*deltaUstep)^(*deltaUbar)) + ((*deltaUbar)^(*deltaUbar));
00151
00152 double b24ac = b*b - 4.0*a*c;
00153 if (b24ac < 0) {
00154 opserr << "ArcLength::update() - imaginary roots due to multiple instability";
00155 opserr << " directions - initial load increment was too large\n";
00156 opserr << "a: " << a << " b: " << b << " c: " << c << " b24ac: " << b24ac << endln;
00157 return -1;
00158 }
00159 double a2 = 2.0*a;
00160 if (a2 == 0.0) {
00161 opserr << "ArcLength::update() - zero denominator";
00162 opserr << " alpha was set to 0.0 and zero reference load\n";
00163 return -2;
00164 }
00165
00166
00167 double sqrtb24ac = sqrt(b24ac);
00168 double dlambda1 = (-b + sqrtb24ac)/a2;
00169 double dlambda2 = (-b - sqrtb24ac)/a2;
00170
00171 double val = (*deltaUhat)^(*deltaUstep);
00172 double theta1 = ((*deltaUstep)^(*deltaUstep)) + ((*deltaUbar)^(*deltaUstep));
00173
00174 theta1 += dlambda1*val;
00175
00176
00177
00178 double dLambda;
00179 if (theta1 > 0)
00180 dLambda = dlambda1;
00181 else
00182 dLambda = dlambda2;
00183
00184
00185
00186 (*deltaU) = (*deltaUbar);
00187 deltaU->addVector(1.0, *deltaUhat,dLambda);
00188
00189
00190 (*deltaUstep) += *deltaU;
00191 deltaLambdaStep += dLambda;
00192 currentLambda += dLambda;
00193
00194
00195 theModel->incrDisp(*deltaU);
00196 theModel->applyLoadDomain(currentLambda);
00197
00198
00199 theModel->updateDomain();
00200
00201
00202 theLinSOE->setX(*deltaU);
00203
00204 return 0;
00205 }
00206
00207
00208
00209 int
00210 ArcLength::domainChanged(void)
00211 {
00212
00213 AnalysisModel *theModel = this->getAnalysisModelPtr();
00214 LinearSOE *theLinSOE = this->getLinearSOEPtr();
00215 if (theModel == 0 || theLinSOE == 0) {
00216 opserr << "WARNING ArcLength::update() ";
00217 opserr << "No AnalysisModel or LinearSOE has been set\n";
00218 return -1;
00219 }
00220 int size = theModel->getNumEqn();
00221
00222 if (deltaUhat == 0 || deltaUhat->Size() != size) {
00223 if (deltaUhat != 0)
00224 delete deltaUhat;
00225 deltaUhat = new Vector(size);
00226 if (deltaUhat == 0 || deltaUhat->Size() != size) {
00227 opserr << "FATAL ArcLength::domainChanged() - ran out of memory for";
00228 opserr << " deltaUhat Vector of size " << size << endln;
00229 exit(-1);
00230 }
00231 }
00232
00233 if (deltaUbar == 0 || deltaUbar->Size() != size) {
00234 if (deltaUbar != 0)
00235 delete deltaUbar;
00236 deltaUbar = new Vector(size);
00237 if (deltaUbar == 0 || deltaUbar->Size() != size) {
00238 opserr << "FATAL ArcLength::domainChanged() - ran out of memory for";
00239 opserr << " deltaUbar Vector of size " << size << endln;
00240 exit(-1);
00241 }
00242 }
00243
00244
00245 if (deltaU == 0 || deltaU->Size() != size) {
00246 if (deltaU != 0)
00247 delete deltaU;
00248 deltaU = new Vector(size);
00249 if (deltaU == 0 || deltaU->Size() != size) {
00250 opserr << "FATAL ArcLength::domainChanged() - ran out of memory for";
00251 opserr << " deltaU Vector of size " << size << endln;
00252 exit(-1);
00253 }
00254 }
00255
00256 if (deltaUstep == 0 || deltaUstep->Size() != size) {
00257 if (deltaUstep != 0)
00258 delete deltaUstep;
00259 deltaUstep = new Vector(size);
00260 if (deltaUstep == 0 || deltaUstep->Size() != size) {
00261 opserr << "FATAL ArcLength::domainChanged() - ran out of memory for";
00262 opserr << " deltaUstep Vector of size " << size << endln;
00263 exit(-1);
00264 }
00265 }
00266
00267 if (phat == 0 || phat->Size() != size) {
00268 if (phat != 0)
00269 delete phat;
00270 phat = new Vector(size);
00271 if (phat == 0 || phat->Size() != size) {
00272 opserr << "FATAL ArcLength::domainChanged() - ran out of memory for";
00273 opserr << " phat Vector of size " << size << endln;
00274 exit(-1);
00275 }
00276 }
00277
00278
00279
00280
00281 currentLambda = theModel->getCurrentDomainTime();
00282 currentLambda += 1.0;
00283 theModel->applyLoadDomain(currentLambda);
00284 this->formUnbalance();
00285 (*phat) = theLinSOE->getB();
00286 currentLambda -= 1.0;
00287 theModel->setCurrentDomainTime(currentLambda);
00288
00289
00290
00291 int haveLoad = 0;
00292 for (int i=0; i<size; i++)
00293 if ( (*phat)(i) != 0.0 ) {
00294 haveLoad = 1;
00295 i = size;
00296 }
00297
00298 if (haveLoad == 0) {
00299 opserr << "WARNING ArcLength::domainChanged() - zero reference load";
00300 return -1;
00301 }
00302
00303 return 0;
00304 }
00305
00306 int
00307 ArcLength::sendSelf(int cTag,
00308 Channel &theChannel)
00309 {
00310 Vector data(5);
00311 data(0) = arcLength2;
00312 data(1) = alpha2;
00313 data(2) = deltaLambdaStep;
00314 data(3) = currentLambda;
00315 data(4) = signLastDeltaLambdaStep;
00316
00317 if (theChannel.sendVector(this->getDbTag(), cTag, data) < 0) {
00318 opserr << "ArcLength::sendSelf() - failed to send the data\n";
00319 return -1;
00320 }
00321 return 0;
00322 }
00323
00324
00325 int
00326 ArcLength::recvSelf(int cTag,
00327 Channel &theChannel, FEM_ObjectBroker &theBroker)
00328 {
00329 Vector data(5);
00330 if (theChannel.recvVector(this->getDbTag(), cTag, data) < 0) {
00331 opserr << "ArcLength::sendSelf() - failed to send the data\n";
00332 return -1;
00333 }
00334
00335
00336 arcLength2 = data(0);
00337 alpha2 = data(1);
00338 deltaLambdaStep = data(2);
00339 currentLambda = data(3);
00340 signLastDeltaLambdaStep = data(4);
00341 return 0;
00342 }
00343
00344 void
00345 ArcLength::Print(OPS_Stream &s, int flag)
00346 {
00347 AnalysisModel *theModel = this->getAnalysisModelPtr();
00348 if (theModel != 0) {
00349 double cLambda = theModel->getCurrentDomainTime();
00350 s << "\t ArcLength - currentLambda: " << cLambda;
00351 s << " arcLength: " << sqrt(arcLength2) << " alpha: ";
00352 s << sqrt(alpha2) << endln;
00353 } else
00354 s << "\t ArcLength - no associated AnalysisModel\n";
00355 }