SeriesMaterial.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.8 $
00022 // $Date: 2006/08/04 18:17:04 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/material/uniaxial/SeriesMaterial.cpp,v $
00024 
00025 // Written: MHS
00026 // Created: Sept 2000
00027 //
00028 // Description: This file contains the class definition for 
00029 // SeriesModel. SeriesModel is an aggregation
00030 // of UniaxialMaterial objects all considered acting in Series.
00031 // Uses the same state determination as the beam elements.
00032 // b = [1 1 ... 1]^
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         // Using the incremental iterative strain
00130         double dv = newStrain-Tstrain;
00131 
00132         Tstrain = newStrain;
00133 
00134         // Stress increment using tangent at last iteration
00135         double dq = Ttangent*dv;
00136 
00137         // Update stress 
00138         Tstress += dq;
00139 
00140         for (int j = 0; j < maxIterations; j++) {
00141 
00142                 // Set to zero for integration
00143                 double f = 0.0;
00144                 double vr = 0.0;
00145 
00146                 for (int i = 0; i < numMaterials; i++) {
00147 
00148                         // Stress unbalance in material i
00149                         double ds = Tstress - stress[i];
00150 
00151                         // Strain increment
00152                         double de = flex[i]*ds;
00153 
00154                         if (initialFlag == true)
00155                                 strain[i] += de;
00156 
00157                         // Update material i
00158                         theModels[i]->setTrialStrain(strain[i]);
00159 
00160                         // Get updated stress from material i
00161                         stress[i] = theModels[i]->getStress();
00162 
00163                         // Get updated flexibility from material i
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                         // Stress unbalance in material i
00171                         ds = Tstress - stress[i];
00172 
00173                         // Residual strain in material i
00174                         de = flex[i]*ds;
00175 
00176                         // Integrate flexibility ...
00177                         f += flex[i];
00178 
00179                         // ... and integrate residual strain
00180                         vr += strain[i] + de;
00181                 }
00182 
00183                 // Updated series tangent
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                 // Residual deformation
00190                 dv = Tstrain - vr;
00191 
00192                 // Stress increment
00193                 dq = Ttangent*dv;
00194 
00195                 if (fabs(dq*dv) < tolerance)
00196                         break;
00197         }
00198 
00199         // Updated stress
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         // Commented out for the same reason it was taken
00261         // out of the NLBeamColumn commitState() -- MHS
00262         //initialFlag = false;
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   // if number of materials != new number we must alolocate space for data
00415   int i;
00416   if (numMaterials != (int)data(1)) {
00417     
00418     // free up old memory if allocated
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     // allocate new memory for data
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   // stress
00519   if (strcmp(argv[0],"stress") == 0) {
00520     theOutput.tag("ResponseType", "sigma11");
00521     theResponse =  new MaterialResponse(this, 1, this->getStress());
00522   }  
00523   // tangent
00524   else if (strcmp(argv[0],"tangent") == 0) {
00525     theOutput.tag("ResponseType", "C11");
00526     theResponse =  new MaterialResponse(this, 2, this->getTangent());
00527   }
00528 
00529   // strain
00530   else if (strcmp(argv[0],"strain") == 0) {
00531     theOutput.tag("ResponseType", "eps11");
00532     theResponse =  new MaterialResponse(this, 3, this->getStrain());
00533   }
00534 
00535   // strain
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 }

Generated on Mon Oct 23 15:05:22 2006 for OpenSees by doxygen 1.5.0