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