TzLiq1.cpp

Go to the documentation of this file.
00001 /* *********************************************************************
00002 **    Module:   TzLiq1.cpp 
00003 **
00004 **    Purpose:  Provide a t-z material that gets pore pressure from a
00005 **                              specified element that contains a PorousFluidSolid.
00006 **
00007 **    Developed by Ross W. Boulanger
00008 **    (C) Copyright 2002, All Rights Reserved.
00009 **
00010 ** ****************************************************************** */
00011 
00012 // $Revision: 1.0
00013 // $Date: 2002/2/5
00014 // $Source: /OpenSees/SRC/material/uniaxial/TzLiq1.cpp
00015 
00016 // Written: RWB
00017 // Created: Feb 2002
00018 // Revision: A
00019 //
00020 // Description: This file contains the class implementation for TzLiq1
00021 
00022 #include <TzLiq1.h>
00023 #include <NDMaterial.h>
00024 #include <Vector.h>
00025 #include <Channel.h>
00026 #include <math.h>
00027 
00028 // Controls on internal iteration between spring components
00029 const int TZmaxIterations = 20;
00030 const double TZtolerance = 1.0e-12;
00031 
00032 int TzLiq1::loadStage = 0;
00033 Vector TzLiq1::stressV3(3);
00034 
00036 //      Constructor with data
00037 
00038 TzLiq1::TzLiq1(int tag, int classtag, int tz_type, double t_ult, double z_50,
00039                 double dash_pot, int solid_elem1, int solid_elem2, Domain *the_Domain)
00040 :TzSimple1(tag, classtag, tz_type, t_ult, z_50, dash_pot),
00041 solidElem1(solid_elem1), solidElem2(solid_elem2), theDomain(the_Domain)
00042 {
00043         // Initialize TzSimple variables and history variables
00044         //
00045         this->revertToStart();
00046     initialTangent = Tangent;
00047 }
00048 
00050 //      Default constructor
00051 
00052 TzLiq1::TzLiq1()
00053 :TzSimple1(), solidElem1(0), solidElem2(0), theDomain(0)
00054 {
00055 }
00057 //      Default destructor
00058 TzLiq1::~TzLiq1()
00059 {
00060   // Call TzSimple1 destructor even though it does nothing.
00061   //
00062   // TzSimple1::~TzSimple1();
00063 }
00064 
00066 int 
00067 TzLiq1::setTrialStrain (double newz, double zRate)
00068 {
00069         // Call the base class TzSimple1 to take care of the basic t-z behavior.
00070         //
00071         TzSimple1::setTrialStrain(newz, zRate);
00072         Tz = newz;
00073 
00074         // Reset mean consolidation stress if loadStage switched from 0 to 1
00075         //              Note: currently assuming y-axis is vertical, and that the
00076         //              out-of-plane normal stress equals sigma-xx.
00077         //
00078         if(lastLoadStage ==0 && loadStage ==1){
00079 
00080                 meanConsolStress = getEffectiveStress();
00081                 if(meanConsolStress == 0.0){
00082                         opserr << "WARNING meanConsolStress is 0 in solid elements, ru will divide by zero";
00083                         opserr << "TzLiq1: " << endln;
00084                         opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00085                         exit(-1);
00086                 }
00087         }
00088         lastLoadStage = loadStage;
00089 
00090         // Obtain the mean effective stress from the adjacent solid elements,
00091         //    and calculate ru for scaling of t-z base relation.
00092         //
00093         if(loadStage == 1) {
00094                 double meanStress = getEffectiveStress();
00095                 Tru = 1.0 - meanStress/meanConsolStress;
00096                 if(Tru > 0.999) Tru = 0.999;
00097         }
00098         else {
00099                 Tru = 0.0;
00100         }
00101 
00102         // Call the base class TzSimple1 to get basic t-z response,
00103         //
00104         double baseT = TzSimple1::getStress();
00105         double baseTangent = TzSimple1::getTangent();
00106 
00107         // Check: Only update Hru if not yet converged (avoiding small changes in Tru).
00108         //
00109         if(Tz !=Cz || Tt !=Ct) Hru = Tru;
00110 
00111         // During dilation of the soil (ru dropping), provide a stiff transition
00112         //   between the old and new scaled t-z relations. This avoids illogical
00113         //   hardening of the t-z relation (i.e., negative stiffnesses).
00114         //
00115         if (Tru < Cru){
00116 
00117                 maxTangent = (TzSimple1::tult/TzSimple1::z50)*(1.0-Cru);
00118 
00119                 //  If unloading, follow the old scaled t-z relation until t=0.
00120                 //
00121                 if(Cz>0.0 && Tz<Cz && baseT>0.0){
00122                         Hru = Cru;
00123                 }
00124                 if(Cz<0.0 && Tz>Cz && baseT<0.0){
00125                         Hru = Cru;
00126                 }
00127                 
00128                 //  If above the stiff transition line (between Tru & Cru scaled surfaces)
00129                 //
00130                 double zref = Cz + baseT*(Cru-Tru)/maxTangent;
00131                 if(Cz>0.0 && Tz>Cz && Tz<zref){
00132                         Hru = 1.0 - (Ct + (Tz-Cz)*maxTangent)/baseT;
00133                 }
00134                 if(Cz<0.0 && Tz<Cz && Tz>zref){
00135                         Hru = 1.0 - (Ct + (Tz-Cz)*maxTangent)/baseT;
00136                 }
00137         }
00138 
00139         //  Now set the tangent and Tt values accordingly
00140         //
00141 
00142         Tt = baseT*(1.0-Hru);
00143         if(Hru==Cru || Hru==Tru){
00144                 Tangent = (1.0-Hru)*baseTangent;
00145         }
00146         else {
00147                 Tangent = maxTangent;
00148         }
00149 
00150         return 0;
00151 }
00153 double 
00154 TzLiq1::getStress(void)
00155 {
00156         double dashForce = getStrainRate()*this->getDampTangent();
00157 
00158         // Limit the combined force to tult*(1-ru).
00159         //
00160         double tmax = (1.0-TZtolerance)*TzSimple1::tult*(1.0-Hru);
00161         if(fabs(Tt + dashForce) >= tmax)
00162                 return tmax*(Tt+dashForce)/fabs(Tt+dashForce);
00163         else return Tt + dashForce;
00164 
00165 }
00167 double 
00168 TzLiq1::getTangent(void)
00169 {
00170         return this->Tangent;
00171 
00172 }
00174 double 
00175 TzLiq1::getInitialTangent(void)
00176 {
00177     return this->initialTangent;
00178 }
00180 double 
00181 TzLiq1::getDampTangent(void)
00182 {
00183         // Call the base class TzSimple1 to get basic t-z response,
00184         //    and then scale by (1-ru).
00185         //
00186         double dampTangent = TzSimple1::getDampTangent();
00187         return dampTangent*(1.0-Hru);
00188 }
00190 double 
00191 TzLiq1::getStrain(void)
00192 {
00193         double strain = TzSimple1::getStrain();
00194     return strain;
00195 }
00197 double 
00198 TzLiq1::getStrainRate(void)
00199 {
00200     double strainrate = TzSimple1::getStrainRate();
00201         return strainrate;
00202 }
00204 int 
00205 TzLiq1::commitState(void)
00206 {
00207         // Call the TzSimple1 base function to take care of details.
00208         //
00209         TzSimple1::commitState();
00210         Cz = Tz;
00211         Ct = Tt;
00212         Cru= Hru;
00213         
00214     return 0;
00215 }
00216 
00218 int 
00219 TzLiq1::revertToLastCommit(void)
00220 {
00221         // reset to committed values
00222     //
00223         TzSimple1::revertToLastCommit();
00224         Tz = Cz;
00225         Tt = Ct;
00226         Hru= Cru;
00227 
00228         return 0;
00229 }
00230 
00232 int 
00233 TzLiq1::revertToStart(void)
00234 {
00235         // Call the TzSimple1 base function to take care of most details.
00236         //
00237         TzSimple1::revertToStart();
00238         Tz = 0.0;
00239         Tt = 0.0;
00240         maxTangent = (TzSimple1::tult/TzSimple1::z50);
00241 
00242         // Excess pore pressure ratio and pointers
00243         //
00244         Tru = 0.0;
00245         Hru = 0.0;
00246         meanConsolStress = -TzSimple1::tult;
00247         lastLoadStage = 0;
00248         loadStage = 0;
00249         elemFlag.assign("NONE");
00250 
00251         // Now get all the committed variables initiated
00252         //
00253         commitState();
00254 
00255     return 0;
00256 }
00257 
00259 double 
00260 TzLiq1::getEffectiveStress(void)
00261 {
00262         // Default value for meanStress
00263         double meanStress = meanConsolStress;
00264         
00265         // if the elemFlag has not been set yet, then set it
00266         //
00267         if(elemFlag.compare("NONE") == 0) {     //string.compare returns zero if equal
00268 
00269                 // if theDomain pointer is nonzero, then set pointers to attached soil elements.
00270                 //
00271                 if(theDomain != 0)
00272                 {       
00273                         Element *theElement1 = theDomain->getElement(solidElem1);
00274                         Element *theElement2 = theDomain->getElement(solidElem2);
00275                         if (theElement1 == 0 || theElement2 == 0) {
00276                                 opserr << "WARNING solid element not found in getEffectiveStress" << endln;
00277                                 opserr << "TzLiq1: " << endln;
00278                                 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00279                                 exit(-1);
00280                         }
00281 
00282                         // Check each of the allowable element types, starting with 4NodeQuads
00283                         theQuad1 = dynamic_cast<FourNodeQuad*>(theElement1);
00284                         theQuad2 = dynamic_cast<FourNodeQuad*>(theElement2);
00285                         if(theQuad1 != 0 && theQuad2 != 0) {
00286                                 elemFlag.assign("4NodeQuad");
00287                         }
00288 
00289                         // Check on each other type of allowable element types, only if no successful yet.
00290                         if(elemFlag.compare("NONE") == 0) {     //string.compare returns zero if equal
00291 
00292                                 // try other elements like, 4NodeQuadUP
00293                                 elemFlag.assign("NONE");
00294                         }
00295                         
00296                         // Check on acceptable soil materials
00297                         //
00298                         if(elemFlag.compare("4NodeQuad") == 0) {
00299                                 NDMaterial *theNDM1[4];
00300                                 NDMaterial *theNDM2[4];
00301                                 FluidSolidPorousMaterial *theFSPM1[4];
00302                                 FluidSolidPorousMaterial *theFSPM2[4];
00303                                 int dummy = 0;
00304                                 for (int i=0; i<4; i++) {
00305                                         theNDM1[i] = theQuad1->theMaterial[i];
00306                                         theNDM2[i] = theQuad2->theMaterial[i];
00307                                         theFSPM1[i] = dynamic_cast<FluidSolidPorousMaterial*>(theNDM1[i]);
00308                                         theFSPM2[i] = dynamic_cast<FluidSolidPorousMaterial*>(theNDM2[i]);
00309                                         if(theFSPM1 == 0 || theFSPM2 == 0) dummy = dummy + 1;
00310                                 }
00311                                 if(dummy == 0) elemFlag.append("-FSPM");
00312 
00313                                 // Check other acceptable soil types.
00314                         }
00315 
00316                         if(elemFlag.compare("NONE") == 0) {     // Never obtained a valid pointer set
00317                                 opserr << "WARNING: Adjoining solid elements did not return valid pointers";
00318                                 opserr << "TzLiq1: " << endln;
00319                                 opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00320                                 exit(-1);
00321                                 return meanStress;
00322                         }
00323         
00324                 }
00325         }
00326         
00327         // Get effective stresses using appropriate pointers in elemFlag not "NONE"
00328         //
00329         if(elemFlag.compare("NONE") != 0) {
00330 
00331                 if(elemFlag.compare("4NodeQuad-FSPM") == 0) {
00332                         meanStress = 0.0;
00333                         Vector *theStressVector = &stressV3;
00334                         double excessPorePressure = 0.0;
00335                         NDMaterial *theNDM;
00336                         FluidSolidPorousMaterial *theFSPM;
00337 
00338                         for(int i=0; i < 4; i++) { 
00339                                 *theStressVector = theQuad1->theMaterial[i]->getStress();
00340                                 meanStress += 2.0*(*theStressVector)[0] + (*theStressVector)[1];
00341                                 *theStressVector = theQuad2->theMaterial[i]->getStress();
00342                                 meanStress += 2.0*(*theStressVector)[0] + (*theStressVector)[1];
00343 
00344                                 theNDM = theQuad1->theMaterial[i];
00345                                 theFSPM= dynamic_cast<FluidSolidPorousMaterial*>(theNDM);
00346                                 excessPorePressure += (theFSPM->trialExcessPressure);
00347                                 theNDM = theQuad2->theMaterial[i];
00348                                 theFSPM= dynamic_cast<FluidSolidPorousMaterial*>(theNDM);
00349                                 excessPorePressure += (theFSPM->trialExcessPressure);
00350                         }
00351                         meanStress = meanStress/(2.0*4.0*3.0);
00352                         excessPorePressure = excessPorePressure/(2.0*4.0);
00353                         meanStress = meanStress - excessPorePressure;
00354 
00355                         return meanStress;
00356                 }
00357 
00358                 else if(elemFlag.compare("4NodeQuadUP-FSPM") == 0) {
00359                         
00360                         // expect to later have UP option on quads
00361 
00362                         return meanStress;
00363                 }
00364                 
00365                 else {  // Never found a matching flag
00366                         opserr << "WARNING: Something wrong with specification of elemFlag in getEffectiveStress";
00367                         opserr << "TzLiq1: " << endln;
00368                         opserr << "Adjacent solidElems: " << solidElem1 << ", " << solidElem2 << endln;
00369                         exit(-1);
00370                         return meanStress;
00371                 }
00372         }
00373 
00374         return meanStress;
00375 }
00376 
00378 int 
00379 TzLiq1::updateParameter(int snum,Information &eleInformation)
00380 {
00381         // TclUpdateMaterialStageCommand will call this routine with the
00382         // command:
00383         //
00384         //      updateMaterialStage - material tag -stage snum
00385         //
00386         // If snum = 0; running linear elastic for soil elements,
00387         //              so excess pore pressure should be zero.
00388         // If snum = 1; running plastic soil element behavior,
00389         //              so this marks the end of the "consol" gravity loading.
00390 
00391         if(snum !=0 && snum !=1){
00392                 opserr << "WARNING updateMaterialStage for TzLiq1 material must be 0 or 1";
00393                 opserr << endln;
00394                 exit(-1);
00395         }
00396         loadStage = snum;
00397 
00398         return 0;
00399 }
00400 
00402 UniaxialMaterial *
00403 TzLiq1::getCopy(void)
00404 {
00405         // Make a new instance of this class and then assign it "this" to make a copy.
00406         //
00407         TzLiq1 *clone;                  // pointer to a TzLiq1 class
00408         clone = new TzLiq1();   // pointer gets a new instance of TzLiq1
00409         *clone = *this;                 // the clone (dereferenced pointer) = dereferenced this.
00410         
00411         return clone;
00412 }
00413 
00415 int 
00416 TzLiq1::sendSelf(int cTag, Channel &theChannel)
00417 {
00418         // I'm following an example by Frank here.
00419         //
00420         int res =0;
00421 
00422         static Vector data(16);
00423 
00424         TzSimple1::sendSelf(cTag, theChannel);
00425 
00426         data(0)  = this->getTag();
00427         data(1)  = Tz;
00428         data(2)  = Cz;
00429         data(3)  = Tt;
00430         data(4)  = Ct;
00431         data(5)  = Tangent;
00432         data(6)  = maxTangent;
00433         data(7)  = Tru;
00434         data(8)  = Cru;
00435         data(9)  = Hru;
00436         data(10) = solidElem1;
00437         data(11) = solidElem2;
00438         data(12) = meanConsolStress;
00439         data(13) = loadStage;
00440         data(14) = lastLoadStage;
00441         data(15) = initialTangent;
00442         
00443   res = theChannel.sendVector(this->getDbTag(), cTag, data);
00444   if (res < 0) 
00445     opserr << "TzLiq1::sendSelf() - failed to send data\n";
00446 
00447   return res;
00448 }
00449 
00451 int 
00452 TzLiq1::recvSelf(int cTag, Channel &theChannel, 
00453                                FEM_ObjectBroker &theBroker)
00454 {
00455   int res = 0;
00456 
00457   static Vector data(16);
00458   res = theChannel.recvVector(this->getDbTag(), cTag, data);
00459   
00460   if (res < 0) {
00461       opserr << "TzLiq1::recvSelf() - failed to receive data\n";
00462       this->setTag(0);      
00463   }
00464   else {
00465     this->setTag((int)data(0));
00466 
00467         TzSimple1::recvSelf(cTag, theChannel, theBroker);
00468 
00469         Tz    = data(1);
00470         Cz    = data(2);
00471         Tt    = data(3);
00472         Ct    = data(4);
00473         Tangent    = data(5);
00474         maxTangent =data(6);
00475         Tru        = data(7);
00476         Cru        = data(8);
00477         Hru        = data(9);
00478         solidElem1        = (int)data(10);
00479         solidElem2        = (int)data(11);
00480         meanConsolStress  = data(12);
00481         loadStage         = (int)data(13);
00482         lastLoadStage     = (int)data(14);
00483         initialTangent    = data(15);
00484 
00485         // set the trial quantities
00486         this->revertToLastCommit();
00487   }
00488 
00489   return res;
00490 }
00491 
00493 void 
00494 TzLiq1::Print(OPS_Stream &s, int flag)
00495 {
00496     s << "TzLiq1, tag: " << this->getTag() << endln;
00497     s << "  tzType: " << tzType << endln;
00498     s << "  tult: " << tult << endln;
00499     s << "  z50: " << z50 << endln;
00500         s << "  dashpot: " << dashpot << endln;
00501         s << "  solidElem1: " << solidElem1 << endln;
00502         s << "  solidElem2: " << solidElem2 << endln;
00503 }
00504 

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