DistributedDisplacementControl.cpp

Go to the documentation of this file.
00001 
00002 /* ****************************************************************** **
00003 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00004 **          Pacific Earthquake Engineering Research Center            **
00005 **                                                                    **
00006 **                                                                    **
00007 ** (C) Copyright 1999, The Regents of the University of California    **
00008 ** All Rights Reserved.                                               **
00009 **                                                                    **
00010 ** Commercial use of this program without express permission of the   **
00011 ** University of California, Berkeley, is strictly prohibited.  See   **
00012 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00013 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00014 **                                                                    **
00015 ** Developed by:                                                      **
00016 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00017 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00018 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00019 **                                                                    **
00020 ** ****************************************************************** */
00021                                                                         
00022 // $Revision: 1.1 $
00023 // $Date: 2005/11/29 21:59:49 $
00024 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/integrator/DistributedDisplacementControl.cpp,v $
00025                                                                         
00026 // Written: fmk 
00027 // Created: 07/98
00028 //
00029 // Description: This file contains the class definition for DistributedDisplacementControl.
00030 // DistributedDisplacementControl is an algorithmic class for perfroming a static analysis
00031 // using the arc length scheme, that is within a load step the follwing
00032 // constraint is enforced: dU^TdU + alpha^2*dLambda^2 = DistributedDisplacementControl^2
00033 // where dU is change in nodal displacements for step, dLambda is
00034 // change in applied load and DistributedDisplacementControl is a control parameter.
00035 //
00036 // What: "@(#) DistributedDisplacementControl.C, revA"
00037 
00038 
00039 #include <DistributedDisplacementControl.h>
00040 #include <AnalysisModel.h>
00041 #include <LinearSOE.h>
00042 #include <Vector.h>
00043 #include <Channel.h>
00044 #include <math.h>
00045 #include <Domain.h>
00046 #include <Node.h>
00047 #include <DOF_Group.h>
00048 #include <ID.h>
00049 
00050 DistributedDisplacementControl::DistributedDisplacementControl(int node, int dof, 
00051                                                                double increment, 
00052                                                                int numIncr,
00053                                                                double min, double max)
00054 :StaticIntegrator(INTEGRATOR_TAGS_DistributedDisplacementControl),
00055  processID(0), theChannels(0), numChannels(0), 
00056  theNode(node), theDof(dof), theIncrement(increment),
00057  theDofID(0), 
00058  deltaUhat(0), deltaUbar(0), deltaU(0), deltaUstep(0), 
00059  phat(0), deltaLambdaStep(0.0), currentLambda(0.0),
00060  specNumIncrStep(numIncr), numIncrLastStep(numIncr),
00061  minIncrement(min), maxIncrement(max)
00062 {
00063   // to avoid divide-by-zero error on first update() ensure numIncr != 0
00064   if (numIncr == 0) {
00065     opserr << "WARNING DistributedDisplacementControl::DistributedDisplacementControl() -";
00066     opserr << " numIncr set to 0, 1 assumed\n";
00067     specNumIncrStep = 1.0;
00068     numIncrLastStep = 1.0;
00069   }
00070 }
00071 
00072 
00073 
00074 DistributedDisplacementControl::DistributedDisplacementControl()
00075 :StaticIntegrator(INTEGRATOR_TAGS_DistributedDisplacementControl),
00076  processID(0), theChannels(0), numChannels(0), 
00077  theNode(0), theDof(0), theIncrement(0),
00078  theDofID(0), deltaUhat(0), deltaUbar(0), deltaU(0), deltaUstep(0), 
00079  phat(0), deltaLambdaStep(0.0), currentLambda(0.0),
00080  specNumIncrStep(0), numIncrLastStep(0),
00081  minIncrement(0), maxIncrement(0)
00082 {
00083 
00084 }
00085 
00086 DistributedDisplacementControl::~DistributedDisplacementControl()
00087 {
00088     // delete any vector object created
00089     if (deltaUhat != 0)
00090         delete deltaUhat;
00091     if (deltaU != 0)
00092         delete deltaU;
00093     if (deltaUstep != 0)
00094         delete deltaUstep;
00095     if (deltaUbar != 0)
00096         delete deltaUbar;
00097     if (phat != 0)
00098         delete phat;
00099     if (theChannels != 0)
00100       delete [] theChannels;
00101 }
00102 
00103 int
00104 DistributedDisplacementControl::newStep(void)
00105 {
00106     // get pointers to AnalysisModel and LinearSOE
00107     AnalysisModel *theModel = this->getAnalysisModelPtr();
00108     LinearSOE *theLinSOE = this->getLinearSOEPtr();    
00109     if (theModel == 0 || theLinSOE == 0) {
00110         opserr << "WARNING DistributedDisplacementControl::newStep() ";
00111         opserr << "No AnalysisModel or LinearSOE has been set\n";
00112         return -1;
00113     }
00114 
00115 
00116     // determine increment for this iteration
00117     double factor = specNumIncrStep/numIncrLastStep;
00118     theIncrement *=factor;
00119 
00120     if (theIncrement < minIncrement)
00121       theIncrement = minIncrement;
00122     else if (theIncrement > maxIncrement)
00123       theIncrement = maxIncrement;
00124 
00125 
00126     // get the current load factor
00127     currentLambda = theModel->getCurrentDomainTime();
00128 
00129     // determine dUhat
00130     this->formTangent();
00131 
00132     if (processID == 0)
00133       theLinSOE->setB(*phat);
00134     else
00135       theLinSOE->zeroB();
00136 
00137     theLinSOE->solve();
00138     (*deltaUhat) = theLinSOE->getX();
00139     Vector &dUhat = *deltaUhat;
00140 
00141     double dUahat = dUhat(theDofID);
00142     if (dUahat == 0.0) {
00143         opserr << "WARNING DistributedDisplacementControl::newStep() ";
00144         opserr << "dUahat is zero -- zero reference displacement at control node DOF\n";
00145         return -1;
00146     }
00147 
00148 
00149     // determine delta lambda(1) == dlambda    
00150     double dLambda = theIncrement/dUahat;
00151 
00152     deltaLambdaStep = dLambda;
00153     currentLambda += dLambda;
00154  //   opserr << "DistributedDisplacementControl: " << dUahat  << " " << theDofID << endln;
00155  //   opserr << "DistributedDisplacementControl::newStep() : " << deltaLambdaStep << endln;
00156     // determine delta U(1) == dU
00157     (*deltaU) = dUhat;
00158     (*deltaU) *= dLambda;
00159     (*deltaUstep) = (*deltaU);
00160 
00161     // update model with delta lambda and delta U
00162     theModel->incrDisp(*deltaU);    
00163     theModel->applyLoadDomain(currentLambda);    
00164     if (theModel->updateDomain() < 0) {
00165       opserr << "DistributedDisplacementControl::newStep - model failed to update for new dU\n";
00166       return -1;
00167     }
00168 
00169     numIncrLastStep = 0;
00170 
00171     return 0;
00172 }
00173 
00174 int
00175 DistributedDisplacementControl::update(const Vector &dU)
00176 {
00177 
00178     AnalysisModel *theModel = this->getAnalysisModelPtr();
00179     LinearSOE *theLinSOE = this->getLinearSOEPtr();    
00180     if (theModel == 0 || theLinSOE == 0) {
00181         opserr << "WARNING DistributedDisplacementControl::update() ";
00182         opserr << "No AnalysisModel or LinearSOE has been set\n";
00183         return -1;
00184     }
00185 
00186     (*deltaUbar) = dU; // have to do this as the SOE is gonna change
00187     double dUabar = (*deltaUbar)(theDofID);
00188     
00189     // determine dUhat    
00190     if (processID == 0)
00191       theLinSOE->setB(*phat);
00192     else
00193       theLinSOE->zeroB();
00194 
00195     theLinSOE->solve();
00196     (*deltaUhat) = theLinSOE->getX();
00197 
00198     double dUahat = (*deltaUhat)(theDofID);
00199 
00200     if (dUahat == 0.0) {
00201         opserr << "WARNING DistributedDisplacementControl::update() ";
00202         opserr << "dUahat is zero -- zero reference displacement at control node DOF\n";
00203         return -1;
00204     }
00205 
00206     // determine delta lambda(1) == dlambda    
00207     double dLambda = -dUabar/dUahat;
00208     
00209     // determine delta U(i)
00210     (*deltaU) = (*deltaUbar);    
00211     deltaU->addVector(1.0, *deltaUhat,dLambda);
00212     
00213     // update dU and dlambda
00214     (*deltaUstep) += *deltaU;
00215     deltaLambdaStep += dLambda;
00216     currentLambda += dLambda;
00217 
00218     // update the model
00219     theModel->incrDisp(*deltaU);    
00220     
00221     theModel->applyLoadDomain(currentLambda);    
00222     if (theModel->updateDomain() < 0) {
00223       opserr << "DistributedDisplacementControl::update - model failed to update for new dU\n";
00224       return -1;
00225     }
00226         
00227     
00228     // set the X soln in linearSOE to be deltaU for convergence Test
00229     theLinSOE->setX(*deltaU);
00230 
00231     numIncrLastStep++;
00232 
00233     return 0;
00234 }
00235 
00236 
00237 
00238 int 
00239 DistributedDisplacementControl::domainChanged(void)
00240 {
00241 
00242     // we first create the Vectors needed
00243     AnalysisModel *theModel = this->getAnalysisModelPtr();
00244     LinearSOE *theLinSOE = this->getLinearSOEPtr();    
00245     if (theModel == 0 || theLinSOE == 0) {
00246         opserr << "WARNING DistributedDisplacementControl::update() ";
00247         opserr << "No AnalysisModel or LinearSOE has been set\n";
00248         return -1;
00249     }    
00250     
00251     //int size = theModel->getNumEqn(); // ask model in case N+1 space
00252     const Vector &b = theLinSOE->getB(); // ask model in case N+1 space
00253     int size = b.Size();
00254 
00255     // first we determine the id of the nodal dof
00256     Domain *theDomain = theModel->getDomainPtr();
00257     if (theDomain == 0) {
00258       opserr << "BUG WARNING DistributedDisplacementControl::domainChanged() - no Domain associated!!";
00259       return -1;
00260     }
00261 
00262     theDofID = -1;
00263     Node *theNodePtr = theDomain->getNode(theNode);
00264     if (theNodePtr != 0) {
00265       DOF_Group *theGroup = theNodePtr->getDOF_GroupPtr();
00266       if (theGroup == 0) {
00267         opserr << "BUG DistributedDisplacementControl::domainChanged() - no DOF_Group associated with the node!!\n";
00268         return -1;
00269       }
00270       const ID &theID = theGroup->getID();
00271       if (theDof < 0 || theDof >= theID.Size()) {
00272         opserr << "DistributedDisplacementControl::domainChanged() - not a valid dof " << theDof << endln;
00273         return -1;
00274       }
00275       theDofID = theID(theDof);
00276       if (theDofID < 0) {
00277         opserr << "DistributedDisplacementControl::domainChanged() - constrained dof not a valid a dof\n";;
00278         return -1;
00279       }
00280     }
00281 
00282     static ID data(1);    
00283 
00284     if (processID != 0) {
00285       Channel *theChannel = theChannels[0];
00286       data(0) = theDofID;
00287 
00288       theChannel->sendID(0, 0, data);
00289       theChannel->recvID(0, 0, data);
00290       theDofID = data(0);
00291     } 
00292     
00293     // if main domain, collect all theDofID if not -1 then this is the value & send value out
00294     else {
00295       
00296       for (int j=0; j<numChannels; j++) {
00297         Channel *theChannel = theChannels[j];
00298         theChannel->recvID(0, 0, data);
00299         if (data(0) != -1)
00300           theDofID = data(0);
00301       }
00302       
00303       for (int k=0; k<numChannels; k++) {
00304         Channel *theChannel = theChannels[k];
00305         data(0) = theDofID;
00306         theChannel->sendID(0, 0, data);
00307       }
00308     }
00309 
00310     if (deltaUhat == 0 || deltaUhat->Size() != size) { // create new Vector
00311         if (deltaUhat != 0)
00312             delete deltaUhat;   // delete the old
00313         deltaUhat = new Vector(size);
00314         if (deltaUhat == 0 || deltaUhat->Size() != size) { // check got it
00315             opserr << "FATAL DistributedDisplacementControl::domainChanged() - ran out of memory for";
00316             opserr << " deltaUhat Vector of size " << size << endln;
00317             exit(-1);
00318         }
00319     }
00320 
00321     if (deltaUbar == 0 || deltaUbar->Size() != size) { // create new Vector
00322         if (deltaUbar != 0)
00323             delete deltaUbar;   // delete the old
00324         deltaUbar = new Vector(size);
00325         if (deltaUbar == 0 || deltaUbar->Size() != size) { // check got it
00326             opserr << "FATAL DistributedDisplacementControl::domainChanged() - ran out of memory for";
00327             opserr << " deltaUbar Vector of size " << size << endln;
00328             exit(-1);
00329         }
00330     }
00331     
00332     if (deltaU == 0 || deltaU->Size() != size) { // create new Vector
00333         if (deltaU != 0)
00334             delete deltaU;   // delete the old
00335         deltaU = new Vector(size);
00336         if (deltaU == 0 || deltaU->Size() != size) { // check got it
00337             opserr << "FATAL DistributedDisplacementControl::domainChanged() - ran out of memory for";
00338             opserr << " deltaU Vector of size " << size << endln;
00339             exit(-1);
00340         }
00341     }
00342 
00343     if (deltaUstep == 0 || deltaUstep->Size() != size) { 
00344         if (deltaUstep != 0)
00345             delete deltaUstep;  
00346         deltaUstep = new Vector(size);
00347         if (deltaUstep == 0 || deltaUstep->Size() != size) { 
00348             opserr << "FATAL DistributedDisplacementControl::domainChanged() - ran out of memory for";
00349             opserr << " deltaUstep Vector of size " << size << endln;
00350             exit(-1);
00351         }
00352     }
00353 
00354     if (phat == 0 || phat->Size() != size) { 
00355         if (phat != 0)
00356             delete phat;  
00357         phat = new Vector(size);
00358         if (phat == 0 || phat->Size() != size) { 
00359             opserr << "FATAL DistributedDisplacementControl::domainChanged() - ran out of memory for";
00360             opserr << " phat Vector of size " << size << endln;
00361             exit(-1);
00362         }
00363     }    
00364 
00365     // now we have to determine phat
00366     // do this by incrementing lambda by 1, applying load
00367     // and getting phat from unbalance.
00368     currentLambda = theModel->getCurrentDomainTime();
00369 
00370     currentLambda += 1.0;
00371     theModel->applyLoadDomain(currentLambda);    
00372 
00373     this->formUnbalance(); // NOTE: this assumes unbalance at last was 0
00374     (*phat) = theLinSOE->getB();
00375 
00376     currentLambda -= 1.0;
00377     theModel->setCurrentDomainTime(currentLambda);    
00378 
00379     // check there is a reference load
00380     int haveLoad = 0;
00381     for (int i=0; i<size; i++)
00382       if ( (*phat)(i) != 0.0 ) {
00383         haveLoad = 1;
00384         i = size;
00385       }
00386 
00387     if (haveLoad == 0) {
00388       opserr << "WARNING DistributedDisplacementControl::domainChanged() - zero reference load";
00389       return -1;
00390     }
00391 
00392 
00393     if (theDofID == -1) {
00394       opserr << "DistributedDisplacementControl::setSize() - failed to find valid dof - are the node tag and dof values correct?\n";
00395       return -1;
00396     }
00397 
00398     return 0;
00399 }
00400 
00401 int
00402 DistributedDisplacementControl::sendSelf(int cTag, Channel &theChannel)
00403 {                                        
00404   int sendID =0;
00405 
00406   // if P0 check if already sent. If already sent use old processID; if not allocate a new process 
00407   // id for remote part of object, enlarge channel * to hold a channel * for this remote object.
00408 
00409   // if not P0, send current processID
00410 
00411   if (processID == 0) {
00412 
00413     // check if already using this object
00414     bool found = false;
00415     for (int i=0; i<numChannels; i++)
00416       if (theChannels[i] == &theChannel) {
00417         sendID = i+1;
00418         found = true;
00419       }
00420 
00421     // if new object, enlarge Channel pointers to hold new channel * & allocate new ID
00422     if (found == false) {
00423       int nextNumChannels = numChannels + 1;
00424       Channel **nextChannels = new Channel *[nextNumChannels];
00425       if (nextChannels == 0) {
00426         opserr << "DistributedDisplacementControl::sendSelf() - failed to allocate channel array of size: " << 
00427           nextNumChannels << endln;
00428         return -1;
00429       }
00430       for (int i=0; i<numChannels; i++)
00431         nextChannels[i] = theChannels[i];
00432       nextChannels[numChannels] = &theChannel;
00433       
00434       numChannels = nextNumChannels;
00435       
00436       if (theChannels != 0)
00437         delete [] theChannels;
00438       
00439       theChannels = nextChannels;
00440       
00441       // allocate new processID for remote object
00442       sendID = numChannels;
00443     }
00444 
00445   } else 
00446     sendID = processID;
00447 
00448   // send remotes processID & info about node, dof and numIncr
00449   static ID idData(3);
00450   idData(0) = sendID;
00451   idData(1) = theNode;
00452   idData(2) = theDof;
00453   int res = theChannel.sendID(0, cTag, idData);
00454   if (res < 0) {
00455     opserr <<"WARNING DistributedDisplacementControl::sendSelf() - failed to send data\n";
00456     return -1;
00457   }
00458 
00459   static Vector dData(5);
00460   dData(0) = theIncrement;
00461   dData(1) = minIncrement;
00462   dData(2) = maxIncrement;
00463   dData(3) = specNumIncrStep;
00464   dData(4) = numIncrLastStep;
00465   res = theChannel.sendVector(0, cTag, dData);
00466   if (res < 0) {
00467     opserr <<"WARNING DistributedDisplacementControl::recvSelf() - failed to recv vector data\n";
00468     return -1;
00469   }             
00470   
00471   return 0;
00472 }
00473 
00474 
00475 int
00476 DistributedDisplacementControl::recvSelf(int cTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00477                               
00478 {
00479   static ID idData(3);
00480   int res = theChannel.recvID(0, cTag, idData);
00481   if (res < 0) {
00482     opserr <<"WARNING DistributedDisplacementControl::recvSelf() - failed to recv id data\n";
00483     return -1;
00484   }           
00485   processID = idData(0);
00486   theNode = idData(1);
00487   theDof  = idData(2);
00488 
00489   static Vector dData(5);
00490   res = theChannel.recvVector(0, cTag, dData);
00491   if (res < 0) {
00492     opserr <<"WARNING DistributedDisplacementControl::recvSelf() - failed to recv vector data\n";
00493     return -1;
00494   }             
00495 
00496   theIncrement = dData(0);
00497   minIncrement = dData(1);
00498   maxIncrement = dData(2);
00499   specNumIncrStep = dData(3);
00500   numIncrLastStep = dData(4);
00501 
00502   // set the Channel & processID
00503   numChannels = 1;
00504   theChannels = new Channel *[1];
00505   theChannels[0] = &theChannel;
00506 
00507   return 0;
00508 }
00509 
00510 void
00511 DistributedDisplacementControl::Print(OPS_Stream &s, int flag)
00512 {
00513     // TO FINISH    
00514 }

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