Separate the solid material representation form the integrand classes themselves, to better facilitate other material laws. Preparation to plasticity modeling.

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@863 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo
2011-03-10 21:21:24 +00:00
committed by Knut Morten Okstad
parent 45850b859d
commit 324c863956
32 changed files with 994 additions and 633 deletions

View File

@@ -0,0 +1,86 @@
// $Id$
//==============================================================================
//!
//! \file LinearMaterial.C
//!
//! \date Mar 08 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief General linear elastic material with push-forward transformations.
//!
//==============================================================================
#include "LinearMaterial.h"
#include "Tensor.h"
double LinearMaterial::getMassDensity (const Vec3& X) const
{
return material->getMassDensity(X);
}
bool LinearMaterial::evaluate (Matrix& C, SymmTensor& sigma, double& U,
const Vec3& X, const Tensor& F,
const SymmTensor& eps, char iop,
const TimeDomain* prm) const
{
// Evaluate the constitutive matrix and the stress tensor at this point
if (!material->evaluate(C,sigma,U,X,F,eps,iop,prm))
return false;
else if (iop == 2)
return true;
double J = F.det();
if (J == 0.0)
{
std::cerr <<" *** LinearMaterial::evaluate: "
<<" Singular/zero deformation gradient\n"<< F;
return false;
}
// Push-forward the constitutive matrix to current configuration
size_t i, j, k, l;
size_t n = F.dim();
size_t m = C.rows();
Matrix T(m,m), Ctmp;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
T(i,j) = F(j,i)*F(j,i);
for (j = n+1, k = 1; j <= m; j++, k++)
T(i,j) = 0.5*(F(k,i)*F(k%3+1,i) + F(k%3+1,i)*F(k,i));
}
for (i = n+1, k = 1; i <= m; i++, k++)
{
for (j = 1; j <= n; j++)
T(i,j) = F(j,k)*F(j,k%3+1) + F(j,k%3+1)*F(j,k);
for (j = n+1, l = 1; j <= m; j++, l++)
T(i,j) = 0.5*(F(l,k)*F(l%3+1,k%3+1) + F(l%3+1,k)*F(l,k%3+1) +
F(l,k%3+1)*F(l%3+1,k) + F(l%3+1,k%3+1)*F(l,k));
}
// C = 1/J * T^t * C * T
Ctmp.multiply(C,T);
C.multiply(T,Ctmp,true);
C *= 1.0/J;
#if INT_DEBUG > 0
std::cout <<"LinearMaterial::C ="<< C;
#endif
if (iop == 1)
{
// Push-forward the stress tensor to current configuration
sigma.transform(F); // sigma = F * sigma * F^t
sigma *= 1.0/J;
#if INT_DEBUG > 0
std::cout <<"LinearMaterial::sigma =\n"<< sigma;
#endif
}
return true;
}

View File

@@ -0,0 +1,59 @@
// $Id$
//==============================================================================
//!
//! \file LinearMaterial.h
//!
//! \date Mar 08 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief General linear elastic material with push-forward transformations.
//!
//==============================================================================
#ifndef _LINEAR_MATERIAL_H
#define _LINEAR_MATERIAL_H
#include "MaterialBase.h"
/*!
\brief Class representing a isotropic linear elastic material model.
*/
class LinearMaterial : public Material
{
public:
//! \brief The constructor initializes the material properties pointer.
LinearMaterial(const Material* mat) : material(mat) {}
//! \brief The destructor deletes the material properties object.
virtual ~LinearMaterial() { delete material; }
//! \brief Prints out material parameters to the given output stream.
virtual void print(std::ostream& os) const { material->print(os); }
//! \brief Evaluates the mass density at an integration point.
virtual double getMassDensity(const Vec3& X) const;
//! \brief Evaluates the constitutive relation at an integration point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density at current point
//! \param[in] X Cartesian coordinates of current point
//! \param[in] F Deformation gradient at current point
//! \param[in] eps Strain tensor at current point
//! \param[in] iop Calculation option;
//! -1 : Calculate the inverse constitutive matrix only,
//! 0 : Calculate the constitutive matrix only,
//! 1 : Calculate Cauchy stresses and the constitutive matrix.
//! 2 : 2nd Piola-Kirchhoff stresses and the tangent constitutive matrix.
//! \param[in] prm Nonlinear solution algorithm parameters
virtual bool evaluate(Matrix& C, SymmTensor& sigma, double& U,
const Vec3& X, const Tensor& F, const SymmTensor& eps,
char iop = 1, const TimeDomain* prm = 0) const;
private:
const Material* material; //!< Pointer to actual material properties object
};
#endif

View File

@@ -1,4 +1,4 @@
// $Id: NeoHookeElasticity.C,v 1.2 2011-02-08 09:06:02 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file NeoHookeElasticity.C
@@ -23,7 +23,7 @@ void NeoHookeElasticity::print (std::ostream& os) const
void NeoHookeElasticity::setMaterial (double Emod, double Poiss, double Density)
{
this->Elasticity::setMaterial(Emod,Poiss,Density);
//this->Elasticity::setMaterial(Emod,Poiss,Density);
// Define the Lame elasticity parameters
lambda = Emod*Poiss / ((1.0+Poiss)*(1.0-Poiss-Poiss));
@@ -43,7 +43,8 @@ bool NeoHookeElasticity::formStressTensor (const Matrix& dNdX, const Vec3&,
}
// Evaluate the kinematic quantities, F, E, Ci, and J at this point
if (!this->kinematics(dNdX,E))
Tensor _F(nsd);
if (!this->kinematics(dNdX,_F,E))
return false;
// Set up the 2nd Piola-Kirchhoff stress tensor, S
@@ -65,17 +66,17 @@ bool NeoHookeElasticity::formTangent (Matrix& Ctan, SymmTensor& S,
}
bool NeoHookeElasticity::kinematics (const Matrix& dNdX, SymmTensor& _E) const
bool NeoHookeElasticity::kinematics (const Matrix& dNdX,
Tensor& _F, SymmTensor& _E) const
{
// Form the deformation gradient, F
if (!this->NonlinearElasticity::kinematics(dNdX,_E))
if (!this->NonlinearElasticity::kinematics(dNdX,_F,_E))
return false;
else
J = F.det();
J = _F.det();
// Form the right Cauchy-Green tensor, C = F^T*F
static Tensor dUdX(nsd);
C.rightCauchyGreen(dUdX=F);
C.rightCauchyGreen(_F);
// Invert the right Cauchy-Green tensor, Ci = C^-1
Ci = C;

View File

@@ -1,4 +1,4 @@
// $Id: NeoHookeElasticity.h,v 1.1 2010-12-18 20:03:53 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file NeoHookeElasticity.h
@@ -45,13 +45,14 @@ public:
protected:
//! \brief Calculates some kinematic quantities at current point.
//! \param[in] dNdX Basis function gradients at current point
//! \param[out] _F Deformation gradient at current point
//! \param[out] _E Green-Lagrange strain tensor at current point
//!
//! \details The deformation gradient \b F and the Green-Lagrange tensor \b E
//! are established. In addition, the right Cauchy-Green tensor \b C and its
//! inverse \b Ci are formed.
//! All quantities are stored internally in mutable data members.
virtual bool kinematics(const Matrix& dNdX, SymmTensor& _E) const;
virtual bool kinematics(const Matrix& dNdX, Tensor& _F, SymmTensor& _E) const;
//! \brief Forms tangential tensorial quantities needed by the evalInt method.
//! \param[in] X Cartesian coordinates of current integration point

View File

@@ -0,0 +1,118 @@
// $Id$
//==============================================================================
//!
//! \file NeoHookeMaterial.C
//!
//! \date Mar 08 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Neo-Hookean hyperelastic material model.
//!
//==============================================================================
#include "NeoHookeMaterial.h"
#include "Tensor.h"
#ifdef USE_FTNMAT
extern "C" {
//! \brief Interface to 2D nonlinear material routines (FORTRAN-77 code).
void cons2d_(const int& ipsw, const int& iter, const int& iwr,
const int& lfirst, const int& mTYP, const int& mVER,
const int& nHV, const int& nTM, const double& detF,
const double* F, const double* pMAT, double* HV, double& Engy,
const double* Sig, double* Cst, int& ierr);
//! \brief Interface to 3D nonlinear material routines (FORTRAN-77 code).
void cons3d_(const int& ipsw, const int& iter, const int& iwr,
const int& lfirst, const int& mTYP, const int& mVER,
const int& nHV, const int& nTM, const double& detF,
const double* F, const double* pMAT, double* HV, double& Engy,
const double* Sig, double* Cst, int& ierr);
}
#ifndef INT_DEBUG
#define INT_DEBUG 0
#endif
#endif
NeoHookeMaterial::NeoHookeMaterial () : LinIsotropic(false)
{
mTYP = 10;
mVER = 0;
pmat[0] = Emod;
pmat[1] = nu;
}
NeoHookeMaterial::NeoHookeMaterial (double E, double v, double d, int ver)
: LinIsotropic(E,v,d,false)
{
mTYP = 10;
mVER = ver;
pmat[0] = Emod;
pmat[1] = nu;
if (nu > 0.5)
{
mTYP = -10; // Assume Lame' parameters (kappa and mu are specified)
double kappa = Emod;
double mu = nu;
// Calculate Young's modulus and Poisson's ratio
Emod = 9.0*kappa*mu/(3.0*kappa + mu);
nu = (1.5*kappa - mu)/(3.0*kappa + mu);
}
}
void NeoHookeMaterial::print (std::ostream& os) const
{
this->LinIsotropic::print(os);
std::cout <<"NeoHookeMaterial: mVER = "<< mVER << std::endl;
}
bool NeoHookeMaterial::evaluate (Matrix& C, SymmTensor& sigma, double& U,
const Vec3& X, const Tensor& F,
const SymmTensor&, char iop,
const TimeDomain*) const
{
double J = F.det();
if (J == 0.0)
{
std::cerr <<" *** NeoHookeMaterial::evaluate: "
<<" Singular/zero deformation gradient\n"<< F;
return false;
}
size_t ndim = F.dim();
size_t ncmp = ndim*(ndim+1)/2;
C.resize(ncmp,ncmp);
int ipsw = INT_DEBUG > 1 ? 9 : 0;
int ierr = 0;
#ifdef USE_FTNMAT
// Invoke the FORTRAN routine for Neo-Hookean hyperelastic material models.
if (ndim == 2)
cons2d_(ipsw,0,6,0,mTYP,mVER,0,3,J,F.ptr(),pmat,
&U,U,sigma.ptr(),C.ptr(),ierr);
else
cons3d_(ipsw,0,6,0,mTYP,mVER,0,6,J,F.ptr(),pmat,
&U,U,sigma.ptr(),C.ptr(),ierr);
#endif
if (iop == 2)
{
// Transform to 2nd Piola-Kirchhoff stresses,
// via pull-back to reference configuration
Tensor Fi(F);
Fi.inverse();
sigma.transform(Fi); // sigma = F^-1 * sigma * F^-t
sigma *= J;
}
#if INT_DEBUG > 0
if (iop > 0)
std::cout <<"NeoHookeMaterial::sigma =\n"<< sigma;
std::cout <<"NeoHookeMaterial::C ="<< C;
#endif
return ierr == 0;
}

View File

@@ -0,0 +1,56 @@
// $Id$
//==============================================================================
//!
//! \file NeoHookeMaterial.h
//!
//! \date Mar 08 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Neo-Hookean hyperelastic material model.
//!
//==============================================================================
#ifndef _NEO_HOOKE_MATERIAL_H
#define _NEO_HOOKE_MATERIAL_H
#include "LinIsotropic.h"
/*!
\brief Class representing a Neo-Hookean hyperelastic material model.
*/
class NeoHookeMaterial : public LinIsotropic
{
public:
//! \brief Default constructor.
NeoHookeMaterial();
//! \brief Constructor initializing the material parameters.
NeoHookeMaterial(double E, double v = 0.0, double density = 0.0, int ver = 0);
//! \brief Empty destructor.
virtual ~NeoHookeMaterial() {}
//! \brief Prints out material parameters to the given output stream.
virtual void print(std::ostream&) const;
//! \brief Evaluates the constitutive relation at an integration point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density
//! \param[in] F Deformation gradient at current point
//! \param[in] iop Calculation option;
//! 0 : Calculate the consitutive matrix only,
//! 1 : Cauchy stresses and the tangent constitutive matrix,
//! 2 : 2nd Piola-Kirchhoff stresses and the tangent constitutive matrix.
virtual bool evaluate(Matrix& C, SymmTensor& sigma, double& U,
const Vec3&, const Tensor& F, const SymmTensor&,
char iop = 1, const TimeDomain* = 0) const;
private:
int mTYP; //!< Material type
int mVER; //!< Material version
double pmat[2]; //!< Material properties
};
#endif

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "NonlinearElasticity.h"
#include "MaterialBase.h"
#include "Utilities.h"
#include "Profiler.h"
@@ -51,8 +52,8 @@ extern "C" {
#endif
NonlinearElasticity::NonlinearElasticity (unsigned short int n, bool ps)
: NonlinearElasticityTL(n,ps), E(n)
NonlinearElasticity::NonlinearElasticity (unsigned short int n)
: NonlinearElasticityTL(n), E(n)
{
fullCmat = false;
}
@@ -80,14 +81,15 @@ bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
PROFILE3("NonlinearEl::evalInt");
// Evaluate the kinematic quantities, F and E, at this point
if (!this->kinematics(dNdX,E))
Tensor F(nsd);
if (!this->kinematics(dNdX,F,E))
return false;
// Evaluate current tangent at this point, that is
// the incremental constitutive matrix, Cmat, and
// the 2nd Piola-Kirchhoff stress tensor, S
static SymmTensor S(nsd);
if (!this->formTangent(Cmat,S,X))
SymmTensor S(nsd);
if (!this->formTangent(Cmat,S,X,F))
return false;
bool haveStrains = !E.isZero(1.0e-16);
@@ -189,7 +191,7 @@ bool NonlinearElasticity::evalSol (Vector& s, const Vector&,
}
// Evaluate the stress state at this point
static SymmTensor Sigma(nsd);
SymmTensor Sigma(nsd);
if (!this->formStressTensor(dNdX,X,Sigma))
return false;
@@ -207,7 +209,7 @@ bool NonlinearElasticity::evalSol (Vector& s,
{
PROFILE3("NonlinearEl::evalSol");
static SymmTensor Sigma(nsd);
SymmTensor Sigma(nsd);
if (!this->formStressTensor(dNdX,X,Sigma))
return false;
@@ -227,24 +229,19 @@ bool NonlinearElasticity::formStressTensor (const Matrix& dNdX, const Vec3& X,
}
// Evaluate the kinematic quantities, F and E, at this point
if (!this->kinematics(dNdX,E))
Tensor F(nsd);
if (!this->kinematics(dNdX,F,E))
return false;
// Evaluate the constitutive matrix, C, at this point
if (!this->formCmatrix(Cmat,X))
return false;
return Cmat.multiply(E,S); // S = C*E
// Evaluate the stress tensor, S, at this point
double U;
return material->evaluate(Cmat,S,U,X,F,E);
}
bool NonlinearElasticity::formTangent (Matrix& Ctan, SymmTensor& S,
const Vec3& X) const
const Vec3& X, const Tensor& F) const
{
if (!this->formCmatrix(Ctan,X))
return false;
else if (eV && !eV->empty())
return Ctan.multiply(E,S); // S = C*E
else
return true; // Initial state (no stresses)
double U;
return material->evaluate(Ctan,S,U,X,F,E,!E.isZero());
}

View File

@@ -1,4 +1,4 @@
// $Id: NonlinearElasticity.h,v 1.2 2011-02-08 09:06:02 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file NonlinearElasticity.h
@@ -36,8 +36,7 @@ class NonlinearElasticity : public NonlinearElasticityTL
public:
//! \brief The default constructor invokes the parent class constructor only.
//! \param[in] n Number of spatial dimensions
//! \param[in] ps If \e true, assume plane stress in 2D
NonlinearElasticity(unsigned short int n = 3, bool ps = true);
NonlinearElasticity(unsigned short int n = 3);
//! \brief Empty destructor.
virtual ~NonlinearElasticity() {}
@@ -76,10 +75,12 @@ public:
protected:
//! \brief Forms tangential tensorial quantities needed by the evalInt method.
//! \param[in] X Cartesian coordinates of current integration point
//! \param[out] Ctan Tangential constitutive tensor at current point
//! \param[out] S 2nd Piola-Kirchhoff stress tensor at current point
virtual bool formTangent(Matrix& Ctan, SymmTensor& S, const Vec3& X) const;
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] F Deformation gradient at current integration point
virtual bool formTangent(Matrix& Ctan, SymmTensor& S,
const Vec3& X, const Tensor& F) const;
//! \brief Forms the 2nd Piola-Kirchhoff stress tensor.
//! \param[in] dNdX Basis function gradients at current integration point

View File

@@ -12,13 +12,14 @@
//==============================================================================
#include "NonlinearElasticity.h"
#include "MaterialBase.h"
#include "ElmMats.h"
#include "Tensor.h"
#include "Vec3Oper.h"
NonlinearElasticityTL::NonlinearElasticityTL (unsigned short int n, bool ps)
: Elasticity(n,ps)
NonlinearElasticityTL::NonlinearElasticityTL (unsigned short int n)
: Elasticity(n)
{
// Only the current solution is needed
primsol.resize(1);
@@ -85,17 +86,20 @@ bool NonlinearElasticityTL::evalInt (LocalIntegral*& elmInt, double detJW,
const Vec3& X) const
{
// Evaluate the deformation gradient, F, and the Green-Lagrange strains, E,
// and compute the nonlinear strain-displacement matrix B from dNdX and F
// and compute the nonlinear strain-displacement matrix, B, from dNdX and F
Tensor F(nsd);
SymmTensor E(nsd), S(nsd);
if (!this->kinematics(dNdX,E))
if (!this->kinematics(dNdX,F,E))
return false;
// Evaluate the constitutive relation
double U = 0.0;
bool lHaveStrains = !E.isZero();
if (eKm || eKg || iS)
if (!this->constitutive(Cmat,S,U,E,X, (eKg || iS) && lHaveStrains))
{
double U;
if (!material->evaluate(Cmat,S,U,X,F,E, (eKg || iS) && lHaveStrains))
return false;
}
if (eKm)
{
@@ -156,8 +160,9 @@ bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt, double detJW,
if (tracFld->isNormalPressure())
{
// Compute the deformation gradient, F
Tensor F(nsd);
SymmTensor dummy(0);
if (!this->kinematics(dNdX,dummy)) return false;
if (!this->kinematics(dNdX,F,dummy)) return false;
// Compute its inverse and determinant, J
double J = F.inverse();
@@ -182,13 +187,14 @@ bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt, double detJW,
}
bool NonlinearElasticityTL::kinematics (const Matrix& dNdX, SymmTensor& E) const
bool NonlinearElasticityTL::kinematics (const Matrix& dNdX,
Tensor& F, SymmTensor& E) const
{
if (!eV || eV->empty())
{
// Initial state, unit deformation gradient and linear B-matrix
F.diag(1.0,nsd);
return this->Elasticity::kinematics(dNdX,E);
F = 1.0;
return this->Elasticity::kinematics(dNdX,F,E);
}
const size_t nenod = dNdX.rows();
@@ -206,7 +212,10 @@ bool NonlinearElasticityTL::kinematics (const Matrix& dNdX, SymmTensor& E) const
// Notice that the matrix multiplication method used here treats the
// element displacement vector, *eV, as a matrix whose number of columns
// equals the number of rows in the matrix dNdX.
if (!F.multiplyMat(*eV,dNdX)) // F = Grad{u} = eV*dNdX
Matrix dUdX;
if (dUdX.multiplyMat(*eV,dNdX)) // dUdX = Grad{u} = eV*dNd
F = dUdX;
else
return false;
unsigned short int i, j, k;
@@ -224,11 +233,10 @@ bool NonlinearElasticityTL::kinematics (const Matrix& dNdX, SymmTensor& E) const
}
// Add the unit tensor to F to form the deformation gradient
for (i = 1; i <= nsd; i++)
F(i,i) += 1.0;
F += 1.0;
#ifdef INT_DEBUG
std::cout <<"NonlinearElasticityTL::F ="<< F;
std::cout <<"NonlinearElasticityTL::F =\n"<< F;
#endif
if (!formB || E.dim() < nsd) return true;

View File

@@ -31,8 +31,7 @@ class NonlinearElasticityTL : public Elasticity
public:
//! \brief The default constructor invokes the parent class constructor only.
//! \param[in] n Number of spatial dimensions
//! \param[in] ps If \e true, assume plane stress in 2D
NonlinearElasticityTL(unsigned short int n = 3, bool ps = true);
NonlinearElasticityTL(unsigned short int n = 3);
//! \brief Empty destructor.
virtual ~NonlinearElasticityTL() {}
@@ -70,17 +69,17 @@ public:
protected:
//! \brief Calculates some kinematic quantities at current point.
//! \param[in] dNdX Basis function gradients at current point
//! \param[in] F Deformation gradient at current point
//! \param[out] E Green-Lagrange strain tensor at current point
//!
//! \details The deformation gradient \b F and the nonlinear
//! strain-displacement matrix \b B are established. The latter matrix
//! is stored in the mutable class member \a Bmat of the parent class.
//! The B-matrix is formed only when the variable \a formB is true.
virtual bool kinematics(const Matrix& dNdX, SymmTensor& E) const;
virtual bool kinematics(const Matrix& dNdX, Tensor& F, SymmTensor& E) const;
protected:
bool formB; //!< Flag determining whether we need to form the B-matrix
mutable Matrix F; //!< Deformation gradient
bool formB; //!< Flag determining whether we need to form the B-matrix
mutable Matrix CB; //!< Result of the matrix-matrix product C*B
};

View File

@@ -12,40 +12,16 @@
//==============================================================================
#include "NonlinearElasticityUL.h"
#include "MaterialBase.h"
#include "ElmMats.h"
#include "ElmNorm.h"
#include "Tensor.h"
#include "Vec3Oper.h"
#ifdef USE_FTNMAT
extern "C" {
//! \brief Interface to 2D nonlinear material routines (FORTRAN-77 code).
void cons2d_(const int& ipsw, const int& iter, const int& iwr,
const int& lfirst, const int& mTYP, const int& mVER,
const int& nHV, const int& nTM, const double& detF,
const double* F, const double* pMAT, double* HV, double& Engy,
const double* Sig, double* Cst, int& ierr);
//! \brief Interface to 3D nonlinear material routines (FORTRAN-77 code).
void cons3d_(const int& ipsw, const int& iter, const int& iwr,
const int& lfirst, const int& mTYP, const int& mVER,
const int& nHV, const int& nTM, const double& detF,
const double* F, const double* pMAT, double* HV, double& Engy,
const double* Sig, double* Cst, int& ierr);
}
#ifndef INT_DEBUG
#define INT_DEBUG 0
#endif
#endif
NonlinearElasticityUL::NonlinearElasticityUL (unsigned short int n,
bool ps, int mver, char lop)
: Elasticity(n,ps)
NonlinearElasticityUL::NonlinearElasticityUL (unsigned short int n, char lop)
: Elasticity(n)
{
mVER = -1;
#ifdef USE_FTNMAT
if (n == 3 || (n == 2 && !ps)) mVER = mver;
#endif
loadOp = lop;
// Only the current solution is needed
@@ -55,30 +31,9 @@ NonlinearElasticityUL::NonlinearElasticityUL (unsigned short int n,
void NonlinearElasticityUL::print (std::ostream& os) const
{
this->Elasticity::print(os);
std::cout <<"NonlinearElasticityUL: Updated Lagrangian formulation";
if (mVER >= 0) std::cout <<", mVER="<< mVER;
if (mVER >= 1) std::cout <<" (Neo-Hooke)";
std::cout << std::endl;
}
void NonlinearElasticityUL::setMaterial (double Young, double Poiss,
double Density)
{
mTYP = 10;
pmat[0] = Young;
pmat[1] = Poiss;
if (Poiss > 0.5)
{
mTYP *= -1; // Assume Lame' parameters (kappa and mu are specified)
double kappa = Young;
double mu = Poiss;
// Calculate Young's modulus and Poisson's ratio
Young = 9.0*kappa*mu/(3.0*kappa + mu);
Poiss = (1.5*kappa - mu)/(3.0*kappa + mu);
}
this->Elasticity::setMaterial(Young,Poiss,Density);
material->print(os);
std::cout <<"NonlinearElasticityUL: Updated Lagrangian formulation"
<< std::endl;
}
@@ -86,6 +41,7 @@ void NonlinearElasticityUL::setMode (SIM::SolutionMode mode)
{
if (!myMats) return;
size_t nvec = 1 + primsol.size();
myMats->rhsOnly = false;
eM = eKm = eKg = 0;
iS = eS = eV = 0;
@@ -93,13 +49,13 @@ void NonlinearElasticityUL::setMode (SIM::SolutionMode mode)
switch (mode)
{
case SIM::STATIC:
myMats->resize(1,2);
myMats->resize(1,nvec);
eKm = &myMats->A[0];
eKg = &myMats->A[0];
break;
case SIM::DYNAMIC:
myMats->resize(2,2);
myMats->resize(2,nvec);
eKm = &myMats->A[0];
eKg = &myMats->A[0];
eM = &myMats->A[1];
@@ -107,9 +63,9 @@ void NonlinearElasticityUL::setMode (SIM::SolutionMode mode)
case SIM::RHS_ONLY:
if (myMats->A.empty())
myMats->resize(1,2);
myMats->resize(1,nvec);
else
myMats->b.resize(2);
myMats->b.resize(nvec);
eKm = &myMats->A[0];
eKg = &myMats->A[0];
myMats->rhsOnly = true;
@@ -132,18 +88,18 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const
{
elmInt = myMats;
// Evaluate the deformation gradient, F, and the Green-Lagrange strains, E
Tensor F(nsd);
SymmTensor E(nsd);
if (!this->kinematics(dNdX,E))
if (!this->kinematics(dNdX,F,E))
return false;
bool lHaveStrains = !E.isZero();
if (lHaveStrains)
{
// Invert the deformation gradient ==> Fi
Matrix Fi(F);
Matrix Fi(nsd,nsd);
Fi.fill(F.ptr());
double J = Fi.inverse();
if (J == 0.0) return false;
@@ -156,7 +112,7 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt, double detJW,
dNdx.multiply(dNdX,Fi); // dNdx = dNdX * F^-1
// Compute the small-deformation strain-displacement matrix B from dNdx
if (!this->formBmatrix(dNdx)) return false;
#if INT_DEBUG > 0
#ifdef INT_DEBUG
std::cout <<"NonlinearElasticityUL::dNdx ="<< dNdx;
std::cout <<"NonlinearElasticityUL::B ="<< Bmat;
#endif
@@ -168,10 +124,12 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the constitutive relation
SymmTensor sigma(nsd);
double U = 0.0;
if (eKm || eKg || iS)
if (!this->constitutive(Cmat,sigma,U,E,X, (eKg || iS) && lHaveStrains))
{
double U = 0.0;
if (!material->evaluate(Cmat,sigma,U,X,F,E, (eKg || iS) && lHaveStrains))
return false;
}
if (eKm)
{
@@ -200,7 +158,7 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt, double detJW,
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,detJW);
return true;
return this->getIntegralResult(elmInt);
}
@@ -208,7 +166,6 @@ bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X, const Vec3& normal) const
{
elmInt = myMats;
if (!tracFld)
{
std::cerr <<" *** NonlinearElasticityUL::evalBou: No tractions."
@@ -232,7 +189,8 @@ bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
if (loadOp == 1)
{
// Compute the deformation gradient, F
if (!this->formDefGradient(dNdX)) return false;
Tensor F(nsd);
if (!this->formDefGradient(dNdX,F)) return false;
// Check for with-rotated pressure load
if (tracFld->isNormalPressure())
@@ -260,23 +218,25 @@ bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
for (i = 1; i <= nsd; i++)
ES(nsd*(a-1)+i) += T[i-1]*N(a)*detJW;
return true;
return this->getIntegralResult(elmInt);
}
bool NonlinearElasticityUL::formDefGradient (const Matrix& dNdX) const
bool NonlinearElasticityUL::formDefGradient (const Matrix& dNdX,
Tensor& F) const
{
static SymmTensor dummy(0);
return this->kinematics(dNdX,dummy);
SymmTensor dummy(0);
return this->kinematics(dNdX,F,dummy);
}
bool NonlinearElasticityUL::kinematics (const Matrix& dNdX, SymmTensor& E) const
bool NonlinearElasticityUL::kinematics (const Matrix& dNdX,
Tensor& F, SymmTensor& E) const
{
if (!eV || eV->empty())
{
// Initial state, unit deformation gradient and zero strains
F.diag(1.0,nsd);
F = 1.0;
E.zero();
return true;
}
@@ -295,7 +255,10 @@ bool NonlinearElasticityUL::kinematics (const Matrix& dNdX, SymmTensor& E) const
// Notice that the matrix multiplication method used here treats the
// element displacement vector, *eV, as a matrix whose number of columns
// equals the number of rows in the matrix dNdX.
if (!F.multiplyMat(*eV,dNdX)) // F = Grad{u} = eV*dNdX
Matrix dUdX;
if (dUdX.multiplyMat(*eV,dNdX)) // dUdX = Grad{u} = eV*dNdX
F = dUdX;
else
return false;
unsigned short int i, j, k;
@@ -313,118 +276,11 @@ bool NonlinearElasticityUL::kinematics (const Matrix& dNdX, SymmTensor& E) const
}
// Add the unit tensor to F to form the deformation gradient
for (i = 1; i <= nsd; i++)
F(i,i) += 1.0;
F += 1.0;
#if INT_DEBUG > 0
#ifdef INT_DEBUG
std::cout <<"NonlinearElasticityUL::eV ="<< *eV;
std::cout <<"NonlinearElasticityUL::F ="<< F;
#endif
return true;
}
bool NonlinearElasticityUL::constitutive (Matrix& C, SymmTensor& sigma,
double& U, const SymmTensor& eps,
const Vec3& X,
char calcStress) const
{
double J = F.det();
if (J == 0.0)
{
std::cerr <<" *** NonlinearElasticityUL::constitutive: "
<<" Singular/zero deformation gradient"<< F;
return false;
}
size_t ndim = F.rows();
#ifdef USE_FTNMAT
if (mVER >= 0)
{
// Invoke the FORTRAN routine for constitutive relations.
// This also includes the Neo-Hookean hyperelastic material models.
size_t ncmp = ndim*(ndim+1)/2;
C.resize(ncmp,ncmp);
int ipsw = INT_DEBUG > 1 ? 9 : 0;
int ierr = 0;
if (ndim == 2)
cons2d_(ipsw,0,6,0,mTYP,mVER,0,3,J,F.ptr(),pmat,
&U,U,sigma.ptr(),C.ptr(),ierr);
else
cons3d_(ipsw,0,6,0,mTYP,mVER,0,6,J,F.ptr(),pmat,
&U,U,sigma.ptr(),C.ptr(),ierr);
if (calcStress == 2)
{
// Transform to 2nd Piola-Kirchhoff stresses,
// via pull-back to reference configuration
F.inverse();
Tensor Fi(ndim);
sigma.transform(Fi=F); // sigma = F^-1 * sigma * F^-t
sigma *= J;
}
#if INT_DEBUG > 0
if (calcStress)
std::cout <<"NonlinearElasticityUL::sigma =\n"<< sigma;
std::cout <<"NonlinearElasticityUL::C ="<< C;
#endif
return ierr == 0;
}
#endif
// We are only doing pure isotrophic linear elastic material in this method.
// Evaluate the constitutive matrix at this point, but first reset nsd to ndim
// since it is used to set the dimension on C.
unsigned short int tmp = nsd;
const_cast<NonlinearElasticityUL*>(this)->nsd = ndim;
if (!this->formCmatrix(C,X)) return false;
const_cast<NonlinearElasticityUL*>(this)->nsd = tmp;
if (calcStress)
// Evaluate the symmetric stress tensor
C.multiply(eps,sigma); // sigma = C*eps
if (calcStress == 1)
{
// Push-forward the stress tensor to current configuration
Tensor dUdX(ndim);
sigma.transform(dUdX=F); // sigma = F * sigma * F^t
sigma *= 1.0/J;
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityUL::sigma =\n"<< sigma;
#endif
}
else if (calcStress == 2)
return true;
// Push-forward the constitutive matrix to current configuration
size_t i, j, k, l, m = C.rows();
Matrix T(m,m), Ctmp;
for (i = 1; i <= ndim; i++)
{
for (j = 1; j <= ndim; j++)
T(i,j) = F(j,i)*F(j,i);
for (j = ndim+1, k = 1; j <= m; j++, k++)
T(i,j) = 0.5*(F(k,i)*F(k%3+1,i) + F(k%3+1,i)*F(k,i));
}
for (i = ndim+1, k = 1; i <= m; i++, k++)
{
for (j = 1; j <= ndim; j++)
T(i,j) = F(j,k)*F(j,k%3+1) + F(j,k%3+1)*F(j,k);
for (j = ndim+1, l = 1; j <= m; j++, l++)
T(i,j) = 0.5*(F(l,k)*F(l%3+1,k%3+1) + F(l%3+1,k)*F(l,k%3+1) +
F(l,k%3+1)*F(l%3+1,k) + F(l%3+1,k%3+1)*F(l,k));
}
// C = 1/J * T^t * C * T
Ctmp.multiply(C,T);
C.multiply(T,Ctmp,true);
C *= 1.0/J;
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityUL::C ="<< C;
std::cout <<"NonlinearElasticityUL::F =\n"<< F;
#endif
return true;
@@ -446,15 +302,16 @@ bool ElasticityNormUL::evalInt (LocalIntegral*& elmInt, double detJW,
NonlinearElasticityUL* ulp = static_cast<NonlinearElasticityUL*>(&problem);
// Evaluate the deformation gradient, F, and the Green-Lagrange strains, E
Tensor F(dNdX.cols());
SymmTensor E(dNdX.cols());
if (!ulp->kinematics(dNdX,E))
if (!ulp->kinematics(dNdX,F,E))
return false;
// Evaluate the 2nd Piola Kirchhoff stresses, S
Matrix C;
SymmTensor S(E.dim());
double U = 0.0;
if (!ulp->constitutive(C,S,U,E,X,2))
if (!ulp->material->evaluate(C,S,U,X,F,E,2))
return false;
if (U == 0.0)

View File

@@ -16,6 +16,8 @@
#include "Elasticity.h"
struct TimeDomain;
/*!
\brief Class representing the integrand of the nonlinear elasticity problem.
@@ -25,9 +27,6 @@
strain tensor, and the method \a constitutive for calculating the tangent
constitutive matrix and the associated stress tensor. The \a evalInt and
\a evalBou methods are also reimplemented to account for the updated geometry.
This class supports isotrophic linear-elastic and neo-Hookean hyperelastic
material laws. The material properties are assumed constant in space.
*/
class NonlinearElasticityUL : public Elasticity
@@ -35,26 +34,14 @@ class NonlinearElasticityUL : public Elasticity
public:
//! \brief The default constructor invokes the parent class constructor.
//! \param[in] n Number of spatial dimensions
//! \param[in] ps If \e true, assume plane stress in 2D
//! \param[in] mver Material version parameter
//! \param[in] lop Load option (0=on initial length, 1=on updated length)
NonlinearElasticityUL(unsigned short int n = 3,
bool ps = false, int mver = 0, char lop = 0);
NonlinearElasticityUL(unsigned short int n = 3, char lop = 0);
//! \brief Empty destructor.
virtual ~NonlinearElasticityUL() {}
//! \brief Prints out problem definition to the given output stream.
virtual void print(std::ostream& os) const;
//! \brief Defines the material properties to use.
//! \param[in] Young Young's modulus
//! \param[in] Poiss Poisson's ratio
//! \param[in] Density Mass density
//!
//! \details If \a Poiss > 0.5, it is assumed that \a Young and \a Poiss
//! are the Lame's parameters instead (bulk and shear moduli).
virtual void setMaterial(double Young, double Poiss, double Density);
//! \brief Defines the solution mode before the element assembly is started.
//! \param[in] mode The solution mode to use
virtual void setMode(SIM::SolutionMode mode);
@@ -93,40 +80,24 @@ public:
//! \brief Calculates some kinematic quantities at current point.
//! \param[in] dNdX Basis function gradients at current point
//! \param[out] F Deformation gradient at current point
//! \param[out] E Green-Lagrange strain tensor at current point
//!
//! \details The deformation gradient is established and stored in
//! the mutable class member \a F.
virtual bool kinematics(const Matrix& dNdX, SymmTensor& E) const;
//! \brief Calculates the deformation gradient at current point.
//! \param[in] dNdX Basis function gradients at current point
bool formDefGradient(const Matrix& dNdX) const;
//! \brief Evaluates the constitutive relation at current point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density
//! \param[in] eps Strain tensor at current point
//! \param[in] X Cartesian coordinates of current point
//! \param[in] calcStress Stress calculation option.
//! 0: No stress calculation, only output the C-matrix,
//! 1: Calculate Cauchy stresses,
//! 2: Calculate Second Piola Kirchhoff stresses.
virtual bool constitutive(Matrix& C, SymmTensor& sigma, double& U,
const SymmTensor& eps, const Vec3& X,
char calcStress = 1) const;
virtual bool kinematics(const Matrix& dNdX, Tensor& F, SymmTensor& E) const;
protected:
//! \brief Calculates the deformation gradient at current point.
//! \param[in] dNdX Basis function gradients at current point
//! \param[out] F Deformation gradient at current point
bool formDefGradient(const Matrix& dNdX, Tensor& F) const;
protected:
mutable Matrix F; //!< Deformation gradient
mutable Matrix dNdx; //!< Basis function gradients in current configuration
mutable Matrix CB; //!< Result of the matrix-matrix product C*B
private:
char loadOp; //!< Load option
int mTYP; //!< Material type
int mVER; //!< Material version
double pmat[2]; //!< Material properties
char loadOp; //!< Load option
friend class ElasticityNormUL;
};

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "NonlinearElasticityULMX.h"
#include "MaterialBase.h"
#include "ElmMats.h"
#include "ElmNorm.h"
#include "Utilities.h"
@@ -39,9 +40,8 @@ extern "C" {
#endif
NonlinearElasticityULMX::NonlinearElasticityULMX (unsigned short int n,
int mver, int pp)
: NonlinearElasticityUL(n, false, mver < 0 ? 0 : mver)
NonlinearElasticityULMX::NonlinearElasticityULMX (unsigned short int n, int pp)
: NonlinearElasticityUL(n)
{
p = pp;
iP = 0;
@@ -151,7 +151,6 @@ bool NonlinearElasticityULMX::evalInt (LocalIntegral*& elmInt, double detJW,
if (myMats->b.size() < 3) return false;
ItgPtData& ptData = myData[iP++];
unsigned short int i, j;
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityUL::dNdX ="<< dNdX;
@@ -159,31 +158,25 @@ bool NonlinearElasticityULMX::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the deformation gradient, Fp, at previous configuration
const_cast<NonlinearElasticityULMX*>(this)->eV = &myMats->b[2];
if (this->formDefGradient(dNdX))
for (i = 1; i <= nsd; i++)
for (j = 1; j <= nsd; j++)
ptData.Fp(i,j) = F(i,j);
else
if (!this->formDefGradient(dNdX,ptData.Fp))
return false;
// Evaluate the deformation gradient, F, at current configuration
const_cast<NonlinearElasticityULMX*>(this)->eV = &myMats->b[1];
if (this->formDefGradient(dNdX))
for (i = 1; i <= nsd; i++)
for (j = 1; j <= nsd; j++)
ptData.F(i,j) = F(i,j);
else
if (!this->formDefGradient(dNdX,ptData.F))
return false;
if (nsd == 2) // In 2D we always assume plane strain so set F(3,3)=1
ptData.F(3,3) = ptData.Fp(3,3) = 1.0;
// Invert the deformation gradient ==> Fi
double J = F.inverse();
Tensor Fi(nsd);
Fi = ptData.F;
double J = Fi.inverse();
if (J == 0.0) return false;
// Push-forward the basis function gradients to current configuration
ptData.dNdx.multiply(dNdX,F); // dNdx = dNdX * F^-1
ptData.dNdx.multiply(dNdX,Fi); // dNdx = dNdX * F^-1
ptData.X.assign(X);
ptData.detJW = detJW;
@@ -359,7 +352,6 @@ bool NonlinearElasticityULMX::finalizeElement (LocalIntegral*& elmInt)
Vector Sigm(nPM), Hsig;
std::vector<SymmTensor> Sig;
Sig.reserve(nGP);
F.resize(3,3);
bool lHaveStress = false;
for (iP = 0; iP < nGP; iP++)
@@ -371,9 +363,8 @@ bool NonlinearElasticityULMX::finalizeElement (LocalIntegral*& elmInt)
// Evaluate the constitutive relation
double U = 0.0;
F.fill(pt.F.ptr());
Sig.push_back(SymmTensor(3));
if (!this->constitutive(Cmat,Sig.back(),U,Sig.back(),pt.X))
if (!material->evaluate(Cmat,Sig.back(),U,pt.X,pt.F,Sig.back()))
return false;
#ifdef USE_FTNMAT
@@ -569,7 +560,6 @@ bool ElasticityNormULMX::finalizeElement (LocalIntegral*& elmInt)
Matrix C;
SymmTensor Sig(3);
elp.F.resize(3,3);
for (iP = 0; iP < nGP; iP++)
{
@@ -583,8 +573,7 @@ bool ElasticityNormULMX::finalizeElement (LocalIntegral*& elmInt)
// Compute the strain energy density
double U = 0.0;
elp.F.fill(pt.F.ptr());
if (!elp.constitutive(C,Sig,U,Sig,pt.X,false))
if (!elp.material->evaluate(C,Sig,U,pt.X,pt.F,Sig,false))
return false;
// Integrate strain energy

View File

@@ -42,9 +42,8 @@ class NonlinearElasticityULMX : public NonlinearElasticityUL
public:
//! \brief The default constructor invokes the parent class constructor.
//! \param[in] n Number of spatial dimensions
//! \param[in] mver Material version parameter
//! \param[in] pp Polynomial order of the pressure/volumetric-change field
NonlinearElasticityULMX(unsigned short int n = 3, int mver = 0, int pp = 1);
NonlinearElasticityULMX(unsigned short int n = 3, int pp = 1);
//! \brief Empty destructor.
virtual ~NonlinearElasticityULMX() {}

View File

@@ -12,9 +12,9 @@
//==============================================================================
#include "NonlinearElasticityULMixed.h"
#include "MaterialBase.h"
#include "ElmMats.h"
#include "Utilities.h"
#include "Tensor.h"
#ifdef USE_FTNMAT
extern "C" {
@@ -189,13 +189,9 @@ const Vector& NonlinearElasticityULMixed::MixedElmMats::getRHSVector () const
}
NonlinearElasticityULMixed::NonlinearElasticityULMixed (unsigned short int n,
int mver)
: NonlinearElasticityUL(n,false,mver)
NonlinearElasticityULMixed::NonlinearElasticityULMixed (unsigned short int n)
: NonlinearElasticityUL(n), Fbar(n), Dmat(7,7)
{
Fbar.resize(3,3);
Dmat.resize(7,7);
if (myMats) delete myMats;
myMats = new MixedElmMats();
@@ -302,8 +298,9 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt, double detJW,
const Vec3& X) const
{
// Evaluate the deformation gradient, F, and the Green-Lagrange strains, E
Tensor F(nsd);
SymmTensor E(nsd);
if (!this->kinematics(dNdX1,E))
if (!this->kinematics(dNdX1,F,E))
return false;
bool lHaveStrains = !E.isZero();
@@ -354,10 +351,9 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt, double detJW,
this->formBodyForce(*eS,N1,X,J*detJW);
// Evaluate the constitutive relation
F = Fbar;
SymmTensor Eps(3), Sig(3), Sigma(nsd);
double U, Bpres = 0.0, Mpres = 0.0;
if (!this->constitutive(Cmat,Sig,U,Eps=E,X,lHaveStrains))
if (!material->evaluate(Cmat,Sig,U,X,Fbar,Eps=E,lHaveStrains))
return false;
#ifdef USE_FTNMAT

View File

@@ -1,4 +1,4 @@
// $Id: NonlinearElasticityULMixed.h,v 1.2 2010-12-30 15:25:14 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file NonlinearElasticityULMixed.h
@@ -16,6 +16,7 @@
#include "NonlinearElasticityUL.h"
#include "ElmMats.h"
#include "Tensor.h"
/*!
@@ -44,8 +45,7 @@ class NonlinearElasticityULMixed : public NonlinearElasticityUL
public:
//! \brief The default constructor invokes the parent class constructor.
//! \param[in] n Number of spatial dimensions
//! \param[in] mver Material version parameter
NonlinearElasticityULMixed(unsigned short int n = 3, int mver = 0);
NonlinearElasticityULMixed(unsigned short int n = 3);
//! \brief Empty destructor.
virtual ~NonlinearElasticityULMixed() {}
@@ -101,7 +101,7 @@ public:
}
protected:
mutable Matrix Fbar; //!< Mixed model deformation gradient
mutable Tensor Fbar; //!< Mixed model deformation gradient
mutable Matrix Dmat; //!< Projected mixed constitutive matrix
};

View File

@@ -1,4 +1,4 @@
// $Id: SIMFiniteDefEl.C,v 1.3 2010-12-29 18:51:53 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file SIMFiniteDefEl.C
@@ -12,36 +12,40 @@
//==============================================================================
#include "SIMFiniteDefEl.h"
#include "LinIsotropic.h"
#include "LinearMaterial.h"
#include "NeoHookeMaterial.h"
#include "NonlinearElasticityULMixed.h"
#include "NonlinearElasticityULMX.h"
#include "NeoHookeElasticity.h"
#include "Utilities.h"
#include "Property.h"
SIMFiniteDefEl2D::SIMFiniteDefEl2D (int form, bool planeStress,
const std::vector<int>& options)
SIMFiniteDefEl2D::SIMFiniteDefEl2D (const std::vector<int>& options)
: SIMLinEl2D(SIM::NONE)
{
int mVER = options.size() > 0 ? options[0] : -1; // material version
int pOrd = options.size() > 1 ? options[1] : 0; // pressure field order
int form = options.size() > 0 ? options[0] : 0; // problem formulation
int pOrd = options.size() > 1 ? options[1] : 0; // pressure field order
switch (form)
{
case SIM::MIXED_QnQn1:
nf[1] = 2; // continuous volumetric change and pressure fields
myProblem = new NonlinearElasticityULMixed(2,mVER);
myProblem = new NonlinearElasticityULMixed(2);
break;
case SIM::MIXED_QnPn1:
// Local discontinuous volumetric change and pressure fields
myProblem = new NonlinearElasticityULMX(2,mVER,pOrd);
myProblem = new NonlinearElasticityULMX(2,pOrd);
break;
case SIM::UPDATED_LAGRANGE:
myProblem = new NonlinearElasticityUL(2,planeStress,mVER);
myProblem = new NonlinearElasticityUL(2);
break;
case SIM::TOTAL_LAGRANGE:
myProblem = new NonlinearElasticityTL(2,planeStress);
myProblem = new NonlinearElasticityTL(2);
break;
case SIM::NONLINEAR: // Old tensor-based TL-formulation
myProblem = new NonlinearElasticity(2,planeStress);
myProblem = new NonlinearElasticity(2);
break;
default:
std::cerr <<" *** SIMFiniteDefEl2D: Unknown problem formulation "
@@ -50,25 +54,65 @@ SIMFiniteDefEl2D::SIMFiniteDefEl2D (int form, bool planeStress,
}
SIMFiniteDefEl3D::SIMFiniteDefEl3D (bool checkRHS, int form,
bool SIMFiniteDefEl2D::parse (char* keyWord, std::istream& is)
{
if (!strncasecmp(keyWord,"ISOTROPIC",9))
{
int nmat = atoi(keyWord+10);
if (myPid == 0)
std::cout <<"\nNumber of isotropic materials: "<< nmat << std::endl;
char* cline = 0;
for (int i = 0; i < nmat && (cline = utl::readLine(is)); i++)
{
int code = atoi(strtok(cline," "));
if (code > 0)
this->setPropertyType(code,Property::MATERIAL,mVec.size());
double E = atof(strtok(NULL," "));
double nu = atof(strtok(NULL," "));
double rho = atof(strtok(NULL," "));
int matVer = (cline = strtok(NULL," ")) ? atoi(cline) : -1;
if (matVer >= 0)
mVec.push_back(new NeoHookeMaterial(E,nu,rho,matVer));
else
mVec.push_back(new LinearMaterial(new LinIsotropic(E,nu,rho)));
if (myPid == 0)
std::cout <<"\tMaterial code "<< code <<": "
<< E <<" "<< nu <<" "<< rho <<" ("<< matVer <<")"<< std::endl;
}
}
else
return this->SIMLinEl2D::parse(keyWord,is);
if (!mVec.empty())
{
Elasticity* elp = dynamic_cast<Elasticity*>(myProblem);
if (elp) elp->setMaterial(mVec.front());
}
return true;
}
SIMFiniteDefEl3D::SIMFiniteDefEl3D (bool checkRHS,
const std::vector<int>& options)
: SIMLinEl3D(checkRHS,SIM::NONE)
{
int mVER = options.size() > 0 ? options[0] : -1; // material version
int pOrd = options.size() > 1 ? options[1] : 0; // pressure field order
int form = options.size() > 0 ? options[0] : 0; // problem formulation
int pOrd = options.size() > 1 ? options[1] : 0; // pressure field order
switch (form)
{
case SIM::MIXED_QnQn1:
nf[1] = 2; // continuous volumetric change and pressure fields
myProblem = new NonlinearElasticityULMixed(3,mVER);
myProblem = new NonlinearElasticityULMixed();
break;
case SIM::MIXED_QnPn1:
// Local discontinuous volumetric change and pressure fields
myProblem = new NonlinearElasticityULMX(3,mVER,pOrd);
myProblem = new NonlinearElasticityULMX(3,pOrd);
break;
case SIM::UPDATED_LAGRANGE:
myProblem = new NonlinearElasticityUL(3,false,mVER);
myProblem = new NonlinearElasticityUL();
break;
case SIM::TOTAL_LAGRANGE:
myProblem = new NonlinearElasticityTL();
@@ -87,3 +131,43 @@ SIMFiniteDefEl3D::SIMFiniteDefEl3D (bool checkRHS, int form,
<< form << std::endl;
}
}
bool SIMFiniteDefEl3D::parse (char* keyWord, std::istream& is)
{
if (!strncasecmp(keyWord,"ISOTROPIC",9))
{
int nmat = atoi(keyWord+10);
if (myPid == 0)
std::cout <<"\nNumber of isotropic materials: "<< nmat << std::endl;
char* cline = 0;
for (int i = 0; i < nmat && (cline = utl::readLine(is)); i++)
{
int code = atoi(strtok(cline," "));
if (code > 0)
this->setPropertyType(code,Property::MATERIAL,mVec.size());
double E = atof(strtok(NULL," "));
double nu = atof(strtok(NULL," "));
double rho = atof(strtok(NULL," "));
int matVer = (cline = strtok(NULL," ")) ? atoi(cline) : -1;
if (matVer >= 0)
mVec.push_back(new NeoHookeMaterial(E,nu,rho,matVer));
else
mVec.push_back(new LinearMaterial(new LinIsotropic(E,nu,rho)));
if (myPid == 0)
std::cout <<"\tMaterial code "<< code <<": "
<< E <<" "<< nu <<" "<< rho <<" ("<< matVer <<")"<< std::endl;
}
}
else
return this->SIMLinEl3D::parse(keyWord,is);
if (!mVec.empty())
{
Elasticity* elp = dynamic_cast<Elasticity*>(myProblem);
if (elp) elp->setMaterial(mVec.front());
}
return true;
}

View File

@@ -1,4 +1,4 @@
// $Id: SIMFiniteDefEl.h,v 1.2 2010-12-29 18:51:53 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file SIMFiniteDefEl.h
@@ -41,13 +41,16 @@ class SIMFiniteDefEl2D : public SIMLinEl2D
{
public:
//! \brief Default constructor.
//! \param[in] form Problem formulation option
//! \param[in] planeStress Plane stress/plane strain option
//! \param[in] options Additional solution formulation options
SIMFiniteDefEl2D(int form = SIM::TOTAL_LAGRANGE, bool planeStress = false,
const std::vector<int>& options = std::vector<int>());
SIMFiniteDefEl2D(const std::vector<int>& options = std::vector<int>());
//! \brief Empty destructor.
virtual ~SIMFiniteDefEl2D() {}
protected:
//! \brief Parses a data section from the input stream.
//! \param[in] keyWord Keyword of current data section to read
//! \param is The file stream to read from
virtual bool parse(char* keyWord, std::istream& is);
};
@@ -60,12 +63,17 @@ class SIMFiniteDefEl3D : public SIMLinEl3D
public:
//! \brief Default constructor.
//! \param[in] checkRHS If \e true, ensure the model is in a right-hand system
//! \param[in] form Problem formulation option
//! \param[in] options Additional solution formulation options
SIMFiniteDefEl3D(bool checkRHS = false, int form = SIM::TOTAL_LAGRANGE,
SIMFiniteDefEl3D(bool checkRHS = false,
const std::vector<int>& options = std::vector<int>());
//! \brief Empty destructor.
virtual ~SIMFiniteDefEl3D() {}
protected:
//! \brief Parses a data section from the input stream.
//! \param[in] keyWord Keyword of current data section to read
//! \param is The file stream to read from
virtual bool parse(char* keyWord, std::istream& is);
};
#endif

View File

@@ -1,4 +1,4 @@
// $Id: main_NonLinEl.C,v 1.6 2011-02-08 09:32:18 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file main_NonLinEl.C
@@ -47,9 +47,10 @@
\arg -check : Data check only, read model and output to VTF (no solution)
\arg -checkRHS : Check that the patches are modelled in a right-hand system
\arg -fixDup : Resolve co-located nodes by merging them into a single node
\arg -2D : Use two-parametric simulation driver
\arg -2D : Use two-parametric simulation driver (plane stress)
\arg -2Dpstrain : Use two-parametric simulation driver (plane strain)
\arg -Tensor : Use tensorial total Lagrangian formulation (slow...)
\arg -UL \a mver : Use updated Lagrangian formulation with nonlinear material
\arg -UL : Use updated Lagrangian formulation with nonlinear material
\arg -MX \a pord : Mixed formulation with internal discontinuous pressure
\arg -mixed : Mixed formulation with continuous pressure and volumetric change
\arg -lag : Use Lagrangian basis functions instead of splines/NURBS
@@ -72,7 +73,7 @@ int main (int argc, char** argv)
bool skip2nd = false;
bool checkRHS = false;
bool fixDup = false;
char twoD = false;
bool twoD = false;
char* infile = 0;
LinAlgInit linalg(argc,argv);
@@ -140,14 +141,14 @@ int main (int argc, char** argv)
checkRHS = true;
else if (!strcmp(argv[i],"-fixDup"))
fixDup = true;
else if (!strcmp(argv[i],"-2Dpstrain"))
twoD = SIMLinEl2D::planeStrain = true;
else if (!strncmp(argv[i],"-2D",3))
twoD = strcmp(argv[i],"-2Dpstrain") ? 1 : 2;
twoD = true;
else if (!strcmp(argv[i],"-UL"))
{
if (form < SIM::UPDATED_LAGRANGE)
form = SIM::UPDATED_LAGRANGE;
if (i < argc-1 && isdigit(argv[i+1][0]))
options[0] = atoi(argv[++i]);
}
else if (!strcmp(argv[i],"-MX"))
{
@@ -178,8 +179,8 @@ int main (int argc, char** argv)
{
std::cout <<"usage: "<< argv[0]
<<" <inputfile> [-dense|-spr|-superlu[<nt>]|-samg|-petsc]\n "
<<" [-lag] [-spec] [-2D[pstrain]] [-UL [<mVER>]] [-MX [<p>]|-mixe"
<<"d] [-nGauss <n>]\n [-vtf <format>] [-nviz <nviz>]"
<<" [-lag] [-spec] [-2D[pstrain]] [-UL] [-MX [<p>]|-mixed]"
<<" [-nGauss <n>]\n [-vtf <format>] [-nviz <nviz>]"
<<" [-nu <nu>] [-nv <nv>] [-nw <nw>]\n "
<<" [-saveInc <dtSave>] [-dumpInc <dtDump> [raw]]\n "
<<" [-ignore <p1> <p2> ...] [-fixDup] [-checkRHS] [-check]\n";
@@ -225,11 +226,12 @@ int main (int argc, char** argv)
utl::profiler->start("Model input");
// Create the finite deformation elasticity model
options[0] = form%100;
SIMbase* model;
if (twoD)
model = new SIMFiniteDefEl2D(form%100,twoD==1,options);
model = new SIMFiniteDefEl2D(options);
else
model = new SIMFiniteDefEl3D(checkRHS,form%100,options);
model = new SIMFiniteDefEl3D(checkRHS,options);
// Read in solver and model definitions
NonLinSIM simulator(model);
@@ -255,6 +257,7 @@ int main (int argc, char** argv)
std::cout <<"\nWriting updated g2-file "<< infile << std::endl;
std::ofstream osg(infile);
model->dumpGeometry(osg);
// Open ASCII file for solution dump
strcat(strtok(infile,"."),".sol");
oss = new std::ofstream(infile);
@@ -290,22 +293,25 @@ int main (int argc, char** argv)
if (!simulator.solveStep(params,SIM::STATIC))
return 5;
// Dump primary solution for inspection or external processing
if (params.time.t + epsT*params.time.dt > nextDump)
{
// Dump primary solution for inspection or external processing
if (dumpWithID)
simulator.dumpStep(params.step,params.time.t,std::cout);
else
simulator.dumpStep(params.step,params.time.t,*oss,false);
nextDump = params.time.t + dtDump;
}
// Save solution variables to VTF for visualization
if (params.time.t + epsT*params.time.dt > nextSave)
if (simulator.saveStep(++iStep,params.time.t,n,skip2nd))
nextSave = params.time.t + dtSave;
else
{
// Save solution variables to VTF for visualization
if (!simulator.saveStep(++iStep,params.time.t,n,skip2nd))
return 6;
nextSave = params.time.t + dtSave;
}
}
if (oss) delete oss;

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "SIMLinEl2D.h"
#include "LinIsotropic.h"
#include "LinearElasticity.h"
#include "AnalyticSolutions.h"
#include "Functions.h"
@@ -23,11 +24,19 @@
#include <string.h>
SIMLinEl2D::SIMLinEl2D (int, bool planeStress)
bool SIMLinEl2D::planeStrain = false;
SIMLinEl2D::SIMLinEl2D (int)
{
myProblem = new LinearElasticity(2,planeStress);
myProblem = new LinearElasticity(2);
}
SIMLinEl2D::~SIMLinEl2D ()
{
for (size_t i = 0; i < mVec.size(); i++)
delete mVec[i];
}
bool SIMLinEl2D::parse (char* keyWord, std::istream& is)
{
@@ -45,33 +54,28 @@ bool SIMLinEl2D::parse (char* keyWord, std::istream& is)
<< gx <<" "<< gy << std::endl;
}
else if (!strncasecmp(keyWord,"ISOTROPHIC",10))
else if (!strncasecmp(keyWord,"ISOTROPIC",9))
{
int nmat = atoi(keyWord+10);
if (myPid == 0)
std::cout <<"\nNumber of isotrophic materials: "<< nmat << std::endl;
std::cout <<"\nNumber of isotropic materials: "<< nmat << std::endl;
for (int i = 0; i < nmat && (cline = utl::readLine(is)); i++)
{
int code = atoi(strtok(cline," "));
int code = atoi(strtok(cline," "));
if (code > 0)
this->setPropertyType(code,Property::MATERIAL,mVec.size());
double E = atof(strtok(NULL," "));
double nu = atof(strtok(NULL," "));
double rho = atof(strtok(NULL," "));
mVec.push_back(new LinIsotropic(E,nu,rho,!planeStrain));
if (myPid == 0)
std::cout <<"\tMaterial code "<< code <<": "
<< E <<" "<< nu <<" "<< rho << std::endl;
if (code == 0 || i == 0)
elp->setMaterial(E,nu,rho);
for (size_t j = 0; j < myProps.size() && code > 0; j++)
if (myProps[j].pindx == (size_t)code &&
myProps[j].pcode == Property::UNDEFINED)
{
myProps[j].pindx = mVec.size();
myProps[j].pcode = Property::MATERIAL;
}
if (code > 0)
mVec.push_back(IsoMat(E,nu,rho));
}
if (!mVec.empty())
elp->setMaterial(mVec.front());
}
else if (!strncasecmp(keyWord,"CONSTANT_PRESSURE",17))
@@ -229,7 +233,7 @@ bool SIMLinEl2D::parse (char* keyWord, std::istream& is)
{
std::cout <<"\tMaterial for all patches: "
<< E <<" "<< nu <<" "<< rho << std::endl;
elp->setMaterial(E,nu,rho);
mVec.push_back(new LinIsotropic(E,nu,rho,!planeStrain));
}
else
{
@@ -241,11 +245,12 @@ bool SIMLinEl2D::parse (char* keyWord, std::istream& is)
std::cout <<"\tMaterial for P"<< patch
<<": "<< E <<" "<< nu <<" "<< rho << std::endl;
myProps.push_back(Property(Property::MATERIAL,mVec.size(),pid,3));
mVec.push_back(IsoMat(E,nu,rho));
if (i == 0)
elp->setMaterial(E,nu,rho);
mVec.push_back(new LinIsotropic(E,nu,rho,!planeStrain));
}
}
if (!mVec.empty())
elp->setMaterial(mVec.front());
}
else
@@ -262,7 +267,7 @@ bool SIMLinEl2D::initMaterial (size_t propInd)
if (propInd >= mVec.size()) propInd = mVec.size()-1;
elp->setMaterial(mVec[propInd].E,mVec[propInd].nu,mVec[propInd].rho);
elp->setMaterial(mVec[propInd]);
return true;
}

View File

@@ -17,6 +17,8 @@
#include "SIM2D.h"
#include "SIMenums.h"
class Material;
/*!
\brief Driver class for 2D isogeometric FEM analysis of elasticity problems.
@@ -27,27 +29,12 @@
class SIMLinEl2D : public SIM2D
{
//! \brief Struct for storage of physical material property parameters.
struct IsoMat
{
double E; //!< Young's modulus
double nu; //!< Poisson's ratio
double rho; //!< Mass density
//! \brief Default constructor.
IsoMat() { E = nu = rho = 0.0; }
//! \brief Constructor initializing a material instance.
IsoMat(double Emod, double Poiss, double D) : E(Emod), nu(Poiss), rho(D) {}
};
typedef std::vector<IsoMat> MaterialVec; //!< Vector of material data sets
public:
//! \brief Default constructor.
//! \param[in] form Problem formulation option
//! \param[in] planeStress Plane stress/plane strain option
SIMLinEl2D(int form = SIM::LINEAR, bool planeStress = true);
//! \brief Empty destructor.
virtual ~SIMLinEl2D() {}
SIMLinEl2D(int form = SIM::LINEAR);
//! \brief The destructor frees the dynamically allocated material properties.
virtual ~SIMLinEl2D();
protected:
//! \brief Parses a data section from the input stream.
@@ -63,8 +50,11 @@ protected:
//! \param[in] propInd Physical property index
virtual bool initNeumann(size_t propInd);
private:
MaterialVec mVec; //!< Material data
public:
static bool planeStrain; //!< Plane strain/stress option
protected:
std::vector<Material*> mVec; //!< Material data
};
#endif

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "SIMLinEl3D.h"
#include "LinIsotropic.h"
#include "LinearElasticity.h"
#include "AnalyticSolutions.h"
#include "Functions.h"
@@ -156,6 +157,13 @@ SIMLinEl3D::SIMLinEl3D (bool checkRHS, int) : SIM3D(checkRHS)
}
SIMLinEl3D::~SIMLinEl3D ()
{
for (size_t i = 0; i < mVec.size(); i++)
delete mVec[i];
}
bool SIMLinEl3D::parse (char* keyWord, std::istream& is)
{
char* cline = 0;
@@ -175,33 +183,27 @@ bool SIMLinEl3D::parse (char* keyWord, std::istream& is)
<< gx <<" "<< gy <<" "<< gz << std::endl;
}
else if (!strncasecmp(keyWord,"ISOTROPHIC",10))
else if (!strncasecmp(keyWord,"ISOTROPIC",9))
{
int nmat = atoi(keyWord+10);
if (myPid == 0)
std::cout <<"\nNumber of isotrophic materials: "<< nmat << std::endl;
std::cout <<"\nNumber of isotropic materials: "<< nmat << std::endl;
for (int i = 0; i < nmat && (cline = utl::readLine(is)); i++)
{
int code = atoi(strtok(cline," "));
int code = atoi(strtok(cline," "));
if (code > 0)
this->setPropertyType(code,Property::MATERIAL,mVec.size());
double E = atof(strtok(NULL," "));
double nu = atof(strtok(NULL," "));
double rho = atof(strtok(NULL," "));
mVec.push_back(new LinIsotropic(E,nu,rho));
if (myPid == 0)
std::cout <<"\tMaterial code "<< code <<": "
<< E <<" "<< nu <<" "<< rho << std::endl;
if (code == 0 || i == 0)
elp->setMaterial(E,nu,rho);
for (size_t j = 0; j < myProps.size() && code > 0; j++)
if (myProps[j].pindx == (size_t)code &&
myProps[j].pcode == Property::UNDEFINED)
{
myProps[j].pindx = mVec.size();
myProps[j].pcode = Property::MATERIAL;
}
if (code > 0)
mVec.push_back(IsoMat(E,nu,rho));
}
if (!mVec.empty())
elp->setMaterial(mVec.front());
}
else if (!strncasecmp(keyWord,"CONSTANT_PRESSURE",17))
@@ -326,7 +328,7 @@ bool SIMLinEl3D::parse (char* keyWord, std::istream& is)
{
std::cout <<"\tMaterial for all patches: "
<< E <<" "<< nu <<" "<< rho << std::endl;
elp->setMaterial(E,nu,rho);
mVec.push_back(new LinIsotropic(E,nu,rho));
}
else
{
@@ -338,10 +340,11 @@ bool SIMLinEl3D::parse (char* keyWord, std::istream& is)
std::cout <<"\tMaterial for P"<< patch
<<": "<< E <<" "<< nu <<" "<< rho << std::endl;
myProps.push_back(Property(Property::MATERIAL,mVec.size(),pid,3));
mVec.push_back(IsoMat(E,nu,rho));
if (i == 0)
elp->setMaterial(E,nu,rho);
mVec.push_back(new LinIsotropic(E,nu,rho));
}
if (!mVec.empty())
elp->setMaterial(mVec.front());
}
}
@@ -398,7 +401,7 @@ bool SIMLinEl3D::initMaterial (size_t propInd)
if (propInd >= mVec.size()) propInd = mVec.size()-1;
elp->setMaterial(mVec[propInd].E,mVec[propInd].nu,mVec[propInd].rho);
elp->setMaterial(mVec[propInd]);
return true;
}

View File

@@ -17,6 +17,8 @@
#include "SIM3D.h"
#include "SIMenums.h"
class Material;
/*!
\brief Driver class for 3D isogeometric FEM analysis of elasticity problems.
@@ -27,27 +29,13 @@
class SIMLinEl3D : public SIM3D
{
//! \brief Struct for storage of physical material property parameters.
struct IsoMat
{
double E; //!< Young's modulus
double nu; //!< Poisson's ratio
double rho; //!< Mass density
//! \brief Default constructor.
IsoMat() { E = nu = rho = 0.0; }
//! \brief Constructor initializing a material instance.
IsoMat(double Emod, double Poiss, double D) : E(Emod), nu(Poiss), rho(D) {}
};
typedef std::vector<IsoMat> MaterialVec; //!< Vector of material data sets
public:
//! \brief Default constructor.
//! \param[in] checkRHS If \e true, ensure the model is in a right-hand system
//! \param[in] form Problem formulation option
SIMLinEl3D(bool checkRHS = false, int form = SIM::LINEAR);
//! \brief Empty destructor.
virtual ~SIMLinEl3D() {}
//! \brief The destructor frees the dynamically allocated material properties.
virtual ~SIMLinEl3D();
protected:
//! \brief Parses a data section from the input stream.
@@ -63,8 +51,8 @@ protected:
//! \param[in] propInd Physical property index
virtual bool initNeumann(size_t propInd);
private:
MaterialVec mVec; //!< Material data
protected:
std::vector<Material*> mVec; //!< Material data
};
#endif

View File

@@ -74,7 +74,7 @@ int main (int argc, char** argv)
bool vizRHS = false;
bool fixDup = false;
bool dumpASCII = false;
char twoD = false;
bool twoD = false;
char* infile = 0;
LinAlgInit linalg(argc,argv);
@@ -137,8 +137,10 @@ int main (int argc, char** argv)
vizRHS = true;
else if (!strcmp(argv[i],"-fixDup"))
fixDup = true;
else if (!strcmp(argv[i],"-2Dpstrain"))
twoD = SIMLinEl2D::planeStrain = true;
else if (!strncmp(argv[i],"-2D",3))
twoD = strcmp(argv[i],"-2Dpstrain") ? 1 : 2;
twoD = true;
else if (!strncmp(argv[i],"-lag",4))
SIMbase::discretization = SIMbase::Lagrange;
else if (!strncmp(argv[i],"-spec",5))
@@ -212,7 +214,7 @@ int main (int argc, char** argv)
// Read in model definitions and establish the FE data structures
SIMbase* model;
if (twoD)
model = new SIMLinEl2D(SIM::LINEAR,twoD==1);
model = new SIMLinEl2D();
else
model = new SIMLinEl3D(checkRHS);

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "Elasticity.h"
#include "MaterialBase.h"
#include "Utilities.h"
#include "ElmMats.h"
#include "ElmNorm.h"
@@ -21,18 +22,14 @@
#include "VTF.h"
Elasticity::Elasticity (unsigned short int n, bool ps) : nsd(n), planeStress(ps)
Elasticity::Elasticity (unsigned short int n) : nsd(n)
{
// Default material properties - typical values for steel (SI units)
Emod = 2.05e11;
nu = 0.29;
rho = 7.85e3;
// Default is zero gravity
g[0] = g[1] = g[2] = 0.0;
grav[0] = grav[1] = grav[2] = 0.0;
myMats = new ElmMats();
material = 0;
locSys = 0;
tracFld = 0;
bodyFld = 0;
@@ -50,14 +47,11 @@ Elasticity::~Elasticity ()
void Elasticity::print (std::ostream& os) const
{
std::cout <<"Elasticity: "<< nsd <<"D";
if (nsd == 2)
std::cout <<" plane "<< (planeStress ? "stress" : "strain");
std::cout <<", E = "<< Emod <<", nu = "<< nu <<", rho = "<< rho
<<", gravity =";
std::cout <<"Elasticity: "<< nsd <<"D, gravity =";
for (unsigned short int d = 0; d < nsd; d++)
std::cout <<" "<< g[d];
std::cout <<" "<< grav[d];
std::cout << std::endl;
if (material) material->print(os);
}
@@ -162,6 +156,10 @@ bool Elasticity::initElement (const std::vector<int>& MNPC)
std::cerr <<" *** Elasticity::initElement: Detected "
<< ierr <<" node numbers out of range."<< std::endl;
int j = 1+myMats->b.size()-primsol.size();
for (size_t i = 1; i < primsol.size() && ierr == 0; i++, j++)
ierr = utl::gather(MNPC,nsd,primsol[j],myMats->b[j]);
if (myMats)
myMats->withLHS = true;
@@ -199,8 +197,8 @@ Vec3 Elasticity::getTraction (const Vec3& X, const Vec3& n) const
Vec3 Elasticity::getBodyforce (const Vec3& X) const
{
Vec3 f(g[0],g[1],g[2]);
f *= this->getMassDensity(X);
Vec3 f(grav[0],grav[1],grav[2]);
f *= material->getMassDensity(X);
if (bodyFld)
f += (*bodyFld)(X);
@@ -214,10 +212,10 @@ bool Elasticity::haveLoads () const
if (tracFld) return true;
if (bodyFld) return true;
if (rho != 0.0)
for (unsigned short int i = 0; i < nsd; i++)
if (g[i] != 0.0)
return true;
for (unsigned short int i = 0; i < nsd; i++)
if (grav[i] != 0.0)
if (material)
return material->getMassDensity(Vec3()) != 0.0;
return false;
}
@@ -259,7 +257,7 @@ bool Elasticity::writeGlvT (VTF* vtf, int iStep, int& nBlock) const
[\a N ] is the element basis functions arranged in a [nsd][nsd*NENOD] matrix.
*/
bool Elasticity::kinematics (const Matrix& dNdX, SymmTensor& eps) const
bool Elasticity::kinematics (const Matrix& dNdX, Tensor&, SymmTensor& eps) const
{
const size_t nenod = dNdX.rows();
const size_t nstrc = nsd*(nsd+1)/2;
@@ -348,115 +346,7 @@ bool Elasticity::kinematics (const Matrix& dNdX, SymmTensor& eps) const
bool Elasticity::formBmatrix (const Matrix& dNdX) const
{
static SymmTensor dummy(0);
return this->Elasticity::kinematics(dNdX,dummy);
}
/*!
The consitutive matrix for Isotrophic linear elastic problems
is defined as follows:
For 2D plain stress: \f[
[C] = \frac{E}{(1-\nu^2)} \left[\begin{array}{ccc}
1 & \ \ \nu & 0 \\
\nu & \ \ 1 & 0 \\
0 & \ \ 0 & \frac{1}{2}(1-\nu)
\end{array}\right] \f]
For 2D plain strain: \f[
[C] = \frac{E}{(1+\nu)(1-2\nu)} \left[\begin{array}{ccc}
1-\nu & \nu & 0 \\
\nu & 1-\nu & 0 \\
0 & 0 & \frac{1}{2}-\nu
\end{array}\right] \f]
For 3D: \f[
[C] = \frac{E}{(1+\nu)(1-2\nu)} \left[\begin{array}{cccccc}
1-\nu & \nu & \nu & 0 & 0 & 0 \\
\nu & 1-\nu & \nu & 0 & 0 & 0 \\
\nu & \nu & 1-\nu & 0 & 0 & 0 \\
0 & 0 & 0 & \frac{1}{2}-\nu & 0 & 0 \\
0 & 0 & 0 & 0 & \frac{1}{2}-\nu & 0 \\
0 & 0 & 0 & 0 & 0 & \frac{1}{2}-\nu
\end{array}\right] \f]
*/
bool Elasticity::formCmatrix (Matrix& C, const Vec3&, bool invers) const
{
const double one = 1.0;
const size_t nst = nsd*(nsd+1)/2;
C.resize(nst,nst,true);
if (nsd == 1)
{
// Special for 1D problems
C(1,1) = invers ? one/Emod : Emod;
return true;
}
else if (nu < 0.0 || nu >= 0.5)
{
std::cerr <<" *** Elasticity::formCmatrix: Poisson's ratio "<< nu
<<" out of range [0,0.5>."<< std::endl;
return false;
}
if (invers)
if (nsd == 3 || (nsd == 2 && planeStress))
{
C(1,1) = one / Emod;
C(2,1) = -nu / Emod;
}
else // 2D plain strain
{
C(1,1) = (one - nu*nu) / Emod;
C(2,1) = (-nu - nu*nu) / Emod;
}
else
if (nsd == 2 && planeStress)
{
C(1,1) = Emod / (one - nu*nu);
C(2,1) = C(1,1) * nu;
}
else // 2D plain strain or 3D
{
double fact = Emod / ((one + nu) * (one - nu - nu));
C(1,1) = fact * (one - nu);
C(2,1) = fact * nu;
}
C(1,2) = C(2,1);
C(2,2) = C(1,1);
const double G = Emod / (2.0 + nu + nu);
C(nsd+1,nsd+1) = invers ? one / G : G;
if (nsd > 2)
{
C(3,1) = C(2,1);
C(3,2) = C(2,1);
C(1,3) = C(2,1);
C(2,3) = C(2,1);
C(3,3) = C(1,1);
C(5,5) = C(4,4);
C(6,6) = C(4,4);
}
return true;
}
bool Elasticity::constitutive (Matrix& C, SymmTensor& sigma, double&,
const SymmTensor& eps, const Vec3& X,
char calcStress) const
{
// Set up the constitutive matrix, C, at this point
if (!this->formCmatrix(C,X))
return false;
else if (!calcStress)
return true;
// Calculate the stress vector, sigma = C*eps
return C.multiply(eps,sigma);
return this->Elasticity::kinematics(dNdX,dummy,dummy);
}
@@ -493,7 +383,7 @@ void Elasticity::formKG (Matrix& EM, const Matrix& dNdX,
void Elasticity::formMassMatrix (Matrix& EM, const Vector& N,
const Vec3& X, double detJW) const
{
double rhow = this->getMassDensity(X)*detJW;
double rhow = material->getMassDensity(X)*detJW;
if (rhow == 0.0) return;
for (size_t a = 1; a <= N.size(); a++)
@@ -527,6 +417,13 @@ Vec3 Elasticity::evalSol (const Vector& N) const
}
bool Elasticity::formCinverse (Matrix& Cinv, const Vec3& X) const
{
SymmTensor dummy(nsd); double U;
return material->evaluate(Cinv,dummy,U,X,dummy,dummy,-1);
}
bool Elasticity::evalSol (Vector& s, const Vector&,
const Matrix& dNdX, const Vec3& X,
const std::vector<int>& MNPC) const
@@ -540,14 +437,15 @@ bool Elasticity::evalSol (Vector& s, const Vector&,
return false;
}
// Evaluate the strain tensor, eps
// Evaluate the deformation gradient, dUdX, and/or the strain tensor, eps
Tensor dUdX(nsd);
SymmTensor eps(nsd);
if (!this->kinematics(dNdX,eps))
if (!this->kinematics(dNdX,dUdX,eps))
return false;
// Calculate the stress tensor through the constitutive relation
SymmTensor sigma(nsd); double U = 0.0;
if (!this->constitutive(Cmat,sigma,U,eps,X))
SymmTensor sigma(nsd); double U;
if (!material->evaluate(Cmat,sigma,U,X,dUdX,eps))
return false;
// Congruence transformation to local coordinate system at current point
@@ -575,14 +473,15 @@ bool Elasticity::evalSol (Vector& s, const Matrix& dNdX, const Vec3& X) const
return false;
}
// Evaluate the strain tensor, eps
// Evaluate the deformation gradient, dUdX, and/or the strain tensor, eps
Tensor dUdX(nsd);
SymmTensor eps(nsd);
if (!this->kinematics(dNdX,eps))
if (!this->kinematics(dNdX,dUdX,eps))
return false;
// Calculate the stress tensor through the constitutive relation
SymmTensor sigma(nsd); double U = 0.0;
if (!this->constitutive(Cmat,sigma,U,eps,X))
SymmTensor sigma(nsd); double U;
if (!material->evaluate(Cmat,sigma,U,X,dUdX,eps))
return false;
s = sigma;
@@ -613,7 +512,7 @@ const char* Elasticity::getFieldLabel (size_t i, const char* prefix) const
static std::string label;
if (prefix)
label = prefix + std::string(" ");
label = std::string(prefix) + " ";
else
label.clear();
@@ -678,7 +577,7 @@ bool ElasticityNorm::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the inverse constitutive matrix at this point
Matrix Cinv;
if (!problem.formCmatrix(Cinv,X,true)) return false;
if (!problem.formCinverse(Cinv,X)) return false;
// Evaluate the finite element stress field
Vector sigmah, sigma;

View File

@@ -19,6 +19,7 @@
#include <map>
class LocalSystem;
class Material;
class ElmMats;
class ElmNorm;
class VTF;
@@ -36,8 +37,7 @@ class Elasticity : public Integrand
protected:
//! \brief The default constructor initializes all pointers to zero.
//! \param[in] n Number of spatial dimensions
//! \param[in] ps If \e true, assume plane stress in 2D
Elasticity(unsigned short int n = 3, bool ps = true);
Elasticity(unsigned short int n = 3);
public:
//! \brief The destructor frees the dynamically allocated data objects.
@@ -57,17 +57,13 @@ public:
//! \brief Defines the gravitation vector.
void setGravity(double gx, double gy = 0.0, double gz = 0.0)
{ g[0] = gx; g[1] = gy; g[2] = gz; }
{ grav[0] = gx; grav[1] = gy; grav[2] = gz; }
//! \brief Defines the body force field.
void setBodyForce(VecFunc* bf) { bodyFld = bf; }
//! \brief Defines material properties for current volume patch.
//! \param[in] Young Young's modulus
//! \param[in] Poiss Poisson's ratio
//! \param[in] Density Mass density
virtual void setMaterial(double Young, double Poiss, double Density)
{ Emod = Young; nu = Poiss; rho = Density; }
//! \brief Defines the material properties.
virtual void setMaterial(Material* mat) { material = mat; }
//! \brief Defines the local coordinate system for stress output.
void setLocalSystem(LocalSystem* cs) { locSys = cs; }
@@ -138,27 +134,13 @@ public:
virtual const char* getFieldLabel(size_t i, const char* prefix = 0) const;
protected:
//! \brief Evaluates the mass density at current point.
virtual double getMassDensity(const Vec3&) const { return rho; }
//! \brief Calculates some kinematic quantities at current point.
//! \param[in] dNdX Basis function gradients at current point
//! \param[out] eps Strain tensor at current point
//!
//! \details The strain displacement matrix \b B is established
//! and stored in the mutable class member \a Bmat.
virtual bool kinematics(const Matrix& dNdX, SymmTensor& eps) const;
//! \brief Evaluates the constitutive relation at current point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density
//! \param[in] eps Strain tensor at current point
//! \param[in] X Cartesian coordinates of current point
//! \param[in] calcStress If \e false, claculate the C-matrix only
virtual bool constitutive(Matrix& C, SymmTensor& sigma, double& U,
const SymmTensor& eps, const Vec3& X,
char calcStress = true) const;
virtual bool kinematics(const Matrix& dNdX, Tensor&, SymmTensor& eps) const;
//! \brief Calculates integration point geometric stiffness contributions.
//! \param EM Element matrix to receive the stiffness contributions
@@ -194,19 +176,11 @@ protected:
bool getIntegralResult(LocalIntegral*& elmInt) const;
public:
//! \brief Sets up the tangential constitutive matrix at current point.
//! \param[out] C \f$6\times6\f$-matrix (in 3D) or \f$3\times3\f$-matrix
//! (in 2D), representing the constitutive tensor
//! \brief Sets up the inverse constitutive matrix at current point.
//! \param[out] Cinv \f$6\times6\f$-matrix (in 3D) or \f$3\times3\f$-matrix
//! (in 2D), representing the inverse constitutive tensor
//! \param[in] X Cartesian coordinates of current point
//! \param[in] invers If \e true, set up the inverse matrix instead
virtual bool formCmatrix(Matrix& C, const Vec3& X, bool invers = false) const;
private:
// Physical properties (constant)
double Emod; //!< Young's modulus
double nu; //!< Poisson's ratio
double rho; //!< Mass density
double g[3]; //!< Gravitation vector
bool formCinverse(Matrix& Cinv, const Vec3& X) const;
protected:
// Finite element quantities
@@ -219,6 +193,10 @@ protected:
ElmMats* myMats; //!< Local element matrices, result of numerical integration
// Physical properties
Material* material; //!< Material data and constitutive relation
double grav[3]; //!< Gravitation vector
LocalSystem* locSys; //!< Local coordinate system for result output
TractionFunc* tracFld; //!< Pointer to boundary traction field
VecFunc* bodyFld; //!< Pointer to body force field
@@ -226,7 +204,6 @@ protected:
mutable std::map<Vec3,Vec3> tracVal; //!< Traction field point values
unsigned short int nsd; //!< Number of space dimensions (1, 2 or, 3)
bool planeStress; //!< Plane stress/strain option for 2D problems
// Work arrays declared as members to avoid frequent re-allocation
// within the numerical integration loop (for reduced overhead)

View File

@@ -0,0 +1,141 @@
// $Id$
//==============================================================================
//!
//! \file LinIsotropic.C
//!
//! \date Mar 01 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Isotropic linear elastic material model.
//!
//==============================================================================
#include "LinIsotropic.h"
#include "Tensor.h"
LinIsotropic::LinIsotropic (bool ps) : planeStress(ps)
{
// Default material properties - typical values for steel (SI units)
Emod = 2.05e11;
nu = 0.29;
rho = 7.85e3;
}
void LinIsotropic::print (std::ostream& os) const
{
std::cout <<"LinIsotropic: ";
if (planeStress)
std::cout <<"plane stress, ";
std::cout <<"E = "<< Emod <<", nu = "<< nu <<", rho = "<< rho << std::endl;
}
/*!
The consitutive matrix for Isotropic linear elastic problems
is defined as follows:
For 2D plain stress: \f[
[C] = \frac{E}{(1-\nu^2)} \left[\begin{array}{ccc}
1 & \ \ \nu & 0 \\
\nu & \ \ 1 & 0 \\
0 & \ \ 0 & \frac{1}{2}(1-\nu)
\end{array}\right] \f]
For 2D plain strain: \f[
[C] = \frac{E}{(1+\nu)(1-2\nu)} \left[\begin{array}{ccc}
1-\nu & \nu & 0 \\
\nu & 1-\nu & 0 \\
0 & 0 & \frac{1}{2}-\nu
\end{array}\right] \f]
For 3D: \f[
[C] = \frac{E}{(1+\nu)(1-2\nu)} \left[\begin{array}{cccccc}
1-\nu & \nu & \nu & 0 & 0 & 0 \\
\nu & 1-\nu & \nu & 0 & 0 & 0 \\
\nu & \nu & 1-\nu & 0 & 0 & 0 \\
0 & 0 & 0 & \frac{1}{2}-\nu & 0 & 0 \\
0 & 0 & 0 & 0 & \frac{1}{2}-\nu & 0 \\
0 & 0 & 0 & 0 & 0 & \frac{1}{2}-\nu
\end{array}\right] \f]
*/
bool LinIsotropic::evaluate (Matrix& C, SymmTensor& sigma, double& U,
const Vec3&, const Tensor&, const SymmTensor& eps,
char iop, const TimeDomain*) const
{
const size_t nsd = eps.dim();
const size_t nst = nsd*(nsd+1)/2;
C.resize(nst,nst,true);
if (nsd == 1)
{
// Special for 1D problems
C(1,1) = iop < 0 ? 1.0/Emod : Emod;
if (iop > 0)
{
sigma = eps; sigma *= Emod;
U = 0.5*sigma(1,1)*eps(1,1);
}
return true;
}
else if (nu < 0.0 || nu >= 0.5)
{
std::cerr <<" *** LinIsotropic::evaluate: Poisson's ratio "<< nu
<<" out of range [0,0.5>."<< std::endl;
return false;
}
if (iop < 0) // The inverse C-matrix is wanted
if (nsd == 3 || (nsd == 2 && planeStress))
{
C(1,1) = 1.0 / Emod;
C(2,1) = -nu / Emod;
}
else // 2D plain strain
{
C(1,1) = (1.0 - nu*nu) / Emod;
C(2,1) = (-nu - nu*nu) / Emod;
}
else
if (nsd == 2 && planeStress)
{
C(1,1) = Emod / (1.0 - nu*nu);
C(2,1) = C(1,1) * nu;
}
else // 2D plain strain or 3D
{
double fact = Emod / ((1.0 + nu) * (1.0 - nu - nu));
C(1,1) = fact * (1.0 - nu);
C(2,1) = fact * nu;
}
C(1,2) = C(2,1);
C(2,2) = C(1,1);
const double G = Emod / (2.0 + nu + nu);
C(nsd+1,nsd+1) = iop < 0 ? 1.0 / G : G;
if (nsd > 2)
{
C(3,1) = C(2,1);
C(3,2) = C(2,1);
C(1,3) = C(2,1);
C(2,3) = C(2,1);
C(3,3) = C(1,1);
C(5,5) = C(4,4);
C(6,6) = C(4,4);
}
if (iop > 0)
// Calculate the stress tensor, sigma = C*eps, and strain energy density, U
if (C.multiply(eps,sigma))
U = 0.5*sigma.innerProd(eps); // U = 0.5*sigma:eps
else
return false;
return true;
}

View File

@@ -0,0 +1,63 @@
// $Id$
//==============================================================================
//!
//! \file LinIsotropic.h
//!
//! \date Mar 01 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Isotropic linear elastic material model.
//!
//==============================================================================
#ifndef _LIN_ISOTROPIC_H
#define _LIN_ISOTROPIC_H
#include "MaterialBase.h"
/*!
\brief Class representing a isotropic linear elastic material model.
*/
class LinIsotropic : public Material
{
public:
//! \brief Default constructor.
//! \param[in] ps If \e true, assume plane stress in 2D
LinIsotropic(bool ps = false);
//! \brief Constructor initializing the material parameters.
LinIsotropic(double E, double v = 0.0, double density = 0.0, bool ps = false)
: Emod(E), nu(v), rho(density), planeStress(ps) {}
//! \brief Empty destructor.
virtual ~LinIsotropic() {}
//! \brief Prints out material parameters to the given output stream.
virtual void print(std::ostream&) const;
//! \brief Evaluates the mass density at current point.
virtual double getMassDensity(const Vec3&) const { return rho; }
//! \brief Evaluates the constitutive relation at an integration point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density at current point
//! \param[in] eps Strain tensor at current point
//! \param[in] iop Calculation option;
//! -1 : Calculate the inverse constitutive matrix only,
//! 0 : Calculate the constitutive matrix only,
//! 1 : Calculate Cauchy stresses and the constitutive matrix.
virtual bool evaluate(Matrix& C, SymmTensor& sigma, double& U,
const Vec3&, const Tensor&, const SymmTensor& eps,
char iop = 1, const TimeDomain* = 0) const;
protected:
// Material properties (constant)
double Emod; //!< Young's modulus
double nu; //!< Poisson's ratio
double rho; //!< Mass density
bool planeStress; //!< Plane stress/strain option for 2D problems
};
#endif

View File

@@ -12,12 +12,12 @@
//==============================================================================
#include "LinearElasticity.h"
#include "MaterialBase.h"
#include "Tensor.h"
#include "Vec3Oper.h"
LinearElasticity::LinearElasticity (unsigned short int n, bool ps)
: Elasticity(n,ps)
LinearElasticity::LinearElasticity (unsigned short int n) : Elasticity(n)
{
// Only the current solution is needed
primsol.resize(1);
@@ -29,17 +29,19 @@ bool LinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
const Vec3& X) const
{
bool lHaveStrains = false;
SymmTensor eps(nsd), sigma(nsd);
SymmTensor eps(nsd);
if (eKm || eKg || iS)
{
// Compute the strain-displacement matrix B from dNdX
// and evaluate the symmetric strain tensor if displacements are available
if (!this->kinematics(dNdX,eps)) return false;
if (!this->kinematics(dNdX,eps,sigma)) return false;
if (!eps.isZero(1.0e-16)) lHaveStrains = true;
// Evaluate the constitutive matrix at this point
if (!this->formCmatrix(Cmat,X)) return false;
// Evaluate the constitutive matrix and the stress tensor at this point
double U;
if (!material->evaluate(Cmat,sigma,U,X,eps,eps))
return false;
}
if (eKm)
@@ -49,11 +51,6 @@ bool LinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
}
SymmTensor sigma(nsd);
if ((eKg || iS) && lHaveStrains)
// Evaluate the symmetric stress tensor
Cmat.multiply(eps,sigma); // sigma = C*eps
if (eKg && lHaveStrains)
// Integrate the geometric stiffness matrix
this->formKG(*eKg,dNdX,sigma,detJW);

View File

@@ -19,17 +19,14 @@
/*!
\brief Class representing the integrand of the linear elasticity problem.
\details This class supports constant isotrophic material properties only.
Properties with spatial variation has to be implemented as sub-classes.
*/
class LinearElasticity : public Elasticity
{
public:
//! \brief The default constructor initializes all pointers to zero.
//! \brief Default constructor.
//! \param[in] n Number of spatial dimensions
//! \param[in] ps If \e true, assume plane stress in 2D
LinearElasticity(unsigned short int n = 3, bool ps = true);
LinearElasticity(unsigned short int n = 3);
//! \brief Empty destructor.
virtual ~LinearElasticity() {}

View File

@@ -0,0 +1,63 @@
// $Id$
//==============================================================================
//!
//! \file MaterialBase.h
//!
//! \date Mar 01 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Base class for material models.
//!
//==============================================================================
#ifndef _MATERIAL_BASE_H
#define _MATERIAL_BASE_H
#include "MatVec.h"
class Vec3;
class Tensor;
class SymmTensor;
struct TimeDomain;
/*!
\brief Base class representing a material model of a PDE problem.
*/
class Material
{
protected:
//! \brief The default constructor is protected to allow sub-classes only.
Material() {}
public:
//! \brief Empty destructor.
virtual ~Material() {}
//! \brief Prints out material parameters to the given output stream.
virtual void print(std::ostream&) const {}
//! \brief Evaluates the mass density at current point.
virtual double getMassDensity(const Vec3&) const { return 0.0; }
//! \brief Evaluates the constitutive relation at an integration point.
//! \param[out] C Constitutive matrix at current point
//! \param[out] sigma Stress tensor at current point
//! \param[out] U Strain energy density at current point
//! \param[in] X Cartesian coordinates of current point
//! \param[in] F Deformation gradient at current point
//! \param[in] eps Strain tensor at current point
//! \param[in] iop Calculation option;
//! -1 : Calculate the inverse constitutive matrix only,
//! 0 : Calculate the consitutive matrix only,
//! 1 : Cauchy stresses and the tangent constitutive matrix,
//! 2 : 2nd Piola-Kirchhoff stresses and the tangent constitutive matrix.
//! \param[in] prm Nonlinear solution algorithm parameters
virtual bool evaluate(Matrix& C, SymmTensor& sigma, double& U,
const Vec3& X, const Tensor& F, const SymmTensor& eps,
char iop = 1, const TimeDomain* prm = 0) const = 0;
};
#endif

View File

@@ -255,7 +255,7 @@ const char* Poisson::getFieldLabel (size_t i, const char* prefix) const
static std::string label;
if (prefix)
label = prefix + std::string(" ");
label = std::string(prefix) + " ";
else
label.clear();