Hsiao (2013) Strain Range Fatigue Model

For developers writing C++, Fortran, Java, code who have questions or comments to make.

Moderators: silvia, selimgunay, Moderators

Post Reply
edwardal
Posts: 20
Joined: Wed Aug 24, 2016 5:33 am
Location: Istituto Universitario di Studi Superiori (IUSS)

Hsiao (2013) Strain Range Fatigue Model

Post by edwardal » Tue Feb 14, 2017 2:25 pm

The strain range based fatigue model developed in "A model to simulate special concentrically braced frames beyond brace fracture" (Hsiao et. al. 2013) was implemented in OpenSees, but I do not see this particular material available anywhere in OpenSees. The amount of coding to implement this into the existing FatigueMaterial would not be terrible, but I would prefer using a version that has already been used/tested. Is this material "publicly" available? It does not appear to be anywhere in the source code, or available as either the .cpp and .h files or a .dll file. If someone could direct me to these files (or point out something that I missed) it would be greatly appreciated.

Thanks,

Ed

(Link to paper): https://www.researchgate.net/publicatio ... e_fracture

TPdct
Posts: 43
Joined: Thu Jan 21, 2016 5:51 am
Location: Dalian University of Technology

Re: Hsiao (2013) Strain Range Fatigue Model

Post by TPdct » Tue Feb 14, 2017 5:42 pm

It's here:

FractureMaterial.h:

#ifndef FractureMaterial_h
#define FractureMaterial_h
#include <UniaxialMaterial.h>
#define MAT_TAG_FractureMaterial 5002
class FractureMaterial : public UniaxialMaterial
{
public:
FractureMaterial(int tag, UniaxialMaterial &material, UniaxialMaterial &materialpost, int Index,
double w_t, double KL_r, double E_Fy,
double Cons = 0.1435,
double Alfa
= -0.4,
double Beta
= -0.3,
double Gama = 0.2,
double minStrain = -1.0e16,
double maxStrain = 1.0e16 );
FractureMaterial();
~FractureMaterial();
const char *getClassType(void) const {return "FractureMaterial";};
int setTrialStrain(double strain, double strainRate = 0.0);
double getStrain(void);
double getStrainRate(void);
double getStress(void);
double getTangent(void);
double getDampTangent(void);
double getInitialTangent(void) {return theMaterial->getInitialTangent();}
int commitState(void);
int revertToLastCommit(void);
int revertToStart(void);
UniaxialMaterial *getCopy(void);
int sendSelf(int commitTag, Channel &theChannel);
int recvSelf(int commitTag, Channel &theChannel,
FEM_ObjectBroker &theBroker);
void Print(OPS_Stream &s, int flag =0);
protected:
private:
UniaxialMaterial *theMaterial;
UniaxialMaterial *theMaterialpost;
int SF;
//int SFF;
double w_t;
double KL_r;
double E_Fy; // w/t Ratio
// KL/r slendness Ratio
// E/ Fy
double Cons;
double Alfa;
double Beta;
double Gama; // Parameters for prediction of the Limit Strain Range
double minStrain;
double maxStrain;
int Index;
bool Cfailed;
bool Tfailed;
double trialStrain;
double mStress;
// For Recording maximun of Strain Range
double maxS;
double minS;
double LimitSR;
double MaxSR;
};
#endif


FractureMaterial.cpp:

#include <elementAPI.h>
#include <stdlib.h>
#include <MaterialResponse.h>
#include <Information.h>
#include <FractureMaterial.h>
#include <ID.h>
#include <Channel.h>
#include <FEM_ObjectBroker.h>
#include <OPS_Globals.h>
#include <OPS_Stream.h>
#ifdef _USRDLL
#define OPS_Export extern "C" _declspec(dllexport)
#elif _MACOSX
#define OPS_Export extern "C" __attribute__((visibility("default")))
#else
#define OPS_Export extern "C"
#endif
OPS_Export void
localInit()
{
OPS_Error("FractureMaterial unaxial material - Written by Po-Chien UW Copyright 2010 - \n", 1);
}
OPS_Export void *
OPS_FractureMaterial()
{
int iData[4];
double dData[9];
int numData;
numData = 1;
if (OPS_GetIntInput( &numData, iData) != 0) {
opserr << "WARNING invalid uniaxialMaterial FractureMaterial tag" << endln;
return 0;
}
numData = 1;
if (OPS_GetIntInput(&numData, &iData[1]) != 0) {
opserr << "WARNING invalid material tag for FractureMaterial " << endln;
return 0;
}
numData = 1;
if (OPS_GetIntInput(&numData, &iData[2]) != 0) {
opserr << "WARNING invalid material tag for FractureMaterial " << endln;
return 0;
}
numData = 1;
if (OPS_GetIntInput(&numData, &iData[3]) != 0) {
opserr << "WARNING invalid Index for FractureMaterial " << endln;
return 0;
}
numData = 9;
if (OPS_GetDoubleInput(&numData, dData) != 0) {
opserr << "WARNING invalid minStrain & maxStrain \n";
return 0;
}
int matID = iData[1];
UniaxialMaterial *theMaterial1 = OPS_GetUniaxialMaterial(matID);
if (theMaterial1 == 0) {
opserr << "WARNING material with tag " << matID << "not found for preFractureMaterial \n"<<
endln;
return 0;
}
int matID2 = iData[2];
UniaxialMaterial *theMaterial2 = OPS_GetUniaxialMaterial(matID2);
if (theMaterial2 == 0) {
opserr << "WARNING material with tag " << matID2 << "not found for post FractureMaterial \n"<<
endln;
return 0;
}
/*(int tag, UniaxialMaterial &material, double w__t , double KL__r, double E__Fy,
double cons, double alfa, double beta, double gama,
double epsmin, double epsmax )*/
UniaxialMaterial *theMaterial3 = new FractureMaterial(iData[0], *theMaterial1, *theMaterial2,
iData[3], dData[0], dData[1], dData[2], dData[3], dData[4], dData[5], dData[6], dData[7], dData[8]);
//UniaxialMaterial *theMaterial2 = new FractureMaterial(iData[0], *theMaterial1, dData[0],
dData[1]);
if (theMaterial3 == 0) {
opserr << "WARNING could not create uniaxialMaterial of type FractureMaterial \n";
return 0;
}
return theMaterial3;
}
FractureMaterial::FractureMaterial(int tag, UniaxialMaterial &material, UniaxialMaterial &materialpost,
int iindex, double w__t , double KL__r, double E__Fy,
double cons, double alfa, double beta, double gama,
double epsmin, double epsmax )
:UniaxialMaterial(tag,MAT_TAG_FractureMaterial), theMaterial(0), theMaterialpost(0),
Index(iindex),
w_t(w__t), KL_r(KL__r), E_Fy(E__Fy),
Cons(cons), Alfa(alfa), Beta(beta), Gama(gama),
minStrain(epsmin), maxStrain(epsmax), Cfailed(false), Tfailed(false), trialStrain(0)
{
SF= 0;
//SFF = 1;
maxS=0.0;
minS=0.0;
LimitSR = Cons*(fabs(pow(w_t,Alfa)))*(fabs(pow(KL_r,Beta)))*(fabs(pow(E_Fy,Gama)));
MaxSR = 0.0;
mStress = 0.0;
theMaterial = material.getCopy();
theMaterialpost = materialpost.getCopy();
if (theMaterial == 0) {
opserr << "FractureMaterial::FractureMaterial -- failed to get copy of material\n";
exit(-1);
}
if (theMaterialpost == 0) {
opserr << "FractureMaterial::FractureMaterial -- failed to get copy of material\n";
exit(-1);
}
}
FractureMaterial::FractureMaterial()
:UniaxialMaterial(0,MAT_TAG_FractureMaterial), theMaterial(0),theMaterialpost(0), Index(0),
w_t(0.0), KL_r(0.0), E_Fy(0.0),
Cons(0.0), Alfa(0.0), Beta(0.0), Gama(0.0),
minStrain(0.0), maxStrain(0.0), Cfailed(false), Tfailed(false), trialStrain(0)
{
SF= 0;
//SFF = 1;
maxS=0.0;
minS=0.0;
LimitSR = 0.0;
MaxSR = 0.0;
mStress = 0.0;
}
FractureMaterial::~FractureMaterial()
{
if (theMaterial)
delete theMaterial;
}
int
FractureMaterial::setTrialStrain(double strain, double strainRate)
{
//if (Cfailed)
// return 0;
// trialStrain = strain;
if( Cfailed )
{
//Tfailed = true;
trialStrain = strain;
return theMaterialpost->setTrialStrain(strain, strainRate);
//return 0;
} else {
Cfailed = false ;
trialStrain = strain;
return theMaterial->setTrialStrain(strain, strainRate);
}
}
double
FractureMaterial::getStress(void)
{
if (Cfailed) {
//double modifier = pow(0.001,SFF);
return theMaterialpost->getStress();
//return 0.0;
} else
return theMaterial->getStress();
}
double
FractureMaterial::getTangent(void)
{
if (Cfailed) {
//double modifier = 1.0e-8 ;
return theMaterialpost->getTangent() ;
} else
return theMaterial->getTangent();
}
double
FractureMaterial::getDampTangent(void)
{
if (Cfailed)
return 0.0;
else
return theMaterial->getDampTangent();
}
double
FractureMaterial::getStrain(void)
{
return theMaterial->getStrain();
}
double
FractureMaterial::getStrainRate(void)
{
return theMaterial->getStrainRate();
}
int
FractureMaterial::commitState(void)
{
if (Cfailed) {
//SFF = SFF +1;
return 0;
}
//Cfailed = Tfailed ;
//Initialize the fatigue parameters if they have
// not been initialized yet
if (SF == 0) {
SF = 1 ;
//SFF = 1;
// Initialize other params if not done so already
maxS = 0.0;
minS = 0.0;
MaxSR = 0.0;
mStress = 0.0;
}
/*//Simple check to see if we reached max strain capacities
if (trialStrain >= maxStrain || trialStrain <= minStrain) {
Tfailed = true;
opserr << "FractureMaterial: material tag " << this->getTag() << " failed from excessive strain\n";
return 0;
} */
// Find the current maximun strain range
if (trialStrain > maxS) {
maxS = trialStrain ;
} else if (trialStrain < minS) {
minS = trialStrain ;
}
MaxSR = fabs( maxS - minS) ;
//if (Cfailed)
//
mStress = 10;
// else
mStress = theMaterial->getStress();
if (Index == 0) {
if ( trialStrain >= maxStrain || trialStrain <= minStrain ) {
Cfailed =true;
opserr << "FractureMaterial: material tag " << this->getTag() << " failed \n";
return 0;
} else {
Cfailed = false;
return theMaterial->commitState();
}
} else {
if ( MaxSR >= LimitSR && mStress >= 0 ) {
Cfailed =true;
opserr << "FractureMaterial: material tag " << this->getTag() << " failed \n";
return 0;
} else {
Cfailed = false;
return theMaterial->commitState();
}
}
}
int
FractureMaterial::revertToLastCommit(void)
{
// Check if failed at last step
if (Cfailed)
return 0;
else
return theMaterial->revertToLastCommit();
}
int
FractureMaterial::revertToStart(void)
{
Cfailed = false;
Tfailed = false;
SF=0;
maxS=0.0;
minS=0.0;
LimitSR = 0.0;
MaxSR = 0.0;
w_t = 0.0;
KL_r = 0.0;
E_Fy = 0.0;
Cons = 0.0;
Alfa = 0.0;
Beta = 0.0;
Gama = 0.0;
Index = 0;
return theMaterial->revertToStart();
}
UniaxialMaterial *
FractureMaterial::getCopy(void)
{
FractureMaterial *theCopy =
new FractureMaterial(this->getTag(), *theMaterial, *theMaterialpost, Index, w_t, KL_r, E_Fy,
Cons, Alfa, Beta, Gama, minStrain, maxStrain);
theCopy->Cfailed = Cfailed;
theCopy->Tfailed = Tfailed;
theCopy->trialStrain = trialStrain;
return theCopy;
}
int
FractureMaterial::sendSelf(int cTag, Channel &theChannel)
{
int dbTag = this->getDbTag();
static ID dataID(3);
dataID(0) = this->getTag();
dataID(1) = theMaterial->getClassTag();
int matDbTag = theMaterial->getDbTag();
if ( matDbTag == 0) {
matDbTag = theChannel.getDbTag();
theMaterial->setDbTag(matDbTag);
}
dataID(2) = matDbTag;
if (theChannel.sendID(dbTag, cTag, dataID) < 0) {
opserr << "FractureMaterial::sendSelf() - failed to send the ID\n";
return -1;
}
static Vector dataVec(11);
dataVec(0) = w_t;
dataVec(1) = KL_r;
dataVec(2) = E_Fy;
dataVec(3) = Cons;
dataVec(4) = Alfa;
dataVec(5) = Beta;
dataVec(6) = Gama;
dataVec(7) = minStrain;
dataVec(8) = maxStrain;
dataVec(9) = SF;
if (Cfailed == true)
dataVec(10) = 1.0;
else
dataVec(10) = 0.0;
if (theChannel.sendVector(dbTag, cTag, dataVec) < 0) {
opserr << "FractureMaterial::sendSelf() - failed to send the Vector\n";
return -2;
}
if (theMaterial->sendSelf(cTag, theChannel) < 0) {
opserr << "FractureMaterial::sendSelf() - failed to send the Material\n";
return -3;
}
return 0;
}
int
FractureMaterial::recvSelf(int cTag, Channel &theChannel,
FEM_ObjectBroker &theBroker)
{
int dbTag = this->getDbTag();
static ID dataID(3);
if (theChannel.recvID(dbTag, cTag, dataID) < 0) {
opserr << "FractureMaterial::recvSelf() - failed to get the ID\n";
return -1;
}
this->setTag(int(dataID(0)));
// as no way to change material, don't have to check classTag of the material
if (theMaterial == 0) {
int matClassTag = int(dataID(1));
theMaterial = theBroker.getNewUniaxialMaterial(matClassTag);
if (theMaterial == 0) {
opserr << "FractureMaterial::recvSelf() - failed to create Material with classTag "
<< dataID(0) << endln;
return -2;
}
}
theMaterial->setDbTag(dataID(2));
static Vector dataVec(11);
if (theChannel.recvVector(dbTag, cTag, dataVec) < 0) {
opserr << "FractureMaterial::recvSelf() - failed to get the Vector\n";
return -3;
}
w_t = dataVec(0);
KL_r = dataVec(1);
E_Fy = dataVec(2);
Cons = dataVec(3);
Alfa = dataVec(4);
Beta = dataVec(5);
Gama = dataVec(6);
minStrain = dataVec(7);
maxStrain = dataVec(8);
SF = dataVec(9);
if (dataVec(10) == 1.0)
Cfailed = true;
else
Cfailed = false;
Tfailed = Cfailed;
if (theMaterial->recvSelf(cTag, theChannel, theBroker) < 0) {
opserr << "FractureMaterial::recvSelf() - failed to get the Material\n";
return -4;
}
return 0;
}
void
FractureMaterial::Print(OPS_Stream &s, int flag)
{
s << "FractureMaterial tag: " << this->getTag() << endln;
s << "\tMaterial: " << theMaterial->getTag() << endln;
//s << "\tMin strain: " << minStrain << endln;
//s << "\tMax strain: " << maxStrain << endln;
}

TPdct
Posts: 43
Joined: Thu Jan 21, 2016 5:51 am
Location: Dalian University of Technology

Re: Hsiao (2013) Strain Range Fatigue Model

Post by TPdct » Tue Feb 14, 2017 5:45 pm

The source code above can be found in his PhD thesis: Seismic Performance Evaluation of Concentrically Braced Frames

edwardal
Posts: 20
Joined: Wed Aug 24, 2016 5:33 am
Location: Istituto Universitario di Studi Superiori (IUSS)

Re: Hsiao (2013) Strain Range Fatigue Model

Post by edwardal » Wed Feb 15, 2017 2:58 am

Thank you very much!

nilz
Posts: 34
Joined: Sat Nov 12, 2016 7:03 am
Location: Ferdowsi university of mashhad

Re: Hsiao (2013) Strain Range Fatigue Model

Post by nilz » Sat Nov 18, 2017 10:26 am

Dear TPdct,
How can link the c++ code in the Hsiao's thesis with Opensees?
I do not know programming in C ++.
Please describe how can use this code in my Opensees code?

nilz
Posts: 34
Joined: Sat Nov 12, 2016 7:03 am
Location: Ferdowsi university of mashhad

Re: Hsiao (2013) Strain Range Fatigue Model

Post by nilz » Sat Dec 16, 2017 6:27 am

Dear edwardal
could you implement the above code in Opensees?
and could you find any version of Opensees which have the FractureMaterial?

Post Reply