ArcLength.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.7 $
00022 // $Date: 2005/10/19 21:53:57 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/integrator/ArcLength.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/analysis/integrator/ArcLength.C
00027 // 
00028 // Written: fmk 
00029 // Created: 07/98
00030 // Revision: A
00031 //
00032 // Description: This file contains the class definition for ArcLength.
00033 // ArcLength is an algorithmic class for perfroming a static analysis
00034 // using the arc length scheme, that is within a load step the follwing
00035 // constraint is enforced: dU^TdU + alpha^2*dLambda^2 = arcLength^2
00036 // where dU is change in nodal displacements for step, dLambda is
00037 // change in applied load and arcLength is a control parameter.
00038 //
00039 // What: "@(#) ArcLength.C, revA"
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     // delete any vector object created
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     // get pointers to AnalysisModel and LinearSOE
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     // get the current load factor
00087     currentLambda = theModel->getCurrentDomainTime();
00088 
00089     if (deltaLambdaStep < 0)
00090         signLastDeltaLambdaStep = -1;
00091     else
00092         signLastDeltaLambdaStep = +1;
00093 
00094     // determine dUhat
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     // determine delta lambda(1) == dlambda
00106     double dLambda = sqrt(arcLength2/((dUhat^dUhat)+alpha2));
00107     dLambda *= signLastDeltaLambdaStep; // base sign of load change
00108                                         // on what was happening last step
00109     deltaLambdaStep = dLambda;
00110     currentLambda += dLambda;
00111 
00112     // determine delta U(1) == dU
00113     (*deltaU) = dUhat;
00114     (*deltaU) *= dLambda;
00115     (*deltaUstep) = (*deltaU);
00116 
00117     // update model with delta lambda and delta U
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; // have to do this as the SOE is gonna change
00137 
00138     // determine dUhat    
00139     theLinSOE->setB(*phat);
00140     theLinSOE->solve();
00141 
00142     (*deltaUhat) = theLinSOE->getX();    
00143 
00144     // determine the coeeficients of our quadratic equation
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     // check for a solution to quadratic
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     // determine the roots of the quadratic
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     //    double theta2 = theta1 + dlambda2*val;
00174     theta1 += dlambda1*val;
00175 
00176     // choose dLambda based on angle between incremental displacement before
00177     // and after this step -- want positive
00178     double dLambda;
00179     if (theta1 > 0)
00180       dLambda = dlambda1;
00181     else
00182       dLambda = dlambda2;
00183 
00184 
00185     // determine delta U(i)
00186     (*deltaU) = (*deltaUbar);    
00187     deltaU->addVector(1.0, *deltaUhat,dLambda);
00188     
00189     // update dU and dlambda
00190     (*deltaUstep) += *deltaU;
00191     deltaLambdaStep += dLambda;
00192     currentLambda += dLambda;
00193 
00194     // update the model
00195     theModel->incrDisp(*deltaU);    
00196     theModel->applyLoadDomain(currentLambda);    
00197 
00198 
00199     theModel->updateDomain();
00200     
00201     // set the X soln in linearSOE to be deltaU for convergence Test
00202     theLinSOE->setX(*deltaU);
00203 
00204     return 0;
00205 }
00206 
00207 
00208 
00209 int 
00210 ArcLength::domainChanged(void)
00211 {
00212     // we first create the Vectors needed
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(); // ask model in case N+1 space
00221 
00222     if (deltaUhat == 0 || deltaUhat->Size() != size) { // create new Vector
00223         if (deltaUhat != 0)
00224             delete deltaUhat;   // delete the old
00225         deltaUhat = new Vector(size);
00226         if (deltaUhat == 0 || deltaUhat->Size() != size) { // check got it
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) { // create new Vector
00234         if (deltaUbar != 0)
00235             delete deltaUbar;   // delete the old
00236         deltaUbar = new Vector(size);
00237         if (deltaUbar == 0 || deltaUbar->Size() != size) { // check got it
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) { // create new Vector
00246         if (deltaU != 0)
00247             delete deltaU;   // delete the old
00248         deltaU = new Vector(size);
00249         if (deltaU == 0 || deltaU->Size() != size) { // check got it
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     // now we have to determine phat
00279     // do this by incrementing lambda by 1, applying load
00280     // and getting phat from unbalance.
00281     currentLambda = theModel->getCurrentDomainTime();
00282     currentLambda += 1.0;
00283     theModel->applyLoadDomain(currentLambda);    
00284     this->formUnbalance(); // NOTE: this assumes unbalance at last was 0
00285     (*phat) = theLinSOE->getB();
00286     currentLambda -= 1.0;
00287     theModel->setCurrentDomainTime(currentLambda);    
00288     
00289 
00290     // check there is a reference load
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   // set the data
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 }

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