00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012 #include <stdlib.h>
00013 #include <FluidSolidPorousMaterial.h>
00014 #include <Information.h>
00015 #include <MaterialResponse.h>
00016 #include <ID.h>
00017 #include <FEM_ObjectBroker.h>
00018
00019 int* FluidSolidPorousMaterial::loadStagex = 0;
00020 int* FluidSolidPorousMaterial::ndmx = 0;
00021 double* FluidSolidPorousMaterial::combinedBulkModulusx = 0;
00022 int FluidSolidPorousMaterial::matCount = 0;
00023 double FluidSolidPorousMaterial::pAtm = 101;
00024
00025 Vector FluidSolidPorousMaterial::workV3(3);
00026 Vector FluidSolidPorousMaterial::workV6(6);
00027 Matrix FluidSolidPorousMaterial::workM3(3,3);
00028 Matrix FluidSolidPorousMaterial::workM6(6,6);
00029
00030 FluidSolidPorousMaterial::FluidSolidPorousMaterial (int tag, int nd, NDMaterial &soilMat,
00031 double combinedBulkModul, double atm)
00032 : NDMaterial(tag, ND_TAG_FluidSolidPorousMaterial)
00033 {
00034 if (combinedBulkModul < 0) {
00035 opserr << "WARNING:FluidSolidPorousMaterial::FluidSolidPorousMaterial: combinedBulkModulus < 0" << endln;
00036 opserr << "Will reset to 0." <<endln;
00037 combinedBulkModul = 0.;
00038 }
00039
00040 if (matCount%20 == 0) {
00041 int * temp1 = loadStagex;
00042 int * temp2 = ndmx;
00043 double * temp3 = combinedBulkModulusx;
00044 loadStagex = new int[matCount+20];
00045 ndmx = new int[matCount+20];
00046 combinedBulkModulusx = new double[matCount+20];
00047 for (int i=0; i<matCount; i++) {
00048 loadStagex[i] = temp1[i];
00049 ndmx[i] = temp2[i];
00050 combinedBulkModulusx[i] = temp3[i];
00051 }
00052 if (matCount > 0) {
00053 delete [] temp1; delete [] temp2; delete [] temp3;
00054 }
00055 }
00056
00057 ndmx[matCount] = nd;
00058 loadStagex[matCount] = 0;
00059 combinedBulkModulusx[matCount] = combinedBulkModul;
00060 matN = matCount;
00061 matCount ++;
00062 pAtm = atm;
00063
00064 theSoilMaterial = soilMat.getCopy();
00065 trialExcessPressure = currentExcessPressure = 0.;
00066 trialVolumeStrain = currentVolumeStrain = 0.;
00067 initMaxPress = 0.;
00068 e2p = 0;
00069 }
00070
00071
00072 FluidSolidPorousMaterial::FluidSolidPorousMaterial ()
00073 : NDMaterial(0,ND_TAG_FluidSolidPorousMaterial), theSoilMaterial(0)
00074 {
00075 trialExcessPressure = currentExcessPressure = 0.;
00076 trialVolumeStrain = currentVolumeStrain = 0.;
00077 initMaxPress = 0.;
00078 e2p = 0;
00079 }
00080
00081
00082 FluidSolidPorousMaterial::FluidSolidPorousMaterial (const FluidSolidPorousMaterial & a)
00083 : NDMaterial(a.getTag(),ND_TAG_FluidSolidPorousMaterial)
00084 {
00085 matN = a.matN;
00086 theSoilMaterial = a.theSoilMaterial->getCopy();
00087 trialExcessPressure = a.trialExcessPressure;
00088 currentExcessPressure = a.currentExcessPressure;
00089 trialVolumeStrain = a.trialVolumeStrain;
00090 currentVolumeStrain = a.currentVolumeStrain;
00091 initMaxPress = a.initMaxPress;
00092 e2p = a.e2p;
00093 }
00094
00095
00096 FluidSolidPorousMaterial::~FluidSolidPorousMaterial ()
00097 {
00098 if (theSoilMaterial != 0)
00099 delete theSoilMaterial;
00100 }
00101
00102
00103 int FluidSolidPorousMaterial::setTrialStrain (const Vector &strain)
00104 {
00105 int ndm = ndmx[matN];
00106
00107 if (ndm==2 && strain.Size()==3)
00108 trialVolumeStrain = strain[0]+strain[1];
00109 else if (ndm==3 && strain.Size()==6)
00110 trialVolumeStrain = strain[0]+strain[1]+strain[2];
00111 else {
00112 opserr << "Fatal:FluidSolidPorousMaterial:: Material dimension is: " << ndm << endln;
00113 opserr << "But strain vector size is: " << strain.Size() << endln;
00114 exit(-1);;
00115 }
00116
00117 return theSoilMaterial->setTrialStrain(strain);
00118 }
00119
00120
00121 int FluidSolidPorousMaterial::setTrialStrain (const Vector &strain, const Vector &rate)
00122 {
00123 int ndm = ndmx[matN];
00124
00125 if (ndm==2 && strain.Size()==3)
00126 trialVolumeStrain = strain[0]+strain[1];
00127 else if (ndm==3 && strain.Size()==6)
00128 trialVolumeStrain = strain[0]+strain[1]+strain[2];
00129 else {
00130 opserr << "Fatal:FluidSolidPorousMaterial:: Material dimension is: " << ndm << endln;
00131 opserr << "But strain vector size is: " << strain.Size() << endln;
00132 exit(-1);;
00133 }
00134
00135 return theSoilMaterial->setTrialStrain(strain, rate);
00136 }
00137
00138
00139 int FluidSolidPorousMaterial::setTrialStrainIncr (const Vector &strain)
00140 {
00141 int ndm = ndmx[matN];
00142
00143 if (ndm==2 && strain.Size()==3)
00144 trialVolumeStrain = currentVolumeStrain + strain[0]+strain[1];
00145 else if (ndm==3 && strain.Size()==6)
00146 trialVolumeStrain = currentVolumeStrain + strain[0]+strain[1]+strain[2];
00147 else {
00148 opserr << "Fatal:FluidSolidPorousMaterial:: Material dimension is: " << ndm << endln;
00149 opserr << "But strain vector size is: " << strain.Size() << endln;
00150 exit(-1);;
00151 }
00152
00153 return theSoilMaterial->setTrialStrainIncr(strain);
00154 }
00155
00156
00157 int FluidSolidPorousMaterial::setTrialStrainIncr (const Vector &strain, const Vector &rate)
00158 {
00159 int ndm = ndmx[matN];
00160
00161 if (ndm==2 && strain.Size()==3)
00162 trialVolumeStrain = currentVolumeStrain + strain[0]+strain[1];
00163 else if (ndm==3 && strain.Size()==6)
00164 trialVolumeStrain = currentVolumeStrain + strain[0]+strain[1]+strain[2];
00165 else {
00166 opserr << "Fatal:FluidSolidPorousMaterial:: Material dimension is: " << ndm << endln;
00167 opserr << "But strain vector size is: " << strain.Size() << endln;
00168 exit(-1);;
00169 }
00170
00171 return theSoilMaterial->setTrialStrainIncr(strain, rate);
00172 }
00173
00174
00175 const Matrix & FluidSolidPorousMaterial::getTangent (void)
00176 {
00177 int ndm = ndmx[matN];
00178 int loadStage = loadStagex[matN];
00179 double combinedBulkModulus = combinedBulkModulusx[matN];
00180
00181 Matrix *workM = (ndm == 2) ? &workM3 : &workM6;
00182
00183 *workM = theSoilMaterial->getTangent();
00184
00185 if (loadStage != 0) {
00186 for (int i=0; i<ndm; i++)
00187 for (int j=0; j<ndm; j++)
00188 (*workM)(i,j) = (*workM)(i,j) + combinedBulkModulus;
00189 }
00190
00191 return *workM;
00192 }
00193
00194 const Matrix & FluidSolidPorousMaterial::getInitialTangent (void)
00195 {
00196 int ndm = ndmx[matN];
00197
00198 Matrix *workM = (ndm == 2) ? &workM3 : &workM6;
00199
00200 *workM = theSoilMaterial->getInitialTangent();
00201
00202 return *workM;
00203 }
00204
00205 double FluidSolidPorousMaterial::getRho(void)
00206 {
00207 return theSoilMaterial->getRho();
00208 }
00209
00210 const Vector & FluidSolidPorousMaterial::getStress (void)
00211 {
00212 int ndm = ndmx[matN];
00213 int loadStage = loadStagex[matN];
00214 double combinedBulkModulus = combinedBulkModulusx[matN];
00215
00216 Vector *workV = (ndm == 2) ? &workV3 : &workV6;
00217
00218 *workV = theSoilMaterial->getStress();
00219
00220 if (loadStage != 0) {
00221 if (e2p==0) {
00222 e2p = 1;
00223 initMaxPress = ((*workV)[0] < (*workV)[1]) ? (*workV)[0] : (*workV)[1];
00224 if (ndm == 3)
00225 initMaxPress = (initMaxPress < (*workV)[2]) ? initMaxPress : (*workV)[2];
00226 }
00227 trialExcessPressure = currentExcessPressure;
00228 trialExcessPressure +=
00229 (trialVolumeStrain - currentVolumeStrain) * combinedBulkModulus;
00230 if (trialExcessPressure > pAtm-initMaxPress)
00231 trialExcessPressure = pAtm-initMaxPress;
00232
00233
00234 for (int i=0; i<ndm; i++)
00235 (*workV)[i] += trialExcessPressure;
00236 }
00237
00238 return *workV;
00239 }
00240
00241
00242 int FluidSolidPorousMaterial::updateParameter(int responseID, Information &info)
00243 {
00244 if (responseID<10)
00245 loadStagex[matN] = responseID;
00246 else {
00247 if (responseID==11) combinedBulkModulusx[matN]=info.theDouble;
00248 }
00249
00250 return 0;
00251 }
00252
00253
00254 const Vector & FluidSolidPorousMaterial::getCommittedStress (void)
00255 {
00256 return theSoilMaterial->getCommittedStress();
00257 }
00258
00259
00260 const Vector & FluidSolidPorousMaterial::getCommittedStrain (void)
00261 {
00262 return theSoilMaterial->getCommittedStrain();
00263 }
00264
00265
00266 const Vector & FluidSolidPorousMaterial::getCommittedPressure (void)
00267 {
00268 int ndm = ndmx[matN];
00269
00270 static Vector temp(2);
00271
00272 temp[0] = currentExcessPressure;
00273 temp[1] = temp[0]/initMaxPress;
00274
00275 return temp;
00276 }
00277
00278
00279 const Vector & FluidSolidPorousMaterial::getStrain (void)
00280 {
00281 return theSoilMaterial->getStrain();
00282 }
00283
00284
00285 int FluidSolidPorousMaterial::commitState (void)
00286 {
00287 int loadStage = loadStagex[matN];
00288
00289 currentVolumeStrain = trialVolumeStrain;
00290 if (loadStage != 0)
00291 currentExcessPressure = trialExcessPressure;
00292 else
00293 currentExcessPressure = 0.;
00294
00295 return theSoilMaterial->commitState();
00296 }
00297
00298
00299 int FluidSolidPorousMaterial::revertToLastCommit (void)
00300 {
00301 return theSoilMaterial->revertToLastCommit();
00302 }
00303
00304 int FluidSolidPorousMaterial::revertToStart (void)
00305 {
00306 return theSoilMaterial->revertToStart();
00307 }
00308
00309 NDMaterial * FluidSolidPorousMaterial::getCopy (void)
00310 {
00311 FluidSolidPorousMaterial * copy = new FluidSolidPorousMaterial(*this);
00312 return copy;
00313 }
00314
00315
00316 NDMaterial * FluidSolidPorousMaterial::getCopy (const char *code)
00317 {
00318 if (strcmp(code,"FluidSolidPorous") == 0 || strcmp(code,"PlaneStrain") == 0 ||
00319 strcmp(code,"ThreeDimensional") == 0) {
00320 FluidSolidPorousMaterial * copy = new FluidSolidPorousMaterial(*this);
00321 return copy;
00322 }
00323
00324 return 0;
00325 }
00326
00327
00328 const char * FluidSolidPorousMaterial::getType (void) const
00329 {
00330 int ndm = ndmx[matN];
00331
00332 return (ndm == 2) ? "PlaneStrain" : "ThreeDimensional";
00333 }
00334
00335
00336 int FluidSolidPorousMaterial::getOrder (void) const
00337 {
00338 int ndm = ndmx[matN];
00339
00340 return (ndm == 2) ? 3 : 6;
00341 }
00342
00343
00344 int FluidSolidPorousMaterial::sendSelf(int commitTag, Channel &theChannel)
00345 {
00346 int ndm = ndmx[matN];
00347 int loadStage = loadStagex[matN];
00348 double combinedBulkModulus = combinedBulkModulusx[matN];
00349
00350 int res = 0;
00351
00352 static Vector data(7);
00353 data(0) = this->getTag();
00354 data(1) = ndm;
00355 data(2) = loadStage;
00356 data(3) = combinedBulkModulus;
00357 data(4) = currentExcessPressure;
00358 data(5) = currentVolumeStrain;
00359 data(6) = matN;
00360
00361 res += theChannel.sendVector(this->getDbTag(), commitTag, data);
00362 if (res < 0) {
00363 opserr << "FluidSolidPorousMaterial::sendSelf -- could not send Vector\n";
00364
00365 return res;
00366 }
00367
00368 ID classTags(2);
00369
00370 classTags(0) = theSoilMaterial->getClassTag();
00371 int matDbTag = theSoilMaterial->getDbTag();
00372
00373
00374 if (matDbTag == 0) {
00375 matDbTag = theChannel.getDbTag();
00376 if (matDbTag != 0)
00377 theSoilMaterial->setDbTag(matDbTag);
00378 }
00379 classTags(1) = matDbTag;
00380
00381 res += theChannel.sendID(this->getDbTag(), commitTag, classTags);
00382 if (res < 0) {
00383 opserr << "WARNING FluidSolidPorousMaterial::sendSelf() - " << this->getTag() << " failed to send ID\n";
00384
00385 return res;
00386 }
00387
00388
00389 res += theSoilMaterial->sendSelf(commitTag, theChannel);
00390 if (res < 0) {
00391 opserr << "WARNING FluidSolidPorousMaterial::sendSelf() - " << this->getTag() << " failed to send its Material\n";
00392 return res;
00393 }
00394
00395 return res;
00396 }
00397
00398
00399
00400
00401 int FluidSolidPorousMaterial::recvSelf(int commitTag, Channel &theChannel,
00402 FEM_ObjectBroker &theBroker)
00403 {
00404 int res = 0;
00405
00406 static Vector data(7);
00407
00408 res += theChannel.recvVector(this->getDbTag(), commitTag, data);
00409 if (res < 0) {
00410 opserr << "FluidSolidPorousMaterial::recvSelf -- could not receive Vector\n";
00411 return res;
00412 }
00413
00414 this->setTag((int)data(0));
00415 int ndm = data(1);
00416 int loadStage = data(2);
00417 double combinedBulkModulus = data(3);
00418 currentExcessPressure = data(4);
00419 currentVolumeStrain = data(5);
00420 matN = data(6);
00421
00422 ndmx[matN] = ndm;
00423 loadStagex[matN] = loadStage;
00424 combinedBulkModulusx[matN] = combinedBulkModulus;
00425
00426
00427 ID classTags(2);
00428
00429 res += theChannel.recvID(this->getDbTag(), commitTag, classTags);
00430 if (res < 0) {
00431 opserr << "FluidSolidPorousMaterial::recvSelf() - failed to recv ID data\n";
00432 return res;
00433 }
00434
00435 int matClassTag = classTags(0);
00436 int matDbTag = classTags(1);
00437
00438
00439 if (theSoilMaterial == 0 || theSoilMaterial->getClassTag() != matClassTag) {
00440 if (theSoilMaterial != 0)
00441 delete theSoilMaterial;
00442 theSoilMaterial = theBroker.getNewNDMaterial(matClassTag);
00443 if (theSoilMaterial == 0) {
00444 opserr << "FluidSolidPorousMaterial::recvSelf() - " <<
00445 "Broker could not create NDMaterial of class type" << matClassTag << endln;
00446 exit(-1);
00447 }
00448 }
00449
00450
00451 theSoilMaterial->setDbTag(matDbTag);
00452 res += theSoilMaterial->recvSelf(commitTag, theChannel, theBroker);
00453 if (res < 0) {
00454 opserr << "FluidSolidPorousMaterial::recvSelf() - material failed to recv itself\n";
00455 return res;
00456 }
00457
00458 return res;
00459 }
00460
00461
00462 Response*
00463 FluidSolidPorousMaterial::setResponse (const char **argv, int argc, Information &matInfo, OPS_Stream &output)
00464 {
00465 if (strcmp(argv[0],"stress") == 0 || strcmp(argv[0],"stresses") == 0)
00466 return new MaterialResponse(this, 1, this->getCommittedStress());
00467
00468 else if (strcmp(argv[0],"strain") == 0 || strcmp(argv[0],"strains") == 0)
00469 return new MaterialResponse(this, 2, this->getCommittedStrain());
00470
00471 else if (strcmp(argv[0],"tangent") == 0)
00472 return new MaterialResponse(this, 3, this->getTangent());
00473
00474 else if (strcmp(argv[0],"backbone") == 0)
00475 return theSoilMaterial->setResponse(argv, argc, matInfo, output);
00476
00477 else if (strcmp(argv[0],"pressure") == 0)
00478 return new MaterialResponse(this, 5, this->getCommittedPressure());
00479
00480 else
00481 return 0;
00482 }
00483
00484
00485 int FluidSolidPorousMaterial::getResponse (int responseID, Information &matInfo)
00486 {
00487 switch (responseID) {
00488 case 1:
00489 return matInfo.setVector(this->getCommittedStress());
00490
00491 case 2:
00492 return matInfo.setVector(this->getCommittedStrain());
00493
00494 case 3:
00495 return matInfo.setMatrix(this->getTangent());
00496
00497 case 4:
00498 return theSoilMaterial->getResponse(responseID, matInfo);
00499
00500 case 5:
00501 return matInfo.setVector(this->getCommittedPressure());
00502
00503 default:
00504 return -1;
00505 }
00506 }
00507
00508
00509 void FluidSolidPorousMaterial::Print(OPS_Stream &s, int flag )
00510 {
00511 s << "FluidSolidPorousMaterial" << endln;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527