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