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