WilsonTheta.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.4 $
00022 // $Date: 2003/02/14 23:00:49 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/integrator/WilsonTheta.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/analysis/integrator/WilsonTheta.C
00027 // 
00028 // Written: fmk 
00029 // Created: 11/98
00030 // Revision: A
00031 //
00032 // Description: This file contains the implementation of WilsonTheta.
00033 //
00034 // What: "@(#) WilsonTheta.C, revA"
00035 
00036 #include <WilsonTheta.h>
00037 #include <FE_Element.h>
00038 #include <LinearSOE.h>
00039 #include <AnalysisModel.h>
00040 #include <Vector.h>
00041 #include <DOF_Group.h>
00042 #include <DOF_GrpIter.h>
00043 #include <AnalysisModel.h>
00044 #include <Channel.h>
00045 #include <FEM_ObjectBroker.h>
00046 
00047 WilsonTheta::WilsonTheta()
00048 :TransientIntegrator(INTEGRATOR_TAGS_WilsonTheta),
00049  theta(0), deltaT(0),
00050  alphaM(0.0), betaK(0.0), betaKi(0.0), betaKc(0.0),
00051  c1(0.0), c2(0.0), c3(0.0), 
00052  Ut(0), Utdot(0), Utdotdot(0),  U(0), Udot(0), Udotdot(0)
00053 {
00054     
00055 }
00056 
00057 WilsonTheta::WilsonTheta(double _theta)
00058 :TransientIntegrator(INTEGRATOR_TAGS_WilsonTheta),
00059  theta(_theta), deltaT(0.0), 
00060  alphaM(0), betaK(0), betaKi(0.0), betaKc(0.0),
00061  c1(0.0), c2(0.0), c3(0.0), 
00062  Ut(0), Utdot(0), Utdotdot(0),  U(0), Udot(0), Udotdot(0)
00063 {
00064     
00065 }
00066 
00067 WilsonTheta::WilsonTheta(double _theta, double alpham, double betak, double betaki, double betakc)
00068 :TransientIntegrator(INTEGRATOR_TAGS_WilsonTheta),
00069  theta(_theta), deltaT(0.0), 
00070  alphaM(alpham), betaK(betak), betaKi(betaKi), betaKc(betakc),
00071  c1(0.0), c2(0.0), c3(0.0), 
00072  Ut(0), Utdot(0), Utdotdot(0),  U(0), Udot(0), Udotdot(0)
00073 {
00074 
00075 }
00076 
00077 WilsonTheta::~WilsonTheta()
00078 {
00079   // clean up the memory created
00080   if (Ut != 0)
00081     delete Ut;
00082   if (Utdot != 0)
00083     delete Utdot;
00084   if (Utdotdot != 0)
00085     delete Utdotdot;
00086   if (U != 0)
00087     delete U;
00088   if (Udot != 0)
00089     delete Udot;
00090   if (Udotdot != 0)
00091     delete Udotdot;
00092 }
00093 
00094 int
00095 WilsonTheta::newStep(double _deltaT)
00096 {
00097   if (theta <= 0.0 ) {
00098     opserr << "Newton::newStep() - error in variable\n";
00099     opserr << "theta: " << theta << " <= 0.0\n";
00100     return -1;
00101   }
00102 
00103   
00104   if (_deltaT <= 0.0) {
00105     opserr << "Newton::newStep() - error in variable\n";
00106     opserr << "dT = " << deltaT << endln;
00107     return -2;  
00108   }
00109 
00110   deltaT = _deltaT;
00111   c1 = 1.0;
00112   c2 = 3.0/(theta*deltaT);
00113   c3 = 2*c2/(theta*deltaT);
00114     
00115   if (U == 0) {
00116     opserr << "Newton::newStep() - domainChange() failed or hasn't been called\n"; 
00117     return -3;  
00118   }
00119 
00120   // set response at t to be that at t+delta t of previous step
00121   (*Ut) = *U;        
00122   (*Utdot) = *Udot;  
00123   (*Utdotdot) = *Udotdot;  
00124     
00125   // set new velocity and accelerations at t + theta delta t
00126   //  (*Udot) *= -2.0;
00127   double a1 = -0.5*theta*deltaT; 
00128   Udot->addVector(-2.0,*Utdotdot,a1);
00129 
00130   //  (*Udotdot) *= -2.0;  
00131   double a2 = -6.0/theta/deltaT; 
00132   Udotdot->addVector(-2.0, *Utdot, a2);
00133     
00134 
00135   // set the new trial response quantities
00136   AnalysisModel *theModel = this->getAnalysisModelPtr();
00137   theModel->setResponse(*U,*Udot,*Udotdot);        
00138 
00139   // increment the time and apply the load
00140   double time = theModel->getCurrentDomainTime();
00141   time += theta * deltaT;
00142   theModel->applyLoadDomain(time);
00143 
00144   theModel->updateDomain();
00145   
00146   return 0;
00147 }
00148 
00149 int
00150 WilsonTheta::formEleTangent(FE_Element *theEle)
00151 {
00152   theEle->zeroTangent();
00153   theEle->addKtToTang(c1);
00154   theEle->addCtoTang(c2);
00155   theEle->addMtoTang(c3);
00156 
00157 
00158   return 0;
00159 }    
00160 
00161 int
00162 WilsonTheta::formNodTangent(DOF_Group *theDof)
00163 {
00164   theDof->zeroTangent();
00165   theDof->addMtoTang(c3);
00166   theDof->addCtoTang(c2);        
00167 
00168   return(0);
00169 }    
00170 
00171 int 
00172 WilsonTheta::domainChanged()
00173 {
00174   AnalysisModel *myModel = this->getAnalysisModelPtr();
00175   LinearSOE *theLinSOE = this->getLinearSOEPtr();
00176   const Vector &x = theLinSOE->getX();
00177   int size = x.Size();
00178 
00179   // if damping factors exist set them in the ele & node of the domain
00180   if (alphaM != 0.0 || betaK != 0.0 || betaKi != 0.0 || betaKc != 0.0)
00181     myModel->setRayleighDampingFactors(alphaM, betaK, betaKi, betaKc);
00182   
00183   // create the new Vector objects
00184   if (Ut == 0 || Ut->Size() != size) {
00185 
00186     // delete the old
00187     if (Ut != 0)
00188       delete Ut;
00189     if (Utdot != 0)
00190       delete Utdot;
00191     if (Utdotdot != 0)
00192       delete Utdotdot;
00193     if (U != 0)
00194       delete U;
00195     if (Udot != 0)
00196       delete Udot;
00197     if (Udotdot != 0)
00198       delete Udotdot;
00199     
00200     // create the new
00201     Ut = new Vector(size);
00202     Utdot = new Vector(size);
00203     Utdotdot = new Vector(size);
00204     U = new Vector(size);
00205     Udot = new Vector(size);
00206     Udotdot = new Vector(size);
00207 
00208     // cheack we obtained the new
00209     if (Ut == 0 || Ut->Size() != size ||
00210         Utdot == 0 || Utdot->Size() != size ||
00211         Utdotdot == 0 || Utdotdot->Size() != size ||
00212         U == 0 || U->Size() != size ||
00213         Udot == 0 || Udot->Size() != size ||
00214         Udotdot == 0 || Udotdot->Size() != size) {
00215       
00216       opserr << "WilsonTheta::domainChanged - ran out of memory\n";
00217 
00218       // delete the old
00219       if (Ut != 0)
00220         delete Ut;
00221       if (Utdot != 0)
00222         delete Utdot;
00223       if (Utdotdot != 0)
00224         delete Utdotdot;
00225       if (U != 0)
00226         delete U;
00227       if (Udot != 0)
00228         delete Udot;
00229       if (Udotdot != 0)
00230         delete Udotdot;
00231 
00232       Ut = 0; Utdot = 0; Utdotdot = 0;
00233       U = 0; Udot = 0; Udotdot = 0;
00234       return -1;
00235     }
00236   }        
00237   
00238   // now go through and populate U, Udot and Udotdot by iterating through
00239   // the DOF_Groups and getting the last committed velocity and accel
00240 
00241   DOF_GrpIter &theDOFs = myModel->getDOFs();
00242   DOF_Group *dofPtr;
00243     
00244   while ((dofPtr = theDOFs()) != 0) {
00245     const Vector &disp = dofPtr->getCommittedDisp();    
00246     const Vector &vel = dofPtr->getCommittedVel();
00247     const Vector &accel = dofPtr->getCommittedAccel();  
00248     const ID &id = dofPtr->getID();
00249     for (int i=0; i < id.Size(); i++) {
00250       int loc = id(i);
00251       if (loc >= 0) {
00252         (*U)(loc) = disp(i);            
00253         (*Udot)(loc) = vel(i);
00254         (*Udotdot)(loc) = accel(i);
00255       }
00256     }
00257   }    
00258   
00259   return 0;
00260 }
00261 
00262 
00263 int
00264 WilsonTheta::update(const Vector &deltaU)
00265 {
00266   AnalysisModel *theModel = this->getAnalysisModelPtr();
00267   if (theModel == 0) {
00268     opserr << "WARNING WilsonTheta::update() - no AnalysisModel set\n";
00269     return -1;
00270   }     
00271 
00272   // check domainChanged() has been called, i.e. Ut will not be zero
00273   if (Ut == 0) {
00274     opserr << "WARNING WilsonTheta::update() - domainChange() failed or not called\n";
00275     return -2;
00276   }     
00277   
00278   // check deltaU is of correct size
00279   if (deltaU.Size() != U->Size()) {
00280     opserr << "WARNING WilsonTheta::update() - Vectors of incompatable size ";
00281     opserr << " expecting " << U->Size() << " obtained " << deltaU.Size() << endln;
00282     return -3;
00283   }
00284 
00285   // determine the response at t + theta * deltaT
00286   (*U) += deltaU;
00287   Udot->addVector(1.0, deltaU,c2);
00288   Udotdot->addVector(1.0, deltaU,c3);
00289   
00290   // update the responses at the DOFs
00291   theModel->setResponse(*U,*Udot,*Udotdot);        
00292   theModel->updateDomain();
00293   
00294   return 0;
00295 }    
00296 
00297 
00298 int
00299 WilsonTheta::commit(void)
00300 {
00301 
00302   AnalysisModel *theModel = this->getAnalysisModelPtr();
00303   if (theModel == 0) {
00304     opserr << "WARNING WilsonTheta::commit() - no AnalysisModel set\n";
00305     return -1;
00306   }       
00307   
00308   // determine the quantities at t + delta t 
00309   /* THIS IS WHAT IS IN BATHE'S BOOK - SEE BELOW FOR QUICKER SOLN
00310   double a1 = c3/theta;
00311   double a2 = c3*deltaT;        
00312   double a3 = (1 - 3.0/theta);
00313   (*Udotdot) = *U;
00314   (*Udotdot) -= *Ut;
00315   (*Udotdot) *= a1;
00316   Udotdot->addVector(*Utdot, -a2);
00317   Udotdot->addVector(*Utdotdot, a3);
00318   */
00319   
00320   /* REVISION BASED ON WHAT IS IN CHOPRA's BOOK - MAKES SENSE - LINEAR ACCEL */
00321 
00322   // determine response quantities at Ut+dt given Ut and Ut + theta dt
00323   double a1,a2;
00324   (*Udotdot) -= *Utdotdot;
00325   (*Udotdot) *= 1/theta;
00326   (*Udotdot) += *Utdotdot;
00327   
00328   (*Udot) = *Utdot;
00329   a1 = 0.5*deltaT;
00330   Udot->addVector(1.0, *Udotdot, a1);
00331   Udot->addVector(1.0, *Utdotdot, a1);
00332 
00333 
00334   (*U) = *Ut;
00335   U->addVector(1.0, *Utdot, deltaT);
00336   a2 = deltaT*deltaT/6.0;
00337   U->addVector(1.0, *Udotdot, a2);
00338   U->addVector(1.0, *Utdotdot, 2*a2);
00339   // update the t + delta t responses at the DOFs 
00340   theModel->setResponse(*U,*Udot,*Udotdot);        
00341   theModel->updateDomain();
00342 
00343   // set the time to be t+delta t
00344   double time = theModel->getCurrentDomainTime();
00345   time -= (theta -1) * deltaT;
00346   theModel->setCurrentDomainTime(time);
00347 
00348   // now invoke commit on the AnalysisModel
00349   return theModel->commitDomain();
00350 }
00351 
00352 int
00353 WilsonTheta::sendSelf(int cTag, Channel &theChannel)
00354 {
00355     static Vector data(5);
00356     data(0) = theta;
00357     data(1) = betaKi;   
00358     data(2) = alphaM;
00359     data(3) = betaK;
00360     data(4) = betaKc;
00361 
00362     if (theChannel.sendVector(this->getDbTag(), cTag, data) < 0) {
00363         opserr << "WilsonTheta::sendSelf() - failed to send the data\n";
00364         return -1;
00365     }
00366     return 0;
00367 }
00368 
00369 int
00370 WilsonTheta::recvSelf(int cTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00371 {
00372     static Vector data(5);
00373     if (theChannel.recvVector(this->getDbTag(), cTag, data) < 0) {
00374         opserr << "WilsonTheta::recvSelf() - ";
00375         opserr << " failed to receive the Vector\n";
00376         return -1;
00377     }
00378 
00379     theta  = data(0);
00380     betaKi = data(1);
00381     alphaM = data(2);
00382     betaK  = data(3);
00383     betaKc = data(4);
00384 
00385     return 0;
00386 }
00387 
00388 void
00389 WilsonTheta::Print(OPS_Stream &s, int flag)
00390 {
00391     AnalysisModel *theModel = this->getAnalysisModelPtr();
00392     if (theModel != 0) {
00393         double currentTime = theModel->getCurrentDomainTime();
00394         s << "\t WilsonTheta - currentTime: " << currentTime;
00395         s << " theta: " << theta << endln;
00396         s << "  Rayleigh Damping - alphaM: " << alphaM;
00397         s << "  betaK: " << betaK << "  betaKi: " << betaKi << endln;       
00398     } else 
00399         s << "\t WilsonTheta - no associated AnalysisModel\n";
00400 }
00401 

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