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 #include <SeriesMaterial.h>
00035 #include <ID.h>
00036 #include <Vector.h>
00037 #include <Channel.h>
00038 #include <FEM_ObjectBroker.h>
00039 #include <stdlib.h>
00040 #include <MaterialResponse.h>
00041
00042 #include <OPS_Globals.h>
00043
00044 SeriesMaterial::SeriesMaterial(int tag, int num,
00045 UniaxialMaterial ** theMaterialModels,
00046 int maxIter, double tol)
00047 :UniaxialMaterial(tag,MAT_TAG_SeriesMaterial),
00048 Tstrain(0.0), Cstrain(0.0), Tstress(0.0), Cstress(0.0),
00049 Ttangent(0.0), Ctangent(0.0),
00050 maxIterations(maxIter), tolerance(tol),
00051 stress(0), flex(0), strain(0), initialFlag(false),
00052 numMaterials(num), theModels(0)
00053 {
00054 theModels = new UniaxialMaterial *[numMaterials];
00055
00056 if (theModels == 0) {
00057 opserr << "SeriesMaterial::SeriesMaterial -- failed to allocate material array\n";
00058 exit(-1);
00059 }
00060
00061
00062 int i;
00063 for (i = 0; i < numMaterials; i++) {
00064 theModels[i] = theMaterialModels[i]->getCopy();
00065 if (theModels[i] == 0) {
00066 opserr << "SeriesMaterial::SeriesMaterial -- failed to get copy of material: " << i << endln;
00067 exit(-1);
00068 }
00069 }
00070
00071 strain = new double [numMaterials];
00072 if (strain == 0) {
00073 opserr << "SeriesMaterial::SeriesMaterial -- failed to allocate strain array\n";
00074 exit(-1);
00075 }
00076
00077 stress = new double [numMaterials];
00078 if (stress == 0) {
00079 opserr << "SeriesMaterial::SeriesMaterial -- failed to allocate stress array\n";
00080 exit(-1);
00081 }
00082
00083 flex = new double [numMaterials];
00084 if (flex == 0) {
00085 opserr << "SeriesMaterial::SeriesMaterial -- failed to allocate flex array\n";
00086 exit(-1);
00087 }
00088
00089 for (i = 0; i < numMaterials; i++) {
00090 strain[i] = 0.0;
00091 stress[i] = 0.0;
00092 flex[i] = 0.0;
00093 }
00094 }
00095
00096 SeriesMaterial::SeriesMaterial()
00097 :UniaxialMaterial(0,MAT_TAG_SeriesMaterial),
00098 Tstrain(0.0), Cstrain(0.0), Tstress(0.0), Cstress(0.0),
00099 Ttangent(0.0), Ctangent(0.0),
00100 maxIterations(0), tolerance(0.0),
00101 stress(0), flex(0), strain(0), initialFlag(false),
00102 numMaterials(0), theModels(0)
00103 {
00104
00105 }
00106
00107 SeriesMaterial::~SeriesMaterial()
00108 {
00109 for (int i = 0; i < numMaterials; i++)
00110 delete theModels[i];
00111
00112 if (theModels != 0)
00113 delete [] theModels;
00114
00115 if (strain)
00116 delete [] strain;
00117
00118 if (stress)
00119 delete [] stress;
00120
00121 if (flex)
00122 delete [] flex;
00123
00124 }
00125
00126 int
00127 SeriesMaterial::setTrialStrain(double newStrain, double strainRate)
00128 {
00129
00130 double dv = newStrain-Tstrain;
00131
00132 Tstrain = newStrain;
00133
00134
00135 double dq = Ttangent*dv;
00136
00137
00138 Tstress += dq;
00139
00140 for (int j = 0; j < maxIterations; j++) {
00141
00142
00143 double f = 0.0;
00144 double vr = 0.0;
00145
00146 for (int i = 0; i < numMaterials; i++) {
00147
00148
00149 double ds = Tstress - stress[i];
00150
00151
00152 double de = flex[i]*ds;
00153
00154 if (initialFlag == true)
00155 strain[i] += de;
00156
00157
00158 theModels[i]->setTrialStrain(strain[i]);
00159
00160
00161 stress[i] = theModels[i]->getStress();
00162
00163
00164 flex[i] = theModels[i]->getTangent();
00165 if (fabs(flex[i]) > 1.0e-12)
00166 flex[i] = 1.0/flex[i];
00167 else
00168 flex[i] = (flex[i] < 0.0) ? -1.0e12 : 1.0e12;
00169
00170
00171 ds = Tstress - stress[i];
00172
00173
00174 de = flex[i]*ds;
00175
00176
00177 f += flex[i];
00178
00179
00180 vr += strain[i] + de;
00181 }
00182
00183
00184 if (fabs(f) > 1.0e-12)
00185 Ttangent = 1.0/f;
00186 else
00187 Ttangent = (f < 0.0) ? -1.0e12 : 1.0e12;
00188
00189
00190 dv = Tstrain - vr;
00191
00192
00193 dq = Ttangent*dv;
00194
00195 if (fabs(dq*dv) < tolerance)
00196 break;
00197 }
00198
00199
00200 Tstress += dq;
00201
00202 initialFlag = true;
00203
00204 return 0;
00205 }
00206
00207 double
00208 SeriesMaterial::getStrain(void)
00209 {
00210 return Tstrain;
00211 }
00212
00213 double
00214 SeriesMaterial::getStress(void)
00215 {
00216 return Tstress;
00217 }
00218
00219 double
00220 SeriesMaterial::getTangent(void)
00221 {
00222 return Ttangent;
00223 }
00224
00225
00226 double
00227 SeriesMaterial::getInitialTangent(void)
00228 {
00229 double kf = 0.0;
00230 double k = 0.0;
00231
00232 if (numMaterials != 0)
00233 kf = theModels[0]->getInitialTangent();
00234
00235 for (int i=1; i<numMaterials; i++) {
00236
00237 k = theModels[i]->getInitialTangent();
00238 if ((kf + k) != 0.0)
00239 kf = kf*k/(kf+k);
00240 else
00241 return 0.0;
00242 }
00243
00244 return kf;
00245 }
00246
00247
00248 int
00249 SeriesMaterial::commitState(void)
00250 {
00251 int err = 0;
00252
00253 Cstrain = Tstrain;
00254 Cstress = Tstress;
00255 Ctangent = Ttangent;
00256
00257 for (int i = 0; i < numMaterials; i++)
00258 err += theModels[i]->commitState();
00259
00260
00261
00262
00263
00264 return err;
00265 }
00266
00267 int
00268 SeriesMaterial::revertToLastCommit(void)
00269 {
00270 int err = 0;
00271
00272 Tstrain = Cstrain;
00273 Tstress = Cstress;
00274 Ttangent = Ctangent;
00275
00276 for (int i = 0; i < numMaterials; i++) {
00277 err += theModels[i]->revertToLastCommit();
00278
00279 strain[i] = theModels[i]->getStrain();
00280 stress[i] = theModels[i]->getStress();
00281 flex[i] = theModels[i]->getTangent();
00282
00283 if (fabs(flex[i]) > 1.0e-12)
00284 flex[i] = 1.0/flex[i];
00285 else
00286 flex[i] = (flex[i] < 0.0) ? -1.0e12 : 1.0e12;
00287 }
00288
00289 initialFlag = false;
00290
00291 return err;
00292 }
00293
00294
00295 int
00296 SeriesMaterial::revertToStart(void)
00297 {
00298 int err = 0;
00299
00300 Cstrain = 0.0;
00301 Cstress = 0.0;
00302 Ctangent = 0.0;
00303
00304 for (int i = 0; i < numMaterials; i++) {
00305 err += theModels[i]->revertToLastCommit();
00306
00307 strain[i] = 0.0;
00308 stress[i] = 0.0;
00309 flex[i] = 0.0;
00310 }
00311
00312 return err;
00313 }
00314
00315
00316
00317 UniaxialMaterial *
00318 SeriesMaterial::getCopy(void)
00319 {
00320 SeriesMaterial *theCopy = new
00321 SeriesMaterial(this->getTag(), numMaterials, theModels,
00322 maxIterations, tolerance);
00323
00324 theCopy->Cstrain = Cstrain;
00325 theCopy->Cstress = Cstress;
00326 theCopy->Ctangent = Ctangent;
00327 theCopy->initialFlag = initialFlag;
00328
00329 for (int i = 0; i < numMaterials; i++) {
00330 theCopy->strain[i] = strain[i];
00331 theCopy->stress[i] = stress[i];
00332 theCopy->flex[i] = flex[i];
00333 }
00334
00335 return theCopy;
00336 }
00337
00338
00339 int
00340 SeriesMaterial::sendSelf(int cTag, Channel &theChannel)
00341 {
00342 int res = 0;
00343
00344 int dataTag = this->getDbTag();
00345
00346 static Vector data(5);
00347
00348 data(0) = this->getTag();
00349 data(1) = numMaterials;
00350 data(2) = (initialFlag) ? 1.0 : 0.0;
00351 data(3) = maxIterations;
00352 data(4) = tolerance;
00353
00354 res = theChannel.sendVector(dataTag, cTag, data);
00355 if (res < 0) {
00356 opserr << "SeriesMaterial::sendSelf -- failed to send data Vector\n";
00357 return res;
00358 }
00359
00360 ID classTags(2*numMaterials);
00361
00362 int i;
00363 for (i = 0; i < numMaterials; i++) {
00364 classTags(i) = theModels[i]->getClassTag();
00365
00366 int dbTag = theModels[i]->getDbTag();
00367 if (dbTag == 0) {
00368 dbTag = theChannel.getDbTag();
00369 if (dbTag != 0)
00370 theModels[i]->setDbTag(dbTag);
00371 }
00372
00373 classTags(i+numMaterials) = dbTag;
00374 }
00375
00376 res = theChannel.sendID(dataTag, cTag, classTags);
00377 if (res < 0) {
00378 opserr << "SeriesMaterial::sendSelf -- failed to send classTags ID\n";
00379 return res;
00380 }
00381
00382 for (i = 0; i < numMaterials; i++) {
00383 res = theModels[i]->sendSelf(cTag, theChannel);
00384 if (res < 0) {
00385 opserr << "SeriesMaterial::sendSelf -- failed to send UniaxialMaterial: " << i << endln;
00386 return res;
00387 }
00388 }
00389
00390 return res;
00391 }
00392
00393 int
00394 SeriesMaterial::recvSelf(int cTag, Channel &theChannel,
00395 FEM_ObjectBroker &theBroker)
00396 {
00397 int res = 0;
00398
00399 int dataTag = this->getDbTag();
00400
00401 static Vector data(5);
00402
00403 res = theChannel.recvVector(dataTag, cTag, data);
00404 if (res < 0) {
00405 opserr << "SeriesMaterial::recvSelf -- failed to receive data Vector\n";
00406 return res;
00407 }
00408
00409 this->setTag((int)data(0));
00410 initialFlag = (data(2) == 1.0) ? true : false;
00411 maxIterations = (int)data(3);
00412 tolerance = data(4);
00413
00414
00415 int i;
00416 if (numMaterials != (int)data(1)) {
00417
00418
00419 if (theModels != 0) {
00420 for (i = 0; i < numMaterials; i++)
00421 if (theModels[i] != 0)
00422 delete theModels[i];
00423 delete [] theModels;
00424 }
00425
00426 if (strain != 0)
00427 delete [] strain;
00428
00429 if (stress != 0)
00430 delete [] stress;
00431
00432 if (flex != 0)
00433 delete [] flex;
00434
00435
00436 numMaterials = (int)data(1);
00437 theModels = new UniaxialMaterial *[numMaterials];
00438 if (theModels == 0) {
00439 opserr << "SeriesMaterial::recvSelf -- failed to allocate UniaxialMaterial array\n";
00440 return -1;
00441 }
00442
00443 for (i = 0; i < numMaterials; i++)
00444 theModels[i] = 0;
00445
00446 strain = new double [numMaterials];
00447 if (strain == 0) {
00448 opserr << "SeriesMaterial::recvSelf -- failed to allocate strain array\n";
00449 return -1;
00450 }
00451
00452 stress = new double [numMaterials];
00453 if (stress == 0) {
00454 opserr << "SeriesMaterial::recvSelf -- failed to allocate stress array\n";
00455 return -1;
00456 }
00457
00458 flex = new double [numMaterials];
00459 if (flex== 0) {
00460 opserr << "SeriesMaterial::recvSelf -- failed to allocate flex array\n";
00461 return -1;
00462 }
00463 }
00464
00465 ID classTags(2*numMaterials);
00466 res = theChannel.recvID(dataTag, cTag, classTags);
00467 if (res < 0) {
00468 opserr << "SeriesMaterial::recvSelf -- failed to receive classTags ID\n";
00469 return res;
00470 }
00471
00472 for (i = 0; i < numMaterials; i++) {
00473 int matClassTag = classTags(i);
00474
00475 if (theModels[i] == 0)
00476 theModels[i] = theBroker.getNewUniaxialMaterial(matClassTag);
00477
00478 else if (theModels[i]->getClassTag() != matClassTag) {
00479 delete theModels[i];
00480 theModels[i] = theBroker.getNewUniaxialMaterial(matClassTag);
00481 }
00482
00483 if (theModels[i] == 0) {
00484 opserr << "SeriesMaterial::recvSelf -- failed to get a newUniaxialMaterial\n";
00485 return -1;
00486 }
00487
00488 theModels[i]->setDbTag(classTags(i+numMaterials));
00489 res = theModels[i]->recvSelf(cTag, theChannel, theBroker);
00490 if (res < 0) {
00491 opserr << "SeriesMaterial::recvSelf -- failed to receive UniaxialMaterial: " << i << endln;
00492 return res;
00493 }
00494 }
00495
00496 return res;
00497 }
00498
00499 void
00500 SeriesMaterial::Print(OPS_Stream &s, int flag)
00501 {
00502 s << "\nSeriesMaterial, tag: " << this->getTag() << endln;
00503 s << "\tUniaxial Componenets" << endln;
00504 for (int i = 0; i < numMaterials; i++)
00505 s << "\t\tUniaxial Material, tag: " << theModels[i]->getTag() << endln;
00506 }
00507
00508 Response*
00509 SeriesMaterial::setResponse(const char **argv, int argc, Information &info, OPS_Stream &theOutput)
00510 {
00511
00512 Response *theResponse = 0;
00513
00514 theOutput.tag("UniaxialMaterialOutput");
00515 theOutput.attr("matType", this->getClassType());
00516 theOutput.attr("matTag", this->getTag());
00517
00518
00519 if (strcmp(argv[0],"stress") == 0) {
00520 theOutput.tag("ResponseType", "sigma11");
00521 theResponse = new MaterialResponse(this, 1, this->getStress());
00522 }
00523
00524 else if (strcmp(argv[0],"tangent") == 0) {
00525 theOutput.tag("ResponseType", "C11");
00526 theResponse = new MaterialResponse(this, 2, this->getTangent());
00527 }
00528
00529
00530 else if (strcmp(argv[0],"strain") == 0) {
00531 theOutput.tag("ResponseType", "eps11");
00532 theResponse = new MaterialResponse(this, 3, this->getStrain());
00533 }
00534
00535
00536 else if ((strcmp(argv[0],"stressStrain") == 0) ||
00537 (strcmp(argv[0],"stressANDstrain") == 0)) {
00538 theOutput.tag("ResponseType", "sig11");
00539 theOutput.tag("ResponseType", "eps11");
00540 theResponse = new MaterialResponse(this, 4, Vector(2));
00541 }
00542
00543 else if (strcmp(argv[0],"strains") == 0) {
00544 for (int i=0; i<numMaterials; i++) {
00545 theOutput.tag("UniaxialMaterialOutput");
00546 theOutput.attr("matType", this->getClassType());
00547 theOutput.attr("matTag", this->getTag());
00548 theOutput.tag("ResponseType", "eps11");
00549 theOutput.endTag();
00550 }
00551
00552 theResponse = new MaterialResponse(this, 100, Vector(numMaterials));
00553 }
00554 else if (strcmp(argv[0],"material") == 0 ||
00555 strcmp(argv[0],"component") == 0) {
00556 if (argc > 1) {
00557 int matNum = atoi(argv[1]) - 1;
00558 if (matNum >= 0 && matNum < numMaterials)
00559 theResponse = theModels[matNum]->setResponse(&argv[2], argc-2, info, theOutput);
00560 }
00561 }
00562
00563 theOutput.endTag();
00564 return theResponse;
00565 }
00566
00567 int
00568 SeriesMaterial::getResponse(int responseID, Information &info)
00569 {
00570 Vector strains(strain, numMaterials);
00571
00572 switch (responseID) {
00573 case 100:
00574 return info.setVector(strains);
00575
00576 default:
00577 return this->UniaxialMaterial::getResponse(responseID, info);
00578 }
00579 }