HSConstraint.cpp

Go to the documentation of this file.
00001 //===============================================================================
00002 //# COPYRIGHT (C): Woody's license (by BJ):
00003 //                 ``This    source  code is Copyrighted in
00004 //                 U.S.,  for  an  indefinite  period,  and anybody
00005 //                 caught  using it without our permission, will be
00006 //                 mighty good friends of ourn, cause we don't give
00007 //                 a  darn.  Hack it. Compile it. Debug it. Run it.
00008 //                 Yodel  it.  Enjoy it. We wrote it, that's all we
00009 //                 wanted to do.''
00010 //
00011 //# PROJECT:           Object Oriented Finite Element Program
00012 //# PURPOSE:           Hyper-spherical Constraint
00013 //# CLASS:             HSConstraint
00014 //#
00015 //# VERSION:           0.61803398874989 (golden section)
00016 //# LANGUAGE:          C++
00017 //# TARGET OS:         all...
00018 //# DESIGN:            Ritu Jain, Boris Jeremic
00019 //# PROGRAMMER(S):     Ritu, Boris Jeremic
00020 //#
00021 //#
00022 //# DATE:              14Mar2003
00023 //# UPDATE HISTORY:
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), /*alpha2(alpha*alpha),*/
00040   psi_u2(psi_u*psi_u), 
00041   psi_f2(psi_f*psi_f),
00042   u_ref2(u_ref*u_ref), //new added
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     // delete any vector object created
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     // get pointers to AnalysisModel and LinearSOE
00074     AnalysisModel *theModel = this->getAnalysisModelPtr();//method defined in Incremental Integrator
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     // get the current load factor
00083     currentLambda = theModel->getCurrentDomainTime();
00084 
00085     if (deltaLambdaStep < 0)
00086         signLastDeltaLambdaStep = -1;
00087     else
00088         signLastDeltaLambdaStep = +1;
00089 
00090 
00091 
00092     // determine dUhat
00093     this->formTangent();
00094     theLinSOE->setB(*phat);//defined in LinearSOE.cpp
00095     theLinSOE->solve();
00096 
00097     (*deltaUhat) = theLinSOE->getX();
00098     Vector &dUhat = *deltaUhat;
00099 
00100     Vector f_ext = *phat;
00101 
00102 
00103     // determine delta lambda(1) == dlambda
00104 //    double dLambda = sqrt(arcLength2/((dUhat^dUhat)+alpha2));
00105 // out temp BJ 
00106 //    double dLambda = sqrt(arcLength2/((psi_u2/u_ref2*fabs(dUhat^dUhat))+psi_f2));
00107 // old version with fext
00108     double dLambda = sqrt(
00109                       arcLength2/( (psi_u2/u_ref2*fabs(dUhat^dUhat) ) + psi_f2*(f_ext^f_ext)  ));
00110     dLambda *= signLastDeltaLambdaStep; // base sign of load change
00111                                         // on what was happening last step
00112     deltaLambdaStep = dLambda;
00113     currentLambda += dLambda;
00114 
00115     // determine delta U(1) == dU
00116     (*deltaU) = dUhat;
00117     (*deltaU) *= dLambda;
00118     (*deltaUstep) = (*deltaU);
00119 
00120     // update model with delta lambda and delta U
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; // have to do this as the SOE is gonna change
00140 
00141     // determine dUhat
00142     theLinSOE->setB(*phat);
00143     theLinSOE->solve();
00144     (*deltaUhat) = theLinSOE->getX();
00145 
00146     Vector f_ext = *phat;
00147 
00148     // determine the coeeficients of our quadratic equation
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     // check for a solution to quadratic
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      // opserr << "HSConstraint::update() - zero denominator";
00177      // opserr << "\n";
00178      // return -2;
00179                 dLambda = -a3/(2.0*a2);
00180 
00181     }
00182     else
00183     {
00184         // determine the roots of the quadratic
00185         double sqrtb24ac = sqrt(b24ac);
00186         double dlambda1 = (-a2 + sqrtb24ac)/a1;
00187         double dlambda2 = (-a2 - sqrtb24ac)/a1;
00188 
00189         //Vector deltaU1 = (*deltaUbar);
00190         //deltaU1->addVector(1.0, *deltaUhat,dlambda1);
00191         //double costheta1 = (*deltaUstep)^((*deltaUstep)+(*deltaU1));
00192 
00193         //Vector deltaU2 = (*deltaUbar);
00194         //deltaU2->addVector(1.0, *deltaUhat,dlambda2);
00195         //double costheta2 = (*deltaUstep)^((*deltaUstep)+(*deltaU2));
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         // choose dLambda based on angle between incremental displacement before
00204         // and after this step -- want positive
00205         /*double dLambda;*/
00206         if (costheta1 > costheta2)
00207                 dLambda = dlambda1;
00208         else
00209                 dLambda = dlambda2;
00210     }
00211 
00212 
00213     // determine delta U(i)
00214     (*deltaU) = (*deltaUbar);
00215     deltaU->addVector(1.0, *deltaUhat,dLambda);
00216 
00217     // update dU and dlambda
00218     (*deltaUstep) += *deltaU;
00219     deltaLambdaStep += dLambda;
00220     currentLambda += dLambda;
00221 
00222     // update the model
00223     theModel->incrDisp(*deltaU);
00224     theModel->applyLoadDomain(currentLambda);
00225     theModel->updateDomain();
00226 
00227     // set the X soln in linearSOE to be deltaU for convergence Test
00228     theLinSOE->setX(*deltaU);
00229 
00230     return 0;
00231 }
00232 
00233 
00234 
00235 int
00236 HSConstraint::domainChanged(void)
00237 {
00238     // we first create the Vectors needed
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(); // ask model in case N+1 space
00247 
00248     if (deltaUhat == 0 || deltaUhat->Size() != size) { // create new Vector
00249         if (deltaUhat != 0)
00250             delete deltaUhat;   // delete the old
00251         deltaUhat = new Vector(size);
00252         if (deltaUhat == 0 || deltaUhat->Size() != size) { // check got it
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) { // create new Vector
00260         if (deltaUbar != 0)
00261             delete deltaUbar;   // delete the old
00262         deltaUbar = new Vector(size);
00263         if (deltaUbar == 0 || deltaUbar->Size() != size) { // check got it
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) { // create new Vector
00272         if (deltaU != 0)
00273             delete deltaU;   // delete the old
00274         deltaU = new Vector(size);
00275         if (deltaU == 0 || deltaU->Size() != size) { // check got it
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     // now we have to determine phat
00305     // do this by incrementing lambda by 1, applying load
00306     // and getting phat from unbalance.
00307     currentLambda = theModel->getCurrentDomainTime();
00308     currentLambda += 1.0;
00309     theModel->applyLoadDomain(currentLambda);
00310     this->formUnbalance(); // NOTE: this assumes unbalance at last was 0
00311     (*phat) = theLinSOE->getB();
00312     currentLambda -= 1.0;
00313     theModel->setCurrentDomainTime(currentLambda);
00314 
00315 
00316     // check there is a reference load
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   //data(1) = alpha2;
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   // set the data
00363   arcLength2 = data(0);
00364   //alpha2 = data(1);
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) /*<<  "  alpha: ";
00379         s << sqrt(alpha2) */ << endln;
00380     } else
00381         s << "\t HSConstraint - no associated AnalysisModel\n";
00382 }

Generated on Mon Oct 23 15:04:58 2006 for OpenSees by doxygen 1.5.0