Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

TransformationFE.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.1.1.1 $
00022 // $Date: 2000/09/15 08:23:16 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/transformation/TransformationFE.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/analysis/TransformationFE.C
00027 //
00028 // Written: fmk 
00029 
00030 // Created: 05/99
00031 // Revision: A
00032 //
00033 // Purpose: This file contains the code for implementing the methods
00034 // of the TransformationFE class interface.
00035 
00036 #include "TransformationFE.h"
00037 #include <stdlib.h>
00038 
00039 #include <Element.h>
00040 #include <Domain.h>
00041 #include <Node.h>
00042 #include <DOF_Group.h>
00043 #include <Integrator.h>
00044 #include <Subdomain.h>
00045 #include <AnalysisModel.h>
00046 #include <Matrix.h>
00047 #include <Vector.h>
00048 #include <TransformationConstraintHandler.h>
00049 
00050 #define MAX_NUM_DOF 64
00051 
00052 // static variables initialisation
00053 Matrix **TransformationFE::modMatrices; 
00054 Vector **TransformationFE::modVectors;  
00055 Matrix **TransformationFE::theTransformations; 
00056 int TransformationFE::numTransFE(0);           
00057 int TransformationFE::transCounter(0);           
00058 int TransformationFE::sizeTransformations(0);          
00059 double *TransformationFE::dataBuffer;          
00060 double *TransformationFE::localKbuffer;          
00061 int TransformationFE::sizeBuffer(0);            
00062 
00063 //  TransformationFE(Element *, Integrator *theIntegrator);
00064 // construictor that take the corresponding model element.
00065 TransformationFE::TransformationFE(Element *ele,
00066        TransformationConstraintHandler &theH) 
00067 :FE_Element(ele), theDOFs(0), numSPs(0), theSPs(0), modID(0), 
00068  modTangent(0), modResidual(0), numGroups(0), numEleNodalDOF(0), theHandler(&theH)
00069 {
00070     // create the array of pointers to DOF_Groups
00071     const ID &nodes = ele->getExternalNodes();
00072     Domain *theDomain = ele->getDomain();
00073     int numNodes = nodes.Size();
00074     theDOFs = new DOF_Group *[numNodes];
00075     if (theDOFs == 0) {
00076  cerr << "FATAL TransformationFE::TransformationFE() - out of memory craeting ";
00077  cerr << "array of size : " << numNodes << " for storage of DOF_Group\n";
00078  exit(-1);
00079     }
00080 
00081     numGroups = numNodes;
00082     numEleNodalDOF = ele->getNumDOF()/numNodes;
00083 
00084     // now fill the array of DOF_Group pointers
00085     for (int i=0; i<numNodes; i++) {
00086  Node *theNode = theDomain->getNode(nodes(i));
00087  if (theNode == 0) {
00088      cerr << "FATAL TransformationFE::TransformationFE() - no Node with tag: ";
00089      cerr << nodes(i) << " in the domain\n";;
00090      exit(-1);
00091  }
00092  DOF_Group *theDofGroup = theNode->getDOF_GroupPtr();
00093  if (theDofGroup == 0) {
00094      cerr << "FATAL TransformationFE::TransformationFE() - no DOF_Group : ";
00095      cerr << " associated with node: " << nodes(i) << " in the domain\n";;
00096      exit(-1);
00097  } 
00098  theDOFs[i] = theDofGroup;
00099     }
00100 
00101     // see if theTransformation array is big enough
00102     // if not delete the old and create a new one
00103     if (numNodes > sizeTransformations) {
00104  if (theTransformations != 0) 
00105      delete [] theTransformations;
00106  
00107  theTransformations = new Matrix *[numNodes];
00108  if (theTransformations == 0) {
00109      cerr << "FATAL TransformationFE::TransformationFE() - out of memory ";
00110      cerr << "for array of pointers for Transformation matrices of size ";
00111      cerr << numNodes;
00112      exit(-1);
00113  }      
00114  sizeTransformations = numNodes;
00115     } 
00116 
00117     // if this is the first element of this type create the arrays for 
00118     // modified tangent and residual matrices
00119     if (numTransFE == 0) {
00120  modMatrices = new Matrix *[MAX_NUM_DOF+1];
00121  modVectors  = new Vector *[MAX_NUM_DOF+1];
00122  dataBuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF];
00123  localKbuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF];
00124  sizeBuffer = MAX_NUM_DOF*MAX_NUM_DOF;
00125  
00126  if (modMatrices == 0 || modVectors == 0) {
00127      cerr << "TransformationFE::TransformationFE(Element *) ";
00128      cerr << " ran out of memory";     
00129  }
00130  for (int i=0; i<MAX_NUM_DOF; i++) {
00131      modMatrices[i] = 0;
00132      modVectors[i] = 0;
00133  }
00134     }
00135 
00136     // increment the number of transformations
00137     numTransFE++;
00138 }
00139 
00140 
00141 
00142 // ~TransformationFE();    
00143 // destructor.
00144 
00145 TransformationFE::~TransformationFE()
00146 {
00147     numTransFE--;
00148     
00149     if (theDOFs != 0)
00150  delete [] theDOFs;
00151     if (theSPs != 0)
00152  delete [] theSPs;
00153 
00154     int numDOF = 0;    
00155     if (modID != 0)
00156  numDOF = modID->Size();
00157     
00158     if (modID != 0)
00159  delete modID;
00160 
00161     if (numDOF > MAX_NUM_DOF) {
00162  // tangent and residual may have been  created specially
00163  if (modTangent != 0) delete modTangent;
00164  if (modResidual != 0) delete modResidual;
00165     }
00166 
00167     // if this is the last FE_Element, clean up the
00168     // storage for the matrix and vector objects
00169     if (numTransFE == 0) {
00170  for (int i=0; i<MAX_NUM_DOF; i++) {
00171      if (modVectors[i] != 0)
00172   delete modVectors[i];
00173      if (modMatrices[i] != 0)
00174   delete modMatrices[i];
00175  }
00176  delete [] modMatrices;
00177  delete [] modVectors;
00178  delete [] theTransformations;
00179  delete [] dataBuffer;
00180  delete [] localKbuffer;
00181  modMatrices = 0;
00182  modVectors = 0;
00183  theTransformations = 0;
00184  dataBuffer = 0;
00185  localKbuffer = 0;
00186  sizeTransformations = 0;
00187  sizeBuffer = 0;
00188  transCounter = 0;
00189     }
00190 }    
00191 
00192 
00193 const ID &
00194 TransformationFE::getDOFtags(void) const 
00195 {
00196     return this->FE_Element::getDOFtags();
00197 }
00198 
00199 
00200 const ID &
00201 TransformationFE::getID(void) const
00202 {
00203     // make sure that it exists
00204     if (modID == 0) {
00205  cerr << "FATAL TransformationFE::getID() called before setID()\n";
00206  exit(-1);
00207     }
00208     return *modID;
00209 }
00210 
00211 
00212 int
00213 TransformationFE::setID(void)
00214 {
00215     // get the TransformationDOF_Groups to do their ID stuff
00216     if (transCounter == 0) {
00217  transCounter++;
00218  theHandler->doneDOFids();
00219     } else if (transCounter == numTransFE)
00220  transCounter = 0;    
00221     else
00222  transCounter++;
00223 
00224     // determine number of DOF
00225     int numDOF = 0;
00226     for (int ii=0; ii<numGroups; ii++) {
00227  DOF_Group *dofPtr = theDOFs[ii];
00228  numDOF += dofPtr->getNumDOF();
00229     }
00230 
00231     // create an ID to hold the array, cannot use existing as 
00232     // may be different size
00233     modID = new ID(numDOF);
00234     if (modID == 0 || modID->Size() == 0) {
00235  cerr << "TransformationFE::setID() ";
00236  cerr << " ran out of memory for ID of size :";
00237  cerr << numDOF << endl;
00238  exit(-1);
00239     }
00240 
00241     // fill in the ID
00242     int current = 0;
00243     for (int i=0; i<numGroups; i++) {
00244  DOF_Group *dofPtr = theDOFs[i];
00245  const ID &theDOFid = dofPtr->getID();
00246 
00247  for (int j=0; j<theDOFid.Size(); j++)  
00248      if (current < numDOF)
00249   (*modID)(current++) = theDOFid(j);
00250      else {
00251   cerr << "WARNING TransformationFE::setID() - numDOF and";
00252   cerr << " number of dof at the DOF_Groups\n";
00253   return -3;
00254      }  
00255     }
00256     
00257     // set the pointers to the modified tangent matrix and residual vector
00258     if (numDOF <= MAX_NUM_DOF) {
00259  // use class wide objects
00260  if (modVectors[numDOF] == 0) {
00261      modVectors[numDOF] = new Vector(numDOF);
00262      modMatrices[numDOF] = new Matrix(numDOF,numDOF);
00263      modResidual = modVectors[numDOF];
00264      modTangent = modMatrices[numDOF];
00265      if (modResidual == 0 || modResidual->Size() != numDOF || 
00266   modTangent == 0 || modTangent->noCols() != numDOF) {  
00267   cerr << "TransformationFE::setID() ";
00268   cerr << " ran out of memory for vector/Matrix of size :";
00269   cerr << numDOF << endl;
00270   exit(-1);
00271      }
00272  } else {
00273      modResidual = modVectors[numDOF];
00274      modTangent = modMatrices[numDOF];
00275  }
00276     } else {
00277  // create matrices and vectors for each object instance
00278  modResidual = new Vector(numDOF);
00279  modTangent = new Matrix(numDOF, numDOF);
00280  if (modResidual == 0 || modResidual->Size() ==0 ||
00281      modTangent ==0 || modTangent->noRows() ==0) {
00282      
00283      cerr << "TransformationFE::setID() ";
00284      cerr << " ran out of memory for vector/Matrix of size :";
00285      cerr << numDOF << endl;
00286      exit(-1);
00287  }
00288     }     
00289 
00290     return 0;
00291 }
00292 
00293 const Matrix &
00294 TransformationFE::getTangent(Integrator *theNewIntegrator)
00295 {
00296     // impose the SP_Constraints at the nodes
00297     if (transCounter == 0) {
00298  transCounter++;
00299  theHandler->enforceSPs();
00300     } else if (transCounter == numTransFE)
00301  transCounter = 0;
00302     else
00303  transCounter++;
00304      
00305     const Matrix &theTangent = this->FE_Element::getTangent(theNewIntegrator);
00306 
00307     // DO THE SP STUFF TO THE TANGENT 
00308     
00309     // get the transformation matrix from each dof group
00310     int numNode = numGroups;
00311     for (int a = 0; a<numNode; a++)
00312  theTransformations[a] = theDOFs[a]->getT();
00313 
00314     // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00315     // where blocks are of size equal to num ele dof at a node
00316     int startRow = 0;
00317 
00318     Matrix *localK = new Matrix(localKbuffer, numEleNodalDOF, numEleNodalDOF);
00319     
00320     // foreach block row, for each block col do
00321     for (int i=0; i<numNode; i++) {
00322  int noRows = 0;
00323  int startCol = 0;
00324  
00325  for (int j=0; j<numNode; j++) {
00326      
00327      const Matrix *Ti = theTransformations[i];
00328      const Matrix *Tj = theTransformations[j];
00329      
00330      // copy K(i,j) into localK matrix
00331      // CHECK SIZE OF BUFFFER     
00332      for (int a=0; a<numEleNodalDOF; a++)
00333   for (int b=0; b<numEleNodalDOF; b++)
00334       (*localK)(a,b) = theTangent(i*numEleNodalDOF+a, j*numEleNodalDOF+b);
00335      
00336      // now perform the matrix computation T(i)^T localK T(j)
00337      // note: if T == 0 then the Identity is assumed
00338      int noCols = 0;
00339      Matrix *localTtKT;
00340      
00341      if (Ti != 0 && Tj != 0) {
00342   noRows = Ti->noCols();
00343   noCols = Tj->noCols();
00344   // CHECK SIZE OF BUFFFER
00345   localTtKT = new Matrix(dataBuffer, noRows, noCols);
00346   *localTtKT = (*Ti)^(*localK)*(*Tj);
00347      } else if (Ti== 0 && Tj != 0) {
00348   noRows = numEleNodalDOF;
00349   noCols = Tj->noCols();
00350   // CHECK SIZE OF BUFFFER
00351   localTtKT = new Matrix(dataBuffer, noRows, noCols);
00352   *localTtKT = (*localK)*(*Tj);  
00353      } else if (Ti != 0 && Tj == 0) {
00354   noRows = Ti->noCols();
00355   noCols = numEleNodalDOF;
00356   // CHECK SIZE OF BUFFFER
00357   localTtKT = new Matrix(dataBuffer, noRows, noCols);
00358   *localTtKT = (*Ti)^(*localK);
00359      } else {
00360   noRows = numEleNodalDOF;
00361   noCols = numEleNodalDOF;
00362   localTtKT = localK;
00363      }
00364      // now copy into modTangent the T(i)^t K(i,j) T(j) product
00365      for (int c=0; c<noRows; c++) 
00366   for (int d=0; d<noCols; d++) 
00367       (*modTangent)(startRow+c, startCol+d) = (*localTtKT)(c,d);
00368      
00369      if (localTtKT  != localK)
00370   delete localTtKT;
00371      
00372      startCol += noCols;
00373  }
00374  startRow += noRows;
00375     }
00376 
00377     delete localK;
00378     return *modTangent;
00379 }
00380 
00381 
00382 const Vector &
00383 TransformationFE::getResidual(Integrator *theNewIntegrator)
00384 {
00385     // impose the SP_Constraints at the nodes
00386     if (transCounter == 0) {
00387  transCounter++;
00388  theHandler->enforceSPs();
00389     } else if (transCounter == numTransFE)
00390  transCounter = 0;
00391     else
00392  transCounter++;
00393      
00394     const Vector &theResidual = this->FE_Element::getResidual(theNewIntegrator);
00395 
00396     // DO THE SP STUFF TO THE TANGENT
00397     
00398     // perform Tt R  -- as T is block diagonal do T(i)^T R(i)
00399     // where blocks are of size equal to num ele dof at a node
00400 
00401     int startRow = 0;
00402     int numNode = numGroups;
00403     
00404     // foreach block row, for each block col do
00405     for (int i=0; i<numNode; i++) {
00406  int noRows = 0;
00407  int noCols = 0;
00408  const Matrix *Ti = theDOFs[i]->getT();
00409  if (Ti != 0) {
00410      noRows = Ti->noCols();
00411      noCols = numEleNodalDOF;
00412      for (int j=0; j<noRows; j++) {
00413   double sum = 0;
00414   for (int k=0; k<noCols; k++)
00415       sum += (*Ti)(k,j) * theResidual(i*numEleNodalDOF + k);
00416   (*modResidual)(startRow +j) = sum;
00417      }
00418  } else {
00419      noRows = numEleNodalDOF;
00420      for (int j=0; j<noRows; j++)
00421   (*modResidual)(startRow +j) = theResidual(i*numEleNodalDOF + j);
00422  }
00423  startRow += noRows;
00424     }
00425     return *modResidual;
00426 }
00427 
00428 
00429 
00430 
00431 const Vector &
00432 TransformationFE::getTangForce(const Vector &disp, double fact)
00433 {
00434     cerr << "TransformationFE::getTangForce() - not yet implemented\n";
00435     modResidual->Zero();
00436     return *modResidual;
00437 }
00438 
00439 const Vector &
00440 TransformationFE::getKtForce(const Vector &disp, double fact)
00441 {
00442     cerr << "TransformationFE::getKtForce() - not yet implemented\n";
00443     modResidual->Zero();
00444     return *modResidual;
00445 }
00446 
00447 
00448 const Vector &
00449 TransformationFE::getKsForce(const Vector &disp, double fact)
00450 {
00451     cerr << "TransformationFE::getKsForce() - not yet implemented\n";
00452     modResidual->Zero();
00453     return *modResidual;
00454 }
00455 
00456 
00457 
00458 const Vector &
00459 TransformationFE::getD_Force(const Vector &vel, double fact)
00460 {
00461     cerr << "TransformationFE::getD_Force() - not yet implemented\n";
00462     modResidual->Zero();
00463     return *modResidual;
00464 }
00465 
00466 
00467 
00468 
00469 const Vector &
00470 TransformationFE::getM_Force(const Vector &accel, double fact)
00471 {
00472   cerr << "TransformationFE::getM_Force() - not yet implemented\n";
00473   modResidual->Zero();
00474   return *modResidual;
00475 }
00476 
00477 
00478 // CHANGE THE ID SENT
00479 const Vector &
00480 TransformationFE::getLastResponse(void)
00481 {
00482     Integrator *theLastIntegrator = this->getLastIntegrator();
00483     if (theLastIntegrator != 0) {
00484  if (theLastIntegrator->getLastResponse(*modResidual,*modID) < 0) {
00485      cerr << "WARNING TransformationFE::getLastResponse(void)";
00486      cerr << " - the Integrator had problems with getLastResponse()\n";
00487  }
00488     }
00489     else {
00490  modResidual->Zero();
00491  cerr << "WARNING  TransformationFE::getLastResponse()";
00492  cerr << " No Integrator yet passed\n";
00493     }
00494     
00495     Vector &result = *modResidual;
00496     return result;
00497 }
00498 
00499 
00500 void  
00501 TransformationFE::addKtForce(const Vector &disp,  double fact)
00502 {
00503     if (fact == 0.0)
00504  return;
00505 
00506     int size = numGroups*numEleNodalDOF;
00507     Vector response(dataBuffer, size);
00508       
00509     int numDOF = modID->Size();    
00510     for (int i=0; i<numDOF; i++) {
00511  int loc = (*modID)(i);
00512  if (loc >= 0)
00513      (*modResidual)(i) = disp(loc);
00514  else
00515      (*modResidual)(i) = 0.0;
00516     }
00517     transformResponse(*modResidual, response);
00518     this->addLocalKtForce(response, fact);
00519 }     
00520 
00521 
00522 void  
00523 TransformationFE::addKsForce(const Vector &disp,  double fact)
00524 {
00525     if (fact == 0.0)
00526  return;
00527 
00528     int size = numGroups*numEleNodalDOF;
00529     Vector response(dataBuffer, size);
00530       
00531     int numDOF = modID->Size();    
00532     for (int i=0; i<numDOF; i++) {
00533  int loc = (*modID)(i);
00534  if (loc >= 0)
00535      (*modResidual)(i) = disp(loc);
00536  else
00537      (*modResidual)(i) = 0.0;
00538     }
00539     transformResponse(*modResidual, response);
00540     this->addLocalKsForce(response, fact);
00541 }     
00542 
00543 void  
00544 TransformationFE::addKiForce(const Vector &disp,  double fact)
00545 {
00546     if (fact == 0.0)
00547  return;
00548 
00549     int size = numGroups*numEleNodalDOF;
00550     Vector response(dataBuffer, size);
00551       
00552     int numDOF = modID->Size();    
00553     for (int i=0; i<numDOF; i++) {
00554  int loc = (*modID)(i);
00555  if (loc >= 0)
00556      (*modResidual)(i) = disp(loc);
00557  else
00558      (*modResidual)(i) = 0.0;
00559     }
00560     transformResponse(*modResidual, response);
00561     this->addLocalKiForce(response, fact);
00562 }     
00563 
00564 
00565 void  
00566 TransformationFE::addKcForce(const Vector &disp,  double fact)
00567 {
00568     if (fact == 0.0)
00569  return;
00570 
00571     int size = numGroups*numEleNodalDOF;
00572     Vector response(dataBuffer, size);
00573       
00574     int numDOF = modID->Size();    
00575     for (int i=0; i<numDOF; i++) {
00576  int loc = (*modID)(i);
00577  if (loc >= 0)
00578      (*modResidual)(i) = disp(loc);
00579  else
00580      (*modResidual)(i) = 0.0;
00581     }
00582     transformResponse(*modResidual, response);
00583     this->addLocalKcForce(response, fact);
00584 }     
00585 
00586 
00587 void  
00588 TransformationFE::addD_Force(const Vector &disp,  double fact)
00589 {
00590     if (fact == 0.0)
00591  return;
00592 
00593     int size = numGroups*numEleNodalDOF;
00594     Vector response(dataBuffer, size);
00595       
00596     int numDOF = modID->Size();    
00597     for (int i=0; i<numDOF; i++) {
00598  int loc = (*modID)(i);
00599  if (loc >= 0)
00600      (*modResidual)(i) = disp(loc);
00601  else
00602      (*modResidual)(i) = 0.0;
00603     }
00604     transformResponse(*modResidual, response);
00605     this->addLocalD_Force(response, fact);
00606 }     
00607 
00608 void  
00609 TransformationFE::addM_Force(const Vector &disp,  double fact)
00610 {
00611     if (fact == 0.0)
00612  return;
00613 
00614     int size = numGroups*numEleNodalDOF;
00615     Vector response(dataBuffer, size);
00616       
00617     int numDOF = modID->Size();    
00618     for (int i=0; i<numDOF; i++) {
00619  int loc = (*modID)(i);
00620  if (loc >= 0)
00621      (*modResidual)(i) = disp(loc);
00622  else
00623      (*modResidual)(i) = 0.0;
00624     }
00625     transformResponse(*modResidual, response);
00626     this->addLocalM_Force(response, fact);
00627 }     
00628 
00629 int 
00630 TransformationFE::transformResponse(const Vector &modResp, 
00631         Vector &unmodResp)
00632 {
00633     // perform T R  -- as T is block diagonal do T(i) R(i)
00634     // where blocks are of size equal to num ele dof at a node
00635 
00636     int startRow = 0;
00637     int numNode = numGroups;
00638 
00639     for (int i=0; i<numNode; i++) {
00640  int noRows = 0;
00641  int noCols = 0;
00642  const Matrix *Ti = theDOFs[i]->getT();
00643  if (Ti != 0) {
00644      noRows = numEleNodalDOF;
00645      noCols = Ti->noCols();
00646      for (int j=0; j<noRows; j++) {
00647   double sum = 0.0;
00648   for (int k=0; k<noCols; k++)
00649       sum += (*Ti)(j,k) * modResp(startRow +k) ;
00650   unmodResp(i*numEleNodalDOF + j) = sum;
00651      }
00652  } else {
00653      noCols = numEleNodalDOF;
00654      for (int j=0; j<noCols; j++)
00655   unmodResp(i*numEleNodalDOF + j) = modResp(startRow +j);
00656  }
00657  startRow += noCols;
00658     }
00659     
00660     return 0;
00661 }
Copyright Contact Us