Subversion Repositories OpenSees

Rev

Rev 1321 | Rev 1350 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* ****************************************************************** **
**    OpenSees - Open System for Earthquake Engineering Simulation    **
**          Pacific Earthquake Engineering Research Center            **
**                                                                    **
**                                                                    **
** (C) Copyright 1999, The Regents of the University of California    **
** All Rights Reserved.                                               **
**                                                                    **
** Commercial use of this program without express permission of the   **
** University of California, Berkeley, is strictly prohibited.  See   **
** file 'COPYRIGHT'  in main directory for information on usage and   **
** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
**                                                                    **
** Developed by:                                                      **
**   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
**   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
**   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
**                                                                    **
** ****************************************************************** */

                                                                       
// $Revision: 1.10 $
// $Date: 2003-03-04 00:48:17 $
// $Source: /usr/local/cvs/OpenSees/SRC/material/uniaxial/Steel01.cpp,v $
                                                                       
                                                                       
// File: ~/material/Steel01.C
//
// Written: MHS
// Created: 06/99
// Revision: A
//
// Description: This file contains the class implementation for
// Steel01.
//
// What: "@(#) Steel01.C, revA"


#include <Steel01.h>
#include <Vector.h>
#include <Matrix.h>
#include <Channel.h>
#include <Information.h>
#include <math.h>
#include <float.h>

Steel01::Steel01
(int tag, double FY, double E, double B,
 double A1, double A2, double A3, double A4,
 double min, double max) :
   UniaxialMaterial(tag,MAT_TAG_Steel01),
   fy(FY), E0(E), b(B), a1(A1), a2(A2), a3(A3), a4(A4),
   epsmin(min), epsmax(max)
{
   // Calculated material parameters
   epsy = fy/E0;         // Yield strain
   Esh = b*E0;           // Hardening modulus

   // Sets all history and state variables to initial values
   // History variables
   CminStrain = 0.0;
   CmaxStrain = 0.0;
   CshiftP = 1.0;
   CshiftN = 1.0;
   Cloading = 0;
   Cfailed = 0;

   TminStrain = 0.0;
   TmaxStrain = 0.0;
   TshiftP = 1.0;
   TshiftN = 1.0;
   Tloading = 0;
   Tfailed = 0;

   // State variables
   Cstrain = 0.0;
   Cstress = 0.0;
   Ctangent = E0;

   Tstrain = 0.0;
   Tstress = 0.0;
   Ttangent = E0;

// AddingSensitivity:BEGIN /////////////////////////////////////
        parameterID = 0;
        SHVs = 0;
// AddingSensitivity:END //////////////////////////////////////
}

Steel01::Steel01():UniaxialMaterial(0,MAT_TAG_Steel01),
 fy(0.0), E0(0.0), b(0.0), a1(0.0), a2(0.0), a3(0.0), a4(0.0),
 epsmin(0.0), epsmax(0.0)
{

// AddingSensitivity:BEGIN /////////////////////////////////////
        parameterID = 0;
        SHVs = 0;
// AddingSensitivity:END //////////////////////////////////////

}

Steel01::~Steel01 ()
{
// AddingSensitivity:BEGIN /////////////////////////////////////
        if (SHVs != 0)
                delete SHVs;
// AddingSensitivity:END //////////////////////////////////////
}

int Steel01::setTrialStrain (double strain, double strainRate)
{
   // Reset history variables to last converged state
   TminStrain = CminStrain;
   TmaxStrain = CmaxStrain;
   TshiftP = CshiftP;
   TshiftN = CshiftN;
   Tloading = Cloading;
   Tfailed = Cfailed;

   // Set trial strain
   Tstrain = strain;

   // Determine change in strain from last converged state
   double dStrain = Tstrain - Cstrain;

   // Calculate the trial state given the trial strain
   //   if (fabs(dStrain) > DBL_EPSILON)  
      determineTrialState (dStrain);

   return 0;
}

int Steel01::setTrial (double strain, double &stress, double &tangent, double strainRate)
{
   // Reset history variables to last converged state
   TminStrain = CminStrain;
   TmaxStrain = CmaxStrain;
   TshiftP = CshiftP;
   TshiftN = CshiftN;
   Tloading = Cloading;
   Tfailed = Cfailed;

   // Set trial strain
   Tstrain = strain;

   // Determine change in strain from last converged state
   double dStrain;
   dStrain = Tstrain - Cstrain;

   // Calculate the trial state given the trial strain
   // if (fabs(dStrain) > DBL_EPSILON)
      determineTrialState (dStrain);

   stress = Tstress;
   tangent = Ttangent;

   return 0;
}

void Steel01::determineTrialState (double dStrain)
{

   if (Tstrain <= epsmin || Tstrain >= epsmax)
      Tfailed = 1;

   if (Tfailed) {
      Tstress = 0.0;
      Ttangent = 0.0;
      return;
   } else {

      double c, c1, c2, c3, fyOneMinusB, c1c3, c1c2;

      fyOneMinusB = fy * (1.0 - b);

      c1 = Esh*Tstrain;

      c2 = TshiftN*fyOneMinusB;

      c3 = TshiftP*fyOneMinusB;

      c1c3 = c1+c3;

      c = Cstress + E0*dStrain;



                if (c1c3 < c) {
                        Tstress = c1c3;
                        state = 2; // positive yielding
                }
                else {
                        Tstress = c;
                        state = 1; // elastic
                }

                c1c2=c1-c2;
                if (c1c2 > Tstress) {
                        Tstress = c1c2;
                        state = 3; // negative yielding
                }








      if (fabs(Tstress-c) < DBL_EPSILON)
          Ttangent = E0;
      else
          Ttangent = Esh;      
     
      //
      // Determine if a load reversal has occurred due to the trial strain
      //

      // Determine initial loading condition
      if (Tloading == 0 && dStrain != 0.0) {
          if (dStrain > 0.0)
            Tloading = 1;
          else
            Tloading = -1;
      }

      // Transition from loading to unloading, i.e. positive strain increment
      // to negative strain increment
      if (Tloading == 1 && dStrain < 0.0) {
          Tloading = -1;
          if (Cstrain > TmaxStrain)
            TmaxStrain = Cstrain;
          TshiftN = 1 + a1*pow((TmaxStrain-TminStrain)/(2.0*a2*epsy),0.8);
      }

      // Transition from unloading to loading, i.e. negative strain increment
      // to positive strain increment
      if (Tloading == -1 && dStrain > 0.0) {
          Tloading = 1;
          if (Cstrain < TminStrain)
            TminStrain = Cstrain;
          TshiftP = 1 + a3*pow((TmaxStrain-TminStrain)/(2.0*a4*epsy),0.8);
      }
   }
}

void Steel01::detectLoadReversal (double dStrain)
{
   // Determine initial loading condition
   if (Tloading == 0 && dStrain != 0.0)
   {
      if (dStrain > 0.0)
         Tloading = 1;
      else
         Tloading = -1;
   }

   // Transition from loading to unloading, i.e. positive strain increment
   // to negative strain increment
   if (Tloading == 1 && dStrain < 0.0)
   {
      Tloading = -1;
      if (Cstrain > TmaxStrain)
         TmaxStrain = Cstrain;
      TshiftN = 1 + a1*pow((TmaxStrain-TminStrain)/(2.0*a2*epsy),0.8);
   }

   // Transition from unloading to loading, i.e. negative strain increment
   // to positive strain increment
   if (Tloading == -1 && dStrain > 0.0)
   {
      Tloading = 1;
      if (Cstrain < TminStrain)
         TminStrain = Cstrain;
      TshiftP = 1 + a3*pow((TmaxStrain-TminStrain)/(2.0*a4*epsy),0.8);
   }
}

double Steel01::getStrain ()
{
   return Tstrain;
}

double Steel01::getStress ()
{
   return Tstress;
}

double Steel01::getTangent ()
{
   return Ttangent;
}

double Steel01::getRho()
{
   return 0.0;
}

int Steel01::commitState ()
{
   // History variables
   CminStrain = TminStrain;
   CmaxStrain = TmaxStrain;
   CshiftP = TshiftP;
   CshiftN = TshiftN;
   Cloading = Tloading;
   Cfailed = Tfailed;

   // State variables
   Cstrain = Tstrain;
   Cstress = Tstress;
   Ctangent = Ttangent;

   return 0;
}

int Steel01::revertToLastCommit ()
{
   // Reset trial history variables to last committed state
   TminStrain = CminStrain;
   TmaxStrain = CmaxStrain;
   TshiftP = CshiftP;
   TshiftN = CshiftN;
   Tloading = Cloading;
   Tfailed = Cfailed;

   // Reset trial state variables to last committed state
   Tstrain = Cstrain;
   Tstress = Cstress;
   Ttangent = Ctangent;

   return 0;
}

int Steel01::revertToStart ()
{
   // History variables
   CminStrain = 0.0;
   CmaxStrain = 0.0;
   CshiftP = 1.0;
   CshiftN = 1.0;
   Cloading = 0;
   Cfailed = 0;

   TminStrain = 0.0;
   TmaxStrain = 0.0;
   TshiftP = 1.0;
   TshiftN = 1.0;
   Tloading = 0;
   Tfailed = 0;

   // State variables
   Cstrain = 0.0;
   Cstress = 0.0;
   Ctangent = E0;

   Tstrain = 0.0;
   Tstress = 0.0;
   Ttangent = E0;

// AddingSensitivity:BEGIN /////////////////////////////////
        if (SHVs != 0)
                SHVs->Zero();
// AddingSensitivity:END //////////////////////////////////

   return 0;
}

UniaxialMaterial* Steel01::getCopy ()
{
   Steel01* theCopy = new Steel01(this->getTag(), fy, E0, b,
                                  a1, a2, a3, a4, epsmin, epsmax);

   // Calculated material properties
   theCopy->epsy = epsy;
   theCopy->Esh = Esh;

   // Converged history variables
   theCopy->CminStrain = CminStrain;
   theCopy->CmaxStrain = CmaxStrain;
   theCopy->CshiftP = CshiftP;
   theCopy->CshiftN = CshiftN;
   theCopy->Cloading = Cloading;
   theCopy->Cfailed = Cfailed;

   // Trial history variables
   theCopy->TminStrain = CminStrain;
   theCopy->TmaxStrain = CmaxStrain;
   theCopy->TshiftP = CshiftP;
   theCopy->TshiftN = CshiftN;
   theCopy->Tloading = Cloading;
   theCopy->Tfailed = Cfailed;

   // Converged state variables
   theCopy->Cstrain = Cstrain;
   theCopy->Cstress = Cstress;
   theCopy->Ctangent = Ctangent;

   // Trial state variables
   theCopy->Tstrain = Tstrain;
   theCopy->Tstress = Tstress;
   theCopy->Ttangent = Ttangent;

   return theCopy;
}

int Steel01::sendSelf (int commitTag, Channel& theChannel)
{
   int res = 0;
   static Vector data(19);
   data(0) = this->getTag();

   // Material properties
   data(1) = fy;
   data(2) = E0;
   data(3) = b;
   data(4) = a1;
   data(5) = a2;
   data(6) = a3;
   data(7) = a4;
   data(8) = epsmin;
   data(9) = epsmax;

   // History variables from last converged state
   data(10) = CminStrain;
   data(11) = CmaxStrain;
   data(12) = CshiftP;
   data(13) = CshiftN;
   data(14) = Cloading;
   data(15) = Cfailed;

   // State variables from last converged state
   data(16) = Cstrain;
   data(17) = Cstress;
   data(18) = Ctangent;

   // Data is only sent after convergence, so no trial variables
   // need to be sent through data vector

   res = theChannel.sendVector(this->getDbTag(), commitTag, data);
   if (res < 0)
      opserr << "Steel01::sendSelf() - failed to send data\n";

   return res;
}

int Steel01::recvSelf (int commitTag, Channel& theChannel,
                                FEM_ObjectBroker& theBroker)
{
   int res = 0;
   static Vector data(19);
   res = theChannel.recvVector(this->getDbTag(), commitTag, data);
 
   if (res < 0) {
      opserr << "Steel01::recvSelf() - failed to receive data\n";
      this->setTag(0);      
   }
   else {
      this->setTag(int(data(0)));

      // Material properties
      fy = data(1);
      E0 = data(2);
      b = data(3);
      a1 = data(4);
      a2 = data(5);
      a3 = data(6);
      a4 = data(7);
      epsmin = data(8);
      epsmax = data(9);

      epsy = fy/E0;
      Esh = b*E0;

      // History variables from last converged state
      CminStrain = data(10);
      CmaxStrain = data(11);
      CshiftP = data(12);
      CshiftN = data(13);
      Cloading = int(data(14));
      Cfailed = int(data(15));

      // Copy converged history values into trial values since data is only
      // sent (received) after convergence
      TminStrain = CminStrain;
      TmaxStrain = CmaxStrain;
      TshiftP = CshiftP;
      TshiftN = CshiftN;
      Tloading = Cloading;
      Tfailed = Cfailed;

      // State variables from last converged state
      Cstrain = data(16);
      Cstress = data(17);
      Ctangent = data(18);      

      // Copy converged state values into trial values
      Tstrain = Cstrain;
      Tstress = Cstress;
      Ttangent = Ctangent;
   }
   
   return res;
}

void Steel01::Print (OPS_Stream& s, int flag)
{
   s << "Steel01 tag: " << this->getTag() << endln;
   s << "  fy: " << fy << " ";
   s << "  E0: " << E0 << " ";
   s << "  b:  " << b << " ";
   s << "  a1: " << a1 << " ";
   s << "  a2: " << a2 << " ";
   s << "  a3: " << a3 << " ";
   s << "  a4: " << a4 << " ";
   if (epsmin != NEG_INF_STRAIN)
     s << "  epsmin: " << epsmin << " ";
   if (epsmax != POS_INF_STRAIN)
     s << "  epsmax: " << epsmax << endln;
}




// AddingSensitivity:BEGIN ///////////////////////////////////
int
Steel01::setParameter(const char **argv, int argc, Information &info)
{
        if (argc < 1)
                return -1;

        if (strcmp(argv[0],"sigmaY") == 0) {
                info.theType = DoubleType;
                return 1;
        }
        if (strcmp(argv[0],"E") == 0) {
                info.theType = DoubleType;
                return 2;
        }
        if (strcmp(argv[0],"b") == 0) {
                info.theType = DoubleType;
                return 3;
        }
        if (strcmp(argv[0],"a1") == 0) {
                info.theType = DoubleType;
                return 4;
        }
        if (strcmp(argv[0],"a2") == 0) {
                info.theType = DoubleType;
                return 5;
        }
        if (strcmp(argv[0],"a3") == 0) {
                info.theType = DoubleType;
                return 6;
        }
        if (strcmp(argv[0],"a4") == 0) {
                info.theType = DoubleType;
                return 7;
        }
        if (strcmp(argv[0],"epsmin") == 0) {
                info.theType = DoubleType;
                return 8;
        }
        if (strcmp(argv[0],"epsmax") == 0) {
                info.theType = DoubleType;
                return 9;
        }
        else
                opserr << "WARNING: Could not set parameter in Steel01. " << endln;
               
        return -1;
}



int
Steel01::updateParameter(int parameterID, Information &info)
{
        switch (parameterID) {
        case -1:
                return -1;
        case 1:
                this->fy = info.theDouble;
                break;
        case 2:
                this->E0 = info.theDouble;
                break;
        case 3:
                this->b = info.theDouble;
                break;
        case 4:
                this->a1 = info.theDouble;
                break;
        case 5:
                this->a2 = info.theDouble;
                break;
        case 6:
                this->a3 = info.theDouble;
                break;
        case 7:
                this->a4 = info.theDouble;
                break;
        case 8:
                this->epsmin = info.theDouble;
                break;
        case 9:
                this->epsmax = info.theDouble;
                break;
        default:
                return -1;
        }

        epsy = fy/E0;           // Yield strain
        Esh = b*E0;             // Hardening modulus
        Ttangent = E0;          // Initial stiffness

        return 0;
}




int
Steel01::activateParameter(int passedParameterID)
{
        parameterID = passedParameterID;

        return 0;
}



double
Steel01::getStrainSensitivity(int gradNumber)
{
        return 0.0;
}

double
Steel01::getStressSensitivity(int gradNumber, bool conditional)
{
        // Initialize return value
        double gradient = 0.0;


        // Pick up sensitivity history variables
        double CstrainSensitivity = 0.0;
        double CstressSensitivity = 0.0;
        if (SHVs != 0) {
                CstrainSensitivity = (*SHVs)(0,(gradNumber-1));
                CstressSensitivity = (*SHVs)(1,(gradNumber-1));
        }


        // Assign values to parameter derivatives (depending on what's random)
        double fySensitivity = 0.0;
        double E0Sensitivity = 0.0;
        double bSensitivity = 0.0;
        if (parameterID == 1) {
                fySensitivity = 1.0;
        }
        else if (parameterID == 2) {
                E0Sensitivity = 1.0;
        }
        else if (parameterID == 3) {
                bSensitivity = 1.0;
        }


        // Compute min and max stress
        double Tstress;
        double dStrain = Tstrain-Cstrain;
        double sigmaElastic = Cstress + E0*dStrain;
        double fyOneMinusB = fy * (1.0 - b);
        double c1 = Esh*Tstrain;
        double c2 = TshiftN*fyOneMinusB;
        double c3 = TshiftP*fyOneMinusB;
        double sigmaMax = c1+c3;
        double sigmaMin = c1-c2;


        // Evaluate stress sensitivity
        if ( (sigmaMax < sigmaElastic) && (fabs(sigmaMax-sigmaElastic)>1e-5) ) {
                Tstress = sigmaMax;
                gradient = E0Sensitivity*b*Tstrain
                                 + E0*bSensitivity*Tstrain
                                 + TshiftP*(fySensitivity*(1-b)-fy*bSensitivity);
        }
        else {
                Tstress = sigmaElastic;
                gradient = CstressSensitivity
                             + E0Sensitivity*(Tstrain-Cstrain)
                                 - E0*CstrainSensitivity;
        }
        if (sigmaMin > Tstress) {
                gradient = E0Sensitivity*b*Tstrain
                             + E0*bSensitivity*Tstrain
                                 - TshiftN*(fySensitivity*(1-b)-fy*bSensitivity);
        }

        return gradient;
}




double
Steel01::getInitialTangentSensitivity(int gradNumber)
{
        // For now, assume that this is only called for initial stiffness
        if (parameterID == 2) {
                return 1.0;
        }
        else {
                return 0.0;
        }
}



double
Steel01::getDampTangentSensitivity(int gradNumber)
{
        return 0.0;
}



double
Steel01::getRhoSensitivity(int gradNumber)
{
        return 0.0;
}

int
Steel01::commitSensitivity(double TstrainSensitivity, int gradNumber, int numGrads)
{
        if (SHVs == 0) {
                SHVs = new Matrix(2,numGrads);
        }


        // Initialize unconditaional stress sensitivity
        double gradient = 0.0;


        // Pick up sensitivity history variables
        double CstrainSensitivity = 0.0;
        double CstressSensitivity        = 0.0;
        if (SHVs != 0) {
                CstrainSensitivity = (*SHVs)(0,(gradNumber-1));
                CstressSensitivity = (*SHVs)(1,(gradNumber-1));
        }


        // Assign values to parameter derivatives (depending on what's random)
        double fySensitivity = 0.0;
        double E0Sensitivity = 0.0;
        double bSensitivity = 0.0;
        if (parameterID == 1) {
                fySensitivity = 1.0;
        }
        else if (parameterID == 2) {
                E0Sensitivity = 1.0;
        }
        else if (parameterID == 3) {
                bSensitivity = 1.0;
        }


        // Compute min and max stress
        double Tstress;
        double dStrain = Tstrain-Cstrain;
        double sigmaElastic = Cstress + E0*dStrain;
        double fyOneMinusB = fy * (1.0 - b);
        double c1 = Esh*Tstrain;
        double c2 = TshiftN*fyOneMinusB;
        double c3 = TshiftP*fyOneMinusB;
        double sigmaMax = c1+c3;
        double sigmaMin = c1-c2;


        // Evaluate stress sensitivity ('gradient')
        if ( (sigmaMax < sigmaElastic) && (fabs(sigmaMax-sigmaElastic)>1e-5) ) {
                Tstress = sigmaMax;
                gradient = E0Sensitivity*b*Tstrain
                                 + E0*bSensitivity*Tstrain
                                 + E0*b*TstrainSensitivity
                                 + TshiftP*(fySensitivity*(1-b)-fy*bSensitivity);
        }
        else {
                Tstress = sigmaElastic;
                gradient = CstressSensitivity
                             + E0Sensitivity*(Tstrain-Cstrain)
                                 + E0*(TstrainSensitivity-CstrainSensitivity);
        }
        if (sigmaMin > Tstress) {
                gradient = E0Sensitivity*b*Tstrain
                             + E0*bSensitivity*Tstrain
                             + E0*b*TstrainSensitivity
                                 - TshiftN*(fySensitivity*(1-b)-fy*bSensitivity);
        }


        // Commit history variables
        (*SHVs)(0,(gradNumber-1)) = TstrainSensitivity;
        (*SHVs)(1,(gradNumber-1)) = gradient;

        return 0;
}

// AddingSensitivity:END /////////////////////////////////////////////