MinUnbalDispNorm.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.8 $
00022 // $Date: 2005/10/19 21:53:57 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/integrator/MinUnbalDispNorm.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/analysis/integrator/MinUnbalDispNorm.C
00027 // 
00028 // Written: fmk 
00029 // Created: 07/99
00030 // Revision: A
00031 //
00032 // What: "@(#) MinUnbalDispNorm.C, revA"
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   // to avoid divide-by-zero error on first update() ensure numIncr != 0
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     // delete any vector object created
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     // get pointers to AnalysisModel and LinearSOE
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     // get the current load factor
00088     currentLambda = theModel->getCurrentDomainTime();
00089 
00090 
00091     // determine dUhat
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     // determine delta lambda(1) == dlambda
00102     double factor = specNumIncrStep/numIncrLastStep;
00103     double dLambda = dLambda1LastStep*factor;
00104 
00105     // check aaint min and max values specified in constructor
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; // base sign of load change
00121                                         // on what was happening last step
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     double work = (*phat)^(dUhat);
00136     int signCurrentWork = 1;
00137     if (work < 0) signCurrentWork = -1;
00138 
00139     if (signCurrentWork != signLastDeltaStep)
00140     */
00141 
00142     deltaLambdaStep = dLambda;
00143     currentLambda += dLambda;
00144     numIncrLastStep = 0;
00145 
00146     // determine delta U(1) == dU
00147     (*deltaU) = dUhat;
00148     (*deltaU) *= dLambda;
00149     (*deltaUstep) = (*deltaU);
00150 
00151     // update model with delta lambda and delta U
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; // have to do this as the SOE is gonna change
00174 
00175     // determine dUhat    
00176     theLinSOE->setB(*phat);
00177     theLinSOE->solve();
00178     (*deltaUhat) = theLinSOE->getX();    
00179 
00180     // determine delta lambda(i)
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     // determine delta U(i)
00191     (*deltaU) = (*deltaUbar);    
00192     deltaU->addVector(1.0, *deltaUhat,dLambda);
00193     
00194     // update dU and dlambda
00195     (*deltaUstep) += *deltaU;
00196     deltaLambdaStep += dLambda;
00197     currentLambda += dLambda;
00198 
00199     // update the model
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     // set the X soln in linearSOE to be deltaU for convergence Test
00209     theLinSOE->setX(*deltaU);
00210 
00211     numIncrLastStep++;
00212     return 0;
00213 }
00214 
00215 
00216 
00217 int 
00218 MinUnbalDispNorm::domainChanged(void)
00219 {
00220     // we first create the Vectors needed
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(); // ask model in case N+1 space
00229 
00230     if (deltaUhat == 0 || deltaUhat->Size() != size) { // create new Vector
00231         if (deltaUhat != 0)
00232             delete deltaUhat;   // delete the old
00233         deltaUhat = new Vector(size);
00234         if (deltaUhat == 0 || deltaUhat->Size() != size) { // check got it
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) { // create new Vector
00242         if (deltaUbar != 0)
00243             delete deltaUbar;   // delete the old
00244         deltaUbar = new Vector(size);
00245         if (deltaUbar == 0 || deltaUbar->Size() != size) { // check got it
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) { // create new Vector
00254         if (deltaU != 0)
00255             delete deltaU;   // delete the old
00256         deltaU = new Vector(size);
00257         if (deltaU == 0 || deltaU->Size() != size) { // check got it
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     // now we have to determine phat
00287     // do this by incrementing lambda by 1, applying load
00288     // and getting phat from unbalance.
00289     currentLambda = theModel->getCurrentDomainTime();
00290     currentLambda += 1.0;
00291     theModel->applyLoadDomain(currentLambda);    
00292     this->formUnbalance(); // NOTE: this assumes unbalance at last was 0
00293     (*phat) = theLinSOE->getB();
00294     currentLambda -= 1.0;
00295     theModel->setCurrentDomainTime(currentLambda);    
00296 
00297 
00298     // check there is a reference load
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   // set the data
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 }

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