00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
00064
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
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
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
00102
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
00118
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
00137 numTransFE++;
00138 }
00139
00140
00141
00142
00143
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
00163 if (modTangent != 0) delete modTangent;
00164 if (modResidual != 0) delete modResidual;
00165 }
00166
00167
00168
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
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
00216 if (transCounter == 0) {
00217 transCounter++;
00218 theHandler->doneDOFids();
00219 } else if (transCounter == numTransFE)
00220 transCounter = 0;
00221 else
00222 transCounter++;
00223
00224
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
00232
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
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
00258 if (numDOF <= MAX_NUM_DOF) {
00259
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
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
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
00308
00309
00310 int numNode = numGroups;
00311 for (int a = 0; a<numNode; a++)
00312 theTransformations[a] = theDOFs[a]->getT();
00313
00314
00315
00316 int startRow = 0;
00317
00318 Matrix *localK = new Matrix(localKbuffer, numEleNodalDOF, numEleNodalDOF);
00319
00320
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
00331
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
00337
00338 int noCols = 0;
00339 Matrix *localTtKT;
00340
00341 if (Ti != 0 && Tj != 0) {
00342 noRows = Ti->noCols();
00343 noCols = Tj->noCols();
00344
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
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
00357 localTtKT = new Matrix(dataBuffer, noRows, noCols);
00358 *localTtKT = (*Ti)^(*localK);
00359 } else {
00360 noRows = numEleNodalDOF;
00361 noCols = numEleNodalDOF;
00362 localTtKT = localK;
00363 }
00364
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
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
00397
00398
00399
00400
00401 int startRow = 0;
00402 int numNode = numGroups;
00403
00404
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
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
00634
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 }