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.17 $
00022 // $Date: 2006/02/08 20:20:00 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/transformation/TransformationFE.cpp,v $
00024                                                                         
00025 // Written: fmk 
00026 // Created: 05/99
00027 //
00028 // Purpose: This file contains the code for implementing the methods
00029 // of the TransformationFE class interface.
00030 
00031 #include "TransformationFE.h"
00032 #include <stdlib.h>
00033 
00034 #include <Element.h>
00035 #include <Domain.h>
00036 #include <Node.h>
00037 #include <DOF_Group.h>
00038 #include <Integrator.h>
00039 #include <Subdomain.h>
00040 #include <AnalysisModel.h>
00041 #include <Matrix.h>
00042 #include <Vector.h>
00043 #include <TransformationConstraintHandler.h>
00044 
00045 #define MAX_NUM_DOF 64
00046 
00047 // static variables initialisation
00048 Matrix **TransformationFE::modMatrices; 
00049 Vector **TransformationFE::modVectors;  
00050 Matrix **TransformationFE::theTransformations; 
00051 int TransformationFE::numTransFE(0);           
00052 int TransformationFE::transCounter(0);           
00053 int TransformationFE::sizeTransformations(0);          
00054 double *TransformationFE::dataBuffer = 0;          
00055 double *TransformationFE::localKbuffer = 0;          
00056 int    *TransformationFE::dofData = 0;    ;          
00057 int TransformationFE::sizeBuffer(0);            
00058 
00059 //  TransformationFE(Element *, Integrator *theIntegrator);
00060 //      construictor that take the corresponding model element.
00061 TransformationFE::TransformationFE(int tag, Element *ele)
00062 :FE_Element(tag, ele), theDOFs(0), numSPs(0), theSPs(0), modID(0), 
00063   modTangent(0), modResidual(0), numGroups(0), numTransformedDOF(0)
00064 {
00065   // set number of original dof at ele
00066     numOriginalDOF = ele->getNumDOF();
00067 
00068     // create the array of pointers to DOF_Groups
00069     const ID &nodes = ele->getExternalNodes();
00070     Domain *theDomain = ele->getDomain();
00071     int numNodes = nodes.Size();
00072     theDOFs = new DOF_Group *[numNodes];
00073     if (theDOFs == 0) {
00074         opserr << "FATAL TransformationFE::TransformationFE() - out of memory craeting ";
00075         opserr << "array of size : " << numNodes << " for storage of DOF_Group\n";
00076         exit(-1);
00077     }
00078 
00079     numGroups = numNodes;
00080 
00081     // now fill the array of DOF_Group pointers
00082     for (int i=0; i<numNodes; i++) {
00083         Node *theNode = theDomain->getNode(nodes(i));
00084         if (theNode == 0) {
00085             opserr << "FATAL TransformationFE::TransformationFE() - no Node with tag: ";
00086             opserr << nodes(i) << " in the domain\n";;
00087             exit(-1);
00088         }
00089         DOF_Group *theDofGroup = theNode->getDOF_GroupPtr();
00090         if (theDofGroup == 0) {
00091             opserr << "FATAL TransformationFE::TransformationFE() - no DOF_Group : ";
00092             opserr << " associated with node: " << nodes(i) << " in the domain\n";;
00093             exit(-1);
00094         }       
00095         theDOFs[i] = theDofGroup;
00096     }
00097 
00098     // see if theTransformation array is big enough
00099     // if not delete the old and create a new one
00100     if (numNodes > sizeTransformations) {
00101         if (theTransformations != 0) 
00102             delete [] theTransformations;
00103         
00104         theTransformations = new Matrix *[numNodes];
00105         if (theTransformations == 0) {
00106             opserr << "FATAL TransformationFE::TransformationFE() - out of memory ";
00107             opserr << "for array of pointers for Transformation matrices of size ";
00108             opserr << numNodes;
00109             exit(-1);
00110         }                   
00111         sizeTransformations = numNodes;
00112     }   
00113 
00114     // if this is the first element of this type create the arrays for 
00115     // modified tangent and residual matrices
00116     if (numTransFE == 0) {
00117 
00118         modMatrices = new Matrix *[MAX_NUM_DOF+1];
00119         modVectors  = new Vector *[MAX_NUM_DOF+1];
00120         dataBuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF];
00121         localKbuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF];
00122         dofData      = new int[MAX_NUM_DOF];
00123         sizeBuffer = MAX_NUM_DOF*MAX_NUM_DOF;
00124         
00125         if (modMatrices == 0 || modVectors == 0 || dataBuffer == 0 ||
00126             localKbuffer == 0 || dofData == 0) {
00127             opserr << "TransformationFE::TransformationFE(Element *) ";
00128             opserr << " 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         delete [] dofData;
00182         modMatrices = 0;
00183         modVectors = 0;
00184         theTransformations = 0;
00185         dataBuffer = 0;
00186         localKbuffer = 0;
00187         dofData = 0;
00188         sizeTransformations = 0;
00189         sizeBuffer = 0;
00190         transCounter = 0;
00191     }
00192 }    
00193 
00194 
00195 const ID &
00196 TransformationFE::getDOFtags(void) const 
00197 {
00198     return this->FE_Element::getDOFtags();
00199 }
00200 
00201 
00202 const ID &
00203 TransformationFE::getID(void) const
00204 {
00205     // make sure that it exists
00206     if (modID == 0) {
00207         opserr << "FATAL TransformationFE::getID() called before setID()\n";
00208         exit(-1);
00209     }
00210     return *modID;
00211 }
00212 
00213 
00214 int
00215 TransformationFE::setID(void)
00216 {
00217     // determine number of DOF
00218     numTransformedDOF = 0;
00219     for (int ii=0; ii<numGroups; ii++) {
00220         DOF_Group *dofPtr = theDOFs[ii];
00221         numTransformedDOF += dofPtr->getNumDOF();
00222     }
00223 
00224     // create an ID to hold the array, cannot use existing as 
00225     // may be different size
00226     modID = new ID(numTransformedDOF);
00227     if (modID == 0 || modID->Size() == 0) {
00228         opserr << "TransformationFE::setID() ";
00229         opserr << " ran out of memory for ID of size :";
00230         opserr << numTransformedDOF << endln;
00231         exit(-1);
00232     }
00233 
00234     // fill in the ID
00235     int current = 0;
00236     for (int i=0; i<numGroups; i++) {
00237         DOF_Group *dofPtr = theDOFs[i];
00238         const ID &theDOFid = dofPtr->getID();
00239 
00240         for (int j=0; j<theDOFid.Size(); j++)  
00241             if (current < numTransformedDOF)
00242                 (*modID)(current++) = theDOFid(j);
00243             else {
00244                 opserr << "WARNING TransformationFE::setID() - numDOF and";
00245                 opserr << " number of dof at the DOF_Groups\n";
00246                 return -3;
00247             }           
00248     }
00249     
00250     // set the pointers to the modified tangent matrix and residual vector
00251     if (numTransformedDOF <= MAX_NUM_DOF) {
00252         // use class wide objects
00253         if (modVectors[numTransformedDOF] == 0) {
00254             modVectors[numTransformedDOF] = new Vector(numTransformedDOF);
00255             modMatrices[numTransformedDOF] = new Matrix(numTransformedDOF,numTransformedDOF);
00256             modResidual = modVectors[numTransformedDOF];
00257             modTangent = modMatrices[numTransformedDOF];
00258             if (modResidual == 0 || modResidual->Size() != numTransformedDOF || 
00259                 modTangent == 0 || modTangent->noCols() != numTransformedDOF)   {  
00260                 opserr << "TransformationFE::setID() ";
00261                 opserr << " ran out of memory for vector/Matrix of size :";
00262                 opserr << numTransformedDOF << endln;
00263                 exit(-1);
00264             }
00265         } else {
00266             modResidual = modVectors[numTransformedDOF];
00267             modTangent = modMatrices[numTransformedDOF];
00268         }
00269     } else {
00270         // create matrices and vectors for each object instance
00271         modResidual = new Vector(numTransformedDOF);
00272         modTangent = new Matrix(numTransformedDOF, numTransformedDOF);
00273         if (modResidual == 0 || modResidual->Size() ==0 ||
00274             modTangent ==0 || modTangent->noRows() ==0) {
00275             
00276             opserr << "TransformationFE::setID() ";
00277             opserr << " ran out of memory for vector/Matrix of size :";
00278             opserr << numTransformedDOF << endln;
00279             exit(-1);
00280         }
00281     }     
00282 
00283     return 0;
00284 }
00285 
00286 const Matrix &
00287 TransformationFE::getTangent(Integrator *theNewIntegrator)
00288 {
00289     const Matrix &theTangent = this->FE_Element::getTangent(theNewIntegrator);
00290 
00291     static ID numDOFs(dofData, 1);
00292     numDOFs.setData(dofData, numGroups);
00293     
00294     // DO THE SP STUFF TO THE TANGENT 
00295     
00296     // get the transformation matrix from each dof group & number of local dof
00297     // for original node.
00298     int numNode = numGroups;
00299     for (int a = 0; a<numNode; a++) {
00300       Matrix *theT = theDOFs[a]->getT();
00301       theTransformations[a] = theT;
00302       if (theT != 0)
00303         numDOFs[a] = theT->noRows(); // T^ 
00304       else
00305         numDOFs[a] = theDOFs[a]->getNumDOF();
00306     }
00307 
00308     // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00309     // where blocks are of size equal to num ele dof at a node
00310 
00311     int startRow = 0;
00312     int noRowsTransformed = 0;
00313     int noRowsOriginal = 0;
00314 
00315     static Matrix localK;
00316 
00317     // foreach block row, for each block col do
00318     for (int i=0; i<numNode; i++) {
00319 
00320         int startCol = 0;
00321         int numDOFi = numDOFs[i];       
00322         int noColsOriginal = 0;
00323 
00324         for (int j=0; j<numNode; j++) {
00325 
00326             const Matrix *Ti = theTransformations[i];
00327             const Matrix *Tj = theTransformations[j];
00328             int numDOFj = numDOFs[j];   
00329             localK.setData(localKbuffer, numDOFi, numDOFj);
00330 
00331             // copy K(i,j) into localK matrix
00332             // CHECK SIZE OF BUFFFER        
00333             for (int a=0; a<numDOFi; a++)
00334                 for (int b=0; b<numDOFj; b++)
00335                     localK(a,b) = theTangent(noRowsOriginal+a, noColsOriginal+b);
00336 
00337             // now perform the matrix computation T(i)^T localK T(j)
00338             // note: if T == 0 then the Identity is assumed
00339             int noColsTransformed = 0;
00340             static Matrix localTtKT;
00341             
00342             if (Ti != 0 && Tj != 0) {
00343                 noRowsTransformed = Ti->noCols();
00344                 noColsTransformed = Tj->noCols();
00345                 // CHECK SIZE OF BUFFFER
00346                 localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00347                 localTtKT = (*Ti) ^ localK * (*Tj);
00348             } else if (Ti == 0 && Tj != 0) {
00349                 noRowsTransformed = numDOFi;
00350                 noColsTransformed = Tj->noCols();
00351                 // CHECK SIZE OF BUFFFER
00352                 localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00353                 // localTtKT = localK * (*Tj);         
00354                 localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0);
00355             } else if (Ti != 0 && Tj == 0) {
00356                 noRowsTransformed = Ti->noCols();
00357                 noColsTransformed = numDOFj;
00358                 // CHECK SIZE OF BUFFFER
00359                 localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00360                 localTtKT = (*Ti) ^ localK;
00361             } else {
00362                 noRowsTransformed = numDOFi;
00363                 noColsTransformed = numDOFj;
00364                 localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00365                 localTtKT = localK;
00366             }
00367             // now copy into modTangent the T(i)^t K(i,j) T(j) product
00368             for (int c=0; c<noRowsTransformed; c++) 
00369                 for (int d=0; d<noColsTransformed; d++) 
00370                     (*modTangent)(startRow+c, startCol+d) = localTtKT(c,d);
00371             
00372             startCol += noColsTransformed;
00373             noColsOriginal += numDOFj;
00374         }
00375 
00376         noRowsOriginal += numDOFi;
00377         startRow += noRowsTransformed;
00378     }
00379 
00380     return *modTangent;
00381 }
00382 
00383 
00384 const Vector &
00385 TransformationFE::getResidual(Integrator *theNewIntegrator)
00386 
00387 {
00388     const Vector &theResidual = this->FE_Element::getResidual(theNewIntegrator);
00389     // DO THE SP STUFF TO THE TANGENT
00390     
00391     // perform Tt R  -- as T is block diagonal do T(i)^T R(i)
00392     // where blocks are of size equal to num ele dof at a node
00393 
00394     int startRowTransformed = 0;
00395     int startRowOriginal = 0;
00396     int numNode = numGroups;
00397 
00398     // foreach block row, for each block col do
00399     for (int i=0; i<numNode; i++) {
00400         int noRows = 0;
00401         int noCols = 0;
00402         const Matrix *Ti = theDOFs[i]->getT();
00403         if (Ti != 0) {
00404           noRows = Ti->noCols(); // T^
00405           noCols = Ti->noRows();
00406 
00407           /*
00408           Vector orig(noCols);
00409           Vector mod(noRows);
00410           for (int k=startRowOriginal; k<startRowOriginal+noCols; k++)
00411             orig(k-startRowOriginal)= theResidual(k);
00412           mod = (*Ti)^orig;
00413           for (int k=startRowTransformed; k<startRowTransformed+noRows; k++)
00414             (*modResidual)(k) = mod (k-startRowTransformed);
00415 
00416           */
00417 
00418           for (int j=0; j<noRows; j++) {
00419             double sum = 0.0;
00420             for (int k=0; k<noCols; k++)
00421               sum += (*Ti)(k,j) * theResidual(startRowOriginal + k);
00422             (*modResidual)(startRowTransformed +j) = sum;
00423           }
00424 
00425         } else {
00426           noCols = theDOFs[i]->getNumDOF();
00427           noRows = noCols;
00428           for (int j=0; j<noRows; j++)
00429             (*modResidual)(startRowTransformed +j) = theResidual(startRowOriginal + j);
00430         }
00431         startRowTransformed += noRows;
00432         startRowOriginal += noCols;
00433     }
00434 
00435     return *modResidual;
00436 }
00437 
00438 
00439 
00440 
00441 const Vector &
00442 TransformationFE::getTangForce(const Vector &disp, double fact)
00443 {
00444     opserr << "TransformationFE::getTangForce() - not yet implemented\n";
00445     modResidual->Zero();
00446     return *modResidual;
00447 }
00448 
00449 const Vector &
00450 TransformationFE::getK_Force(const Vector &accel, double fact)
00451 {
00452   this->FE_Element::zeroTangent();    
00453   this->FE_Element::addKtToTang();    
00454   const Matrix &theTangent = this->FE_Element::getTangent(0);
00455 
00456   static ID numDOFs(dofData, 1);
00457   numDOFs.setData(dofData, numGroups);
00458     
00459   // DO THE SP STUFF TO THE TANGENT 
00460   
00461   // get the transformation matrix from each dof group & number of local dof
00462   // for original node.
00463   int numNode = numGroups;
00464   for (int a = 0; a<numNode; a++) {
00465     Matrix *theT = theDOFs[a]->getT();
00466     theTransformations[a] = theT;
00467     if (theT != 0)
00468       numDOFs[a] = theT->noRows(); // T^ 
00469     else
00470       numDOFs[a] = theDOFs[a]->getNumDOF();
00471   }
00472   
00473   // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00474   // where blocks are of size equal to num ele dof at a node
00475   
00476   int startRow = 0;
00477   int noRowsTransformed = 0;
00478   int noRowsOriginal = 0;
00479   
00480   static Matrix localK;
00481   
00482   // foreach block row, for each block col do
00483   for (int i=0; i<numNode; i++) {
00484     
00485     int startCol = 0;
00486     int numDOFi = numDOFs[i];   
00487     int noColsOriginal = 0;
00488     
00489     for (int j=0; j<numNode; j++) {
00490       
00491       const Matrix *Ti = theTransformations[i];
00492       const Matrix *Tj = theTransformations[j];
00493       int numDOFj = numDOFs[j]; 
00494       localK.setData(localKbuffer, numDOFi, numDOFj);
00495       
00496       // copy K(i,j) into localK matrix
00497       // CHECK SIZE OF BUFFFER      
00498       for (int a=0; a<numDOFi; a++)
00499         for (int b=0; b<numDOFj; b++)
00500           localK(a,b) = theTangent(noRowsOriginal+a, noColsOriginal+b);
00501       
00502       // now perform the matrix computation T(i)^T localK T(j)
00503       // note: if T == 0 then the Identity is assumed
00504       int noColsTransformed = 0;
00505       static Matrix localTtKT;
00506       
00507       if (Ti != 0 && Tj != 0) {
00508         noRowsTransformed = Ti->noCols();
00509         noColsTransformed = Tj->noCols();
00510         // CHECK SIZE OF BUFFFER
00511         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00512         localTtKT = (*Ti) ^ localK * (*Tj);
00513       } else if (Ti == 0 && Tj != 0) {
00514         noRowsTransformed = numDOFi;
00515         noColsTransformed = Tj->noCols();
00516         // CHECK SIZE OF BUFFFER
00517         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00518         // localTtKT = localK * (*Tj);         
00519         localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0);
00520       } else if (Ti != 0 && Tj == 0) {
00521         noRowsTransformed = Ti->noCols();
00522         noColsTransformed = numDOFj;
00523         // CHECK SIZE OF BUFFFER
00524         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00525         localTtKT = (*Ti) ^ localK;
00526       } else {
00527         noRowsTransformed = numDOFi;
00528         noColsTransformed = numDOFj;
00529         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00530         localTtKT = localK;
00531       }
00532       // now copy into modTangent the T(i)^t K(i,j) T(j) product
00533       for (int c=0; c<noRowsTransformed; c++) 
00534         for (int d=0; d<noColsTransformed; d++) 
00535           (*modTangent)(startRow+c, startCol+d) = localTtKT(c,d);
00536       
00537       startCol += noColsTransformed;
00538       noColsOriginal += numDOFj;
00539     }
00540     
00541     noRowsOriginal += numDOFi;
00542     startRow += noRowsTransformed;
00543   }
00544   
00545   // get the components we need out of the vector
00546   // and place in a temporary vector
00547   Vector tmp(numTransformedDOF);
00548   for (int j=0; j<numTransformedDOF; j++) {
00549     int dof = (*modID)(j);
00550     if (dof >= 0)
00551       tmp(j) = accel(dof);
00552     else
00553       tmp(j) = 0.0;
00554   }
00555 
00556   modResidual->addMatrixVector(0.0, *modTangent, tmp, 1.0);
00557 
00558   return *modResidual;
00559 }
00560 
00561 
00562 const Vector &
00563 TransformationFE::getKi_Force(const Vector &accel, double fact)
00564 {
00565   this->FE_Element::zeroTangent();    
00566   this->FE_Element::addKiToTang();    
00567   const Matrix &theTangent = this->FE_Element::getTangent(0);
00568 
00569   static ID numDOFs(dofData, 1);
00570   numDOFs.setData(dofData, numGroups);
00571     
00572   // DO THE SP STUFF TO THE TANGENT 
00573   
00574   // get the transformation matrix from each dof group & number of local dof
00575   // for original node.
00576   int numNode = numGroups;
00577   for (int a = 0; a<numNode; a++) {
00578     Matrix *theT = theDOFs[a]->getT();
00579     theTransformations[a] = theT;
00580     if (theT != 0)
00581       numDOFs[a] = theT->noRows(); // T^ 
00582     else
00583       numDOFs[a] = theDOFs[a]->getNumDOF();
00584   }
00585   
00586   // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00587   // where blocks are of size equal to num ele dof at a node
00588   
00589   int startRow = 0;
00590   int noRowsTransformed = 0;
00591   int noRowsOriginal = 0;
00592   
00593   static Matrix localK;
00594   
00595   // foreach block row, for each block col do
00596   for (int i=0; i<numNode; i++) {
00597     
00598     int startCol = 0;
00599     int numDOFi = numDOFs[i];   
00600     int noColsOriginal = 0;
00601     
00602     for (int j=0; j<numNode; j++) {
00603       
00604       const Matrix *Ti = theTransformations[i];
00605       const Matrix *Tj = theTransformations[j];
00606       int numDOFj = numDOFs[j]; 
00607       localK.setData(localKbuffer, numDOFi, numDOFj);
00608       
00609       // copy K(i,j) into localK matrix
00610       // CHECK SIZE OF BUFFFER      
00611       for (int a=0; a<numDOFi; a++)
00612         for (int b=0; b<numDOFj; b++)
00613           localK(a,b) = theTangent(noRowsOriginal+a, noColsOriginal+b);
00614       
00615       // now perform the matrix computation T(i)^T localK T(j)
00616       // note: if T == 0 then the Identity is assumed
00617       int noColsTransformed = 0;
00618       static Matrix localTtKT;
00619       
00620       if (Ti != 0 && Tj != 0) {
00621         noRowsTransformed = Ti->noCols();
00622         noColsTransformed = Tj->noCols();
00623         // CHECK SIZE OF BUFFFER
00624         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00625         localTtKT = (*Ti) ^ localK * (*Tj);
00626       } else if (Ti == 0 && Tj != 0) {
00627         noRowsTransformed = numDOFi;
00628         noColsTransformed = Tj->noCols();
00629         // CHECK SIZE OF BUFFFER
00630         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00631         // localTtKT = localK * (*Tj);         
00632         localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0);
00633       } else if (Ti != 0 && Tj == 0) {
00634         noRowsTransformed = Ti->noCols();
00635         noColsTransformed = numDOFj;
00636         // CHECK SIZE OF BUFFFER
00637         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00638         localTtKT = (*Ti) ^ localK;
00639       } else {
00640         noRowsTransformed = numDOFi;
00641         noColsTransformed = numDOFj;
00642         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00643         localTtKT = localK;
00644       }
00645       // now copy into modTangent the T(i)^t K(i,j) T(j) product
00646       for (int c=0; c<noRowsTransformed; c++) 
00647         for (int d=0; d<noColsTransformed; d++) 
00648           (*modTangent)(startRow+c, startCol+d) = localTtKT(c,d);
00649       
00650       startCol += noColsTransformed;
00651       noColsOriginal += numDOFj;
00652     }
00653     
00654     noRowsOriginal += numDOFi;
00655     startRow += noRowsTransformed;
00656   }
00657   
00658   // get the components we need out of the vector
00659   // and place in a temporary vector
00660   Vector tmp(numTransformedDOF);
00661   for (int j=0; j<numTransformedDOF; j++) {
00662     int dof = (*modID)(j);
00663     if (dof >= 0)
00664       tmp(j) = accel(dof);
00665     else
00666       tmp(j) = 0.0;
00667   }
00668 
00669   modResidual->addMatrixVector(0.0, *modTangent, tmp, 1.0);
00670 
00671   return *modResidual;
00672 }
00673 
00674 const Vector &
00675 TransformationFE::getM_Force(const Vector &accel, double fact)
00676 {
00677   this->FE_Element::zeroTangent();    
00678   this->FE_Element::addMtoTang();    
00679   const Matrix &theTangent = this->FE_Element::getTangent(0);
00680 
00681   static ID numDOFs(dofData, 1);
00682   numDOFs.setData(dofData, numGroups);
00683     
00684   // DO THE SP STUFF TO THE TANGENT 
00685   
00686   // get the transformation matrix from each dof group & number of local dof
00687   // for original node.
00688   int numNode = numGroups;
00689   for (int a = 0; a<numNode; a++) {
00690     Matrix *theT = theDOFs[a]->getT();
00691     theTransformations[a] = theT;
00692     if (theT != 0)
00693       numDOFs[a] = theT->noRows(); // T^ 
00694     else
00695       numDOFs[a] = theDOFs[a]->getNumDOF();
00696   }
00697   
00698   // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00699   // where blocks are of size equal to num ele dof at a node
00700   
00701   int startRow = 0;
00702   int noRowsTransformed = 0;
00703   int noRowsOriginal = 0;
00704   
00705   static Matrix localK;
00706   
00707   // foreach block row, for each block col do
00708   for (int i=0; i<numNode; i++) {
00709     
00710     int startCol = 0;
00711     int numDOFi = numDOFs[i];   
00712     int noColsOriginal = 0;
00713     
00714     for (int j=0; j<numNode; j++) {
00715       
00716       const Matrix *Ti = theTransformations[i];
00717       const Matrix *Tj = theTransformations[j];
00718       int numDOFj = numDOFs[j]; 
00719       localK.setData(localKbuffer, numDOFi, numDOFj);
00720       
00721       // copy K(i,j) into localK matrix
00722       // CHECK SIZE OF BUFFFER      
00723       for (int a=0; a<numDOFi; a++)
00724         for (int b=0; b<numDOFj; b++)
00725           localK(a,b) = theTangent(noRowsOriginal+a, noColsOriginal+b);
00726       
00727       // now perform the matrix computation T(i)^T localK T(j)
00728       // note: if T == 0 then the Identity is assumed
00729       int noColsTransformed = 0;
00730       static Matrix localTtKT;
00731       
00732       if (Ti != 0 && Tj != 0) {
00733         noRowsTransformed = Ti->noCols();
00734         noColsTransformed = Tj->noCols();
00735         // CHECK SIZE OF BUFFFER
00736         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00737         localTtKT = (*Ti) ^ localK * (*Tj);
00738       } else if (Ti == 0 && Tj != 0) {
00739         noRowsTransformed = numDOFi;
00740         noColsTransformed = Tj->noCols();
00741         // CHECK SIZE OF BUFFFER
00742         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00743         // localTtKT = localK * (*Tj);         
00744         localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0);
00745       } else if (Ti != 0 && Tj == 0) {
00746         noRowsTransformed = Ti->noCols();
00747         noColsTransformed = numDOFj;
00748         // CHECK SIZE OF BUFFFER
00749         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00750         localTtKT = (*Ti) ^ localK;
00751       } else {
00752         noRowsTransformed = numDOFi;
00753         noColsTransformed = numDOFj;
00754         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00755         localTtKT = localK;
00756       }
00757       // now copy into modTangent the T(i)^t K(i,j) T(j) product
00758       for (int c=0; c<noRowsTransformed; c++) 
00759         for (int d=0; d<noColsTransformed; d++) 
00760           (*modTangent)(startRow+c, startCol+d) = localTtKT(c,d);
00761       
00762       startCol += noColsTransformed;
00763       noColsOriginal += numDOFj;
00764     }
00765     
00766     noRowsOriginal += numDOFi;
00767     startRow += noRowsTransformed;
00768   }
00769   
00770   // get the components we need out of the vector
00771   // and place in a temporary vector
00772   Vector tmp(numTransformedDOF);
00773   for (int j=0; j<numTransformedDOF; j++) {
00774     int dof = (*modID)(j);
00775     if (dof >= 0)
00776       tmp(j) = accel(dof);
00777     else
00778       tmp(j) = 0.0;
00779   }
00780 
00781   modResidual->addMatrixVector(0.0, *modTangent, tmp, 1.0);
00782 
00783   return *modResidual;
00784 }
00785 
00786 const Vector &
00787 TransformationFE::getC_Force(const Vector &accel, double fact)
00788 {
00789   this->FE_Element::zeroTangent();    
00790   this->FE_Element::addCtoTang();    
00791   const Matrix &theTangent = this->FE_Element::getTangent(0);
00792 
00793   static ID numDOFs(dofData, 1);
00794   numDOFs.setData(dofData, numGroups);
00795     
00796   // DO THE SP STUFF TO THE TANGENT 
00797   
00798   // get the transformation matrix from each dof group & number of local dof
00799   // for original node.
00800   int numNode = numGroups;
00801   for (int a = 0; a<numNode; a++) {
00802     Matrix *theT = theDOFs[a]->getT();
00803     theTransformations[a] = theT;
00804     if (theT != 0)
00805       numDOFs[a] = theT->noRows(); // T^ 
00806     else
00807       numDOFs[a] = theDOFs[a]->getNumDOF();
00808   }
00809   
00810   // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j)
00811   // where blocks are of size equal to num ele dof at a node
00812   
00813   int startRow = 0;
00814   int noRowsTransformed = 0;
00815   int noRowsOriginal = 0;
00816   
00817   static Matrix localK;
00818   
00819   // foreach block row, for each block col do
00820   for (int i=0; i<numNode; i++) {
00821     
00822     int startCol = 0;
00823     int numDOFi = numDOFs[i];   
00824     int noColsOriginal = 0;
00825     
00826     for (int j=0; j<numNode; j++) {
00827       
00828       const Matrix *Ti = theTransformations[i];
00829       const Matrix *Tj = theTransformations[j];
00830       int numDOFj = numDOFs[j]; 
00831       localK.setData(localKbuffer, numDOFi, numDOFj);
00832       
00833       // copy K(i,j) into localK matrix
00834       // CHECK SIZE OF BUFFFER      
00835       for (int a=0; a<numDOFi; a++)
00836         for (int b=0; b<numDOFj; b++)
00837           localK(a,b) = theTangent(noRowsOriginal+a, noColsOriginal+b);
00838       
00839       // now perform the matrix computation T(i)^T localK T(j)
00840       // note: if T == 0 then the Identity is assumed
00841       int noColsTransformed = 0;
00842       static Matrix localTtKT;
00843       
00844       if (Ti != 0 && Tj != 0) {
00845         noRowsTransformed = Ti->noCols();
00846         noColsTransformed = Tj->noCols();
00847         // CHECK SIZE OF BUFFFER
00848         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00849         localTtKT = (*Ti) ^ localK * (*Tj);
00850       } else if (Ti == 0 && Tj != 0) {
00851         noRowsTransformed = numDOFi;
00852         noColsTransformed = Tj->noCols();
00853         // CHECK SIZE OF BUFFFER
00854         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00855         // localTtKT = localK * (*Tj);         
00856         localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0);
00857       } else if (Ti != 0 && Tj == 0) {
00858         noRowsTransformed = Ti->noCols();
00859         noColsTransformed = numDOFj;
00860         // CHECK SIZE OF BUFFFER
00861         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00862         localTtKT = (*Ti) ^ localK;
00863       } else {
00864         noRowsTransformed = numDOFi;
00865         noColsTransformed = numDOFj;
00866         localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed);
00867         localTtKT = localK;
00868       }
00869       // now copy into modTangent the T(i)^t K(i,j) T(j) product
00870       for (int c=0; c<noRowsTransformed; c++) 
00871         for (int d=0; d<noColsTransformed; d++) 
00872           (*modTangent)(startRow+c, startCol+d) = localTtKT(c,d);
00873       
00874       startCol += noColsTransformed;
00875       noColsOriginal += numDOFj;
00876     }
00877     
00878     noRowsOriginal += numDOFi;
00879     startRow += noRowsTransformed;
00880   }
00881   
00882   // get the components we need out of the vector
00883   // and place in a temporary vector
00884   Vector tmp(numTransformedDOF);
00885   for (int j=0; j<numTransformedDOF; j++) {
00886     int dof = (*modID)(j);
00887     if (dof >= 0)
00888       tmp(j) = accel(dof);
00889     else
00890       tmp(j) = 0.0;
00891   }
00892 
00893   modResidual->addMatrixVector(0.0, *modTangent, tmp, 1.0);
00894 
00895   return *modResidual;
00896 }
00897 
00898 
00899 void  
00900 TransformationFE::addD_Force(const Vector &disp,  double fact)
00901 {
00902     if (fact == 0.0)
00903         return;
00904 
00905     static Vector response;
00906     response.setData(dataBuffer, numOriginalDOF);
00907                     
00908     for (int i=0; i<numTransformedDOF; i++) {
00909         int loc = (*modID)(i);
00910         if (loc >= 0)
00911             (*modResidual)(i) = disp(loc);
00912         else
00913             (*modResidual)(i) = 0.0;
00914     }
00915     transformResponse(*modResidual, response);
00916     this->addLocalD_Force(response, fact);
00917 }        
00918 
00919 void  
00920 TransformationFE::addM_Force(const Vector &disp,  double fact)
00921 {
00922     if (fact == 0.0)
00923         return;
00924 
00925     static Vector response;
00926     response.setData(dataBuffer, numOriginalDOF);
00927                     
00928     for (int i=0; i<numTransformedDOF; i++) {
00929         int loc = (*modID)(i);
00930         if (loc >= 0)
00931             (*modResidual)(i) = disp(loc);
00932         else
00933             (*modResidual)(i) = 0.0;
00934     }
00935     transformResponse(*modResidual, response);
00936     this->addLocalM_Force(response, fact);
00937 }        
00938 
00939 
00940 
00941 // CHANGE THE ID SENT
00942 const Vector &
00943 TransformationFE::getLastResponse(void)
00944 {
00945     Integrator *theLastIntegrator = this->getLastIntegrator();
00946     if (theLastIntegrator != 0) {
00947         if (theLastIntegrator->getLastResponse(*modResidual,*modID) < 0) {
00948             opserr << "WARNING TransformationFE::getLastResponse(void)";
00949             opserr << " - the Integrator had problems with getLastResponse()\n";
00950         }
00951     }
00952     else {
00953         modResidual->Zero();
00954         opserr << "WARNING  TransformationFE::getLastResponse()";
00955         opserr << " No Integrator yet passed\n";
00956     }
00957     
00958     Vector &result = *modResidual;
00959     return result;
00960 }
00961 
00962 
00963 int 
00964 TransformationFE::transformResponse(const Vector &modResp, 
00965                                     Vector &unmodResp)
00966 {
00967     // perform T R  -- as T is block diagonal do T(i) R(i)
00968     // where blocks are of size equal to num ele dof at a node
00969 
00970     int startRowOriginal = 0;
00971     int startRowTransformed = 0;
00972     int numNode = numGroups;
00973     int noRows = 0;
00974     int noCols = 0;
00975 
00976     for (int i=0; i<numNode; i++) {
00977         const Matrix *Ti = theDOFs[i]->getT();
00978         if (Ti != 0) {
00979             noRows = Ti->noRows();
00980             noCols = Ti->noCols();
00981             for (int j=0; j<noRows; j++) {
00982                 double sum = 0.0;
00983                 for (int k=0; k<noCols; k++)
00984                     sum += (*Ti)(j,k) * modResp(startRowTransformed +k) ;
00985                 unmodResp(startRowOriginal + j) = sum;
00986             }
00987         } else {
00988             noCols = theDOFs[i]->getNumDOF();
00989             noRows = noCols;
00990             for (int j=0; j<noCols; j++)
00991                 unmodResp(startRowOriginal + j) = modResp(startRowTransformed +j);
00992         }
00993         startRowOriginal += noRows;
00994         startRowTransformed += noCols;
00995     }
00996 
00997     return 0;
00998 }
00999 
01000 
01001 // AddingSensitivity:BEGIN /////////////////////////////////
01002 void  
01003 TransformationFE::addD_ForceSensitivity(int gradNumber, const Vector &disp,  double fact)
01004 {
01005     if (fact == 0.0)
01006         return;
01007 
01008     static Vector response;
01009     response.setData(dataBuffer, numOriginalDOF);
01010                     
01011     for (int i=0; i<numTransformedDOF; i++) {
01012         int loc = (*modID)(i);
01013         if (loc >= 0)
01014             (*modResidual)(i) = disp(loc);
01015         else
01016             (*modResidual)(i) = 0.0;
01017     }
01018     transformResponse(*modResidual, response);
01019     this->addLocalD_ForceSensitivity(gradNumber, response, fact);
01020 }        
01021 
01022 void  
01023 TransformationFE::addM_ForceSensitivity(int gradNumber, const Vector &disp,  double fact)
01024 {
01025     if (fact == 0.0)
01026         return;
01027 
01028     static Vector response;
01029     response.setData(dataBuffer, numOriginalDOF);
01030                     
01031     for (int i=0; i<numTransformedDOF; i++) {
01032         int loc = (*modID)(i);
01033         if (loc >= 0)
01034             (*modResidual)(i) = disp(loc);
01035         else
01036             (*modResidual)(i) = 0.0;
01037     }
01038     transformResponse(*modResidual, response);
01039     this->addLocalM_ForceSensitivity(gradNumber, response, fact);
01040 }        
01041 
01042 // AddingSensitivity:END ////////////////////////////////////

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