git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@863 e10b68d5-8a6e-419e-a041-bce267b0401d
248 lines
6.6 KiB
C
248 lines
6.6 KiB
C
// $Id$
|
|
//==============================================================================
|
|
//!
|
|
//! \file NonlinearElasticity.C
|
|
//!
|
|
//! \date May 25 2010
|
|
//!
|
|
//! \author Knut Morten Okstad / SINTEF
|
|
//!
|
|
//! \brief Integrand implementations for nonlinear elasticity problems.
|
|
//!
|
|
//==============================================================================
|
|
|
|
#include "NonlinearElasticity.h"
|
|
#include "MaterialBase.h"
|
|
#include "Utilities.h"
|
|
#include "Profiler.h"
|
|
|
|
#ifndef NO_FORTRAN
|
|
#if defined(_WIN32)
|
|
#define stiff_tl2d_ STIFF_TL2D
|
|
#define stiff_tl3d_ STIFF_TL3D
|
|
#define stiff_tl3d_isoel_ STIFF_TL3D_ISOEL
|
|
#define stiff_tl3d_isoel_ STIFF_TL3D_ISOEL
|
|
#elif defined(_AIX)
|
|
#define stiff_tl2d_ stiff_tl2d
|
|
#define stiff_tl3d_ stiff_tl3d
|
|
#define stiff_tl2d_isoel_ stiff_tl2d_isoel
|
|
#define stiff_tl3d_isoel_ stiff_tl3d_isoel
|
|
#endif
|
|
|
|
extern "C" {
|
|
//! \brief Calculates material stiffness contributions for 2D problems.
|
|
void stiff_tl2d_(const int& nenod, const double& detJW,
|
|
const double* dNdX, const double* F, const double* Cmat,
|
|
double* EM);
|
|
//! \brief Calculates material stiffness contributions for 3D problems.
|
|
void stiff_tl3d_(const int& nenod, const double& detJW,
|
|
const double* dNdX, const double* F, const double* Cmat,
|
|
double* EM);
|
|
//! \brief Optimized for isotropic linear elastic materials in 2D.
|
|
void stiff_tl2d_isoel_(const int& nenod, const double& detJW,
|
|
const double* dNdX, const double* F,
|
|
const double& C1, const double& C2,const double& C3,
|
|
double* EM);
|
|
//! \brief Optimized for isotropic linear elastic materials in 3D.
|
|
void stiff_tl3d_isoel_(const int& nenod, const double& detJW,
|
|
const double* dNdX, const double* F,
|
|
const double& C1, const double& C2,const double& C3,
|
|
double* EM);
|
|
}
|
|
#endif
|
|
|
|
|
|
NonlinearElasticity::NonlinearElasticity (unsigned short int n)
|
|
: NonlinearElasticityTL(n), E(n)
|
|
{
|
|
fullCmat = false;
|
|
}
|
|
|
|
|
|
void NonlinearElasticity::print (std::ostream& os) const
|
|
{
|
|
this->Elasticity::print(os);
|
|
std::cout <<"NonlinearElasticity: Total Lagrangian formulation "
|
|
<<" (tensorial form)"<< std::endl;
|
|
}
|
|
|
|
|
|
void NonlinearElasticity::setMode (SIM::SolutionMode mode)
|
|
{
|
|
this->NonlinearElasticityTL::setMode(mode);
|
|
formB = false; // We don't need the B-matrix in the tensor formulation
|
|
}
|
|
|
|
|
|
bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
|
|
const Vector& N, const Matrix& dNdX,
|
|
const Vec3& X) const
|
|
{
|
|
PROFILE3("NonlinearEl::evalInt");
|
|
|
|
// Evaluate the kinematic quantities, F and E, at this point
|
|
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
|
|
SymmTensor S(nsd);
|
|
if (!this->formTangent(Cmat,S,X,F))
|
|
return false;
|
|
|
|
bool haveStrains = !E.isZero(1.0e-16);
|
|
|
|
size_t a, b;
|
|
unsigned short int i, j, k;
|
|
|
|
if (eKm)
|
|
{
|
|
// Integrate the material stiffness matrix
|
|
#ifndef NO_FORTRAN
|
|
// Using Fortran routines optimized for symmetric constitutive tensors
|
|
PROFILE4("stiff_TL_");
|
|
if (nsd == 3)
|
|
if (fullCmat)
|
|
stiff_tl3d_(N.size(),detJW,dNdX.ptr(),F.ptr(),
|
|
Cmat.ptr(),eKm->ptr());
|
|
else
|
|
stiff_tl3d_isoel_(N.size(),detJW,dNdX.ptr(),F.ptr(),
|
|
Cmat(1,1),Cmat(1,2),Cmat(4,4),eKm->ptr());
|
|
else if (nsd == 2)
|
|
if (fullCmat)
|
|
stiff_tl2d_(N.size(),detJW,dNdX.ptr(),F.ptr(),
|
|
Cmat.ptr(),eKm->ptr());
|
|
else
|
|
stiff_tl2d_isoel_(N.size(),detJW,dNdX.ptr(),F.ptr(),
|
|
Cmat(1,1),Cmat(1,2),Cmat(3,3),eKm->ptr());
|
|
else if (nsd == 1)
|
|
for (a = 1; a <= N.size(); a++)
|
|
for (b = 1; b <= N.size(); b++)
|
|
(*eKm)(a,b) += dNdX(a,1)*F(1,1)*Cmat(1,1)*F(1,1)*dNdX(b,1);
|
|
#else
|
|
// This is too costly, but is basically what is done in the fortran routines
|
|
PROFILE4("dNdX^t*F^t*C*F*dNdX");
|
|
unsigned short int l, m, n;
|
|
SymmTensor4 D(Cmat,nsd); // fourth-order material tensor
|
|
Matrix& EM = *eKm;
|
|
for (a = 1; a <= N.size(); a++)
|
|
for (b = 1; b <= N.size(); b++)
|
|
for (m = 1; m <= nsd; m++)
|
|
for (n = 1; n <= nsd; n++)
|
|
{
|
|
double km = 0.0;
|
|
for (i = 1; i <= nsd; i++)
|
|
for (j = 1; j <= nsd; j++)
|
|
for (k = 1; k <= nsd; k++)
|
|
for (l = 1; l <= nsd; l++)
|
|
km += dNdX(a,i)*F(m,j)*D(i,j,k,l)*F(n,k)*dNdX(b,l);
|
|
|
|
EM(nsd*(a-1)+m,nsd*(b-1)+n) += km*detJW;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (eKg && haveStrains)
|
|
// Integrate the geometric stiffness matrix
|
|
this->formKG(*eKg,dNdX,S,detJW);
|
|
|
|
if (eM)
|
|
// Integrate the mass matrix
|
|
this->formMassMatrix(*eM,N,X,detJW);
|
|
|
|
if (iS && haveStrains)
|
|
{
|
|
// Integrate the internal forces
|
|
Vector& ES = *iS;
|
|
for (a = 1; a <= N.size(); a++)
|
|
for (k = 1; k <= nsd; k++)
|
|
{
|
|
double f = 0.0;
|
|
for (i = 1; i <= nsd; i++)
|
|
for (j = 1; j <= nsd; j++)
|
|
f -= dNdX(a,i)*F(k,j)*S(i,j);
|
|
ES(nsd*(a-1)+k) += f*detJW;
|
|
}
|
|
}
|
|
|
|
if (eS)
|
|
// Integrate the load vector due to gravitation and other body forces
|
|
this->formBodyForce(*eS,N,X,detJW);
|
|
|
|
return this->getIntegralResult(elmInt);
|
|
}
|
|
|
|
|
|
bool NonlinearElasticity::evalSol (Vector& s, const Vector&,
|
|
const Matrix& dNdX, const Vec3& X,
|
|
const std::vector<int>& MNPC) const
|
|
{
|
|
PROFILE3("NonlinearEl::evalSol");
|
|
|
|
int ierr = 0;
|
|
if (eV && !primsol.front().empty())
|
|
if ((ierr = utl::gather(MNPC,nsd,primsol.front(),*eV)))
|
|
{
|
|
std::cerr <<" *** NonlinearElasticity::evalSol: Detected "
|
|
<< ierr <<" node numbers out of range."<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
// Evaluate the stress state at this point
|
|
SymmTensor Sigma(nsd);
|
|
if (!this->formStressTensor(dNdX,X,Sigma))
|
|
return false;
|
|
|
|
// Congruence transformation to local coordinate system at current point
|
|
if (locSys) Sigma.transform(locSys->getTmat(X));
|
|
|
|
s = Sigma;
|
|
s.push_back(Sigma.vonMises());
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NonlinearElasticity::evalSol (Vector& s,
|
|
const Matrix& dNdX, const Vec3& X) const
|
|
{
|
|
PROFILE3("NonlinearEl::evalSol");
|
|
|
|
SymmTensor Sigma(nsd);
|
|
if (!this->formStressTensor(dNdX,X,Sigma))
|
|
return false;
|
|
|
|
s = Sigma;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NonlinearElasticity::formStressTensor (const Matrix& dNdX, const Vec3& X,
|
|
SymmTensor& S) const
|
|
{
|
|
if (!eV || eV->empty())
|
|
{
|
|
// Initial state (zero stresses)
|
|
S.zero();
|
|
return true;
|
|
}
|
|
|
|
// Evaluate the kinematic quantities, F and E, at this point
|
|
Tensor F(nsd);
|
|
if (!this->kinematics(dNdX,F,E))
|
|
return false;
|
|
|
|
// 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 Tensor& F) const
|
|
{
|
|
double U;
|
|
return material->evaluate(Ctan,S,U,X,F,E,!E.isZero());
|
|
}
|