Modified the ASM-Integrand interface by introducing the class FiniteElement (with subclass MxFiniteElement for mixed problems) incapsulating the various finite element quantities evaluated at the integration point. The number of evalInt interface are thereby also reduced, making the code (hopefully) more readable, etc.

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@880 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo
2011-03-29 17:27:23 +00:00
committed by Knut Morten Okstad
parent 087c8bce35
commit 1b4e69e5db
31 changed files with 755 additions and 789 deletions

View File

@@ -13,6 +13,7 @@
#include "NonlinearElasticity.h"
#include "MaterialBase.h"
#include "FiniteElement.h"
#include "Utilities.h"
#include "Profiler.h"
@@ -75,15 +76,15 @@ void NonlinearElasticity::setMode (SIM::SolutionMode mode)
}
bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt,
const FiniteElement& fe,
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))
if (!this->kinematics(fe.dNdX,F,E))
return false;
// Evaluate current tangent at this point, that is
@@ -106,30 +107,30 @@ bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
PROFILE4("stiff_TL_");
if (nsd == 3)
if (fullCmat)
stiff_tl3d_(N.size(),detJW,dNdX.ptr(),F.ptr(),
stiff_tl3d_(fe.N.size(),fe.detJxW,fe.dNdX.ptr(),F.ptr(),
Cmat.ptr(),eKm->ptr());
else
stiff_tl3d_isoel_(N.size(),detJW,dNdX.ptr(),F.ptr(),
stiff_tl3d_isoel_(fe.N.size(),fe.detJxW,fe.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(),
stiff_tl2d_(fe.N.size(),fe.detJxW,fe.dNdX.ptr(),F.ptr(),
Cmat.ptr(),eKm->ptr());
else
stiff_tl2d_isoel_(N.size(),detJW,dNdX.ptr(),F.ptr(),
stiff_tl2d_isoel_(fe.N.size(),fe.detJxW,fe.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);
for (a = 1; a <= fe.N.size(); a++)
for (b = 1; b <= fe.N.size(); b++)
(*eKm)(a,b) += fe.dNdX(a,1)*F(1,1)*Cmat(1,1)*F(1,1)*fe.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 (a = 1; a <= fe.N.size(); a++)
for (b = 1; b <= fe.N.size(); b++)
for (m = 1; m <= nsd; m++)
for (n = 1; n <= nsd; n++)
{
@@ -138,39 +139,39 @@ bool NonlinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
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);
km += fe.dNdX(a,i)*F(m,j)*D(i,j,k,l)*F(n,k)*fe.dNdX(b,l);
EM(nsd*(a-1)+m,nsd*(b-1)+n) += km*detJW;
EM(nsd*(a-1)+m,nsd*(b-1)+n) += km*fe.detJxW;
}
#endif
}
if (eKg && haveStrains)
// Integrate the geometric stiffness matrix
this->formKG(*eKg,dNdX,S,detJW);
this->formKG(*eKg,fe.dNdX,S,fe.detJxW);
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N,X,detJW);
this->formMassMatrix(*eM,fe.N,X,fe.detJxW);
if (iS && haveStrains)
{
// Integrate the internal forces
Vector& ES = *iS;
for (a = 1; a <= N.size(); a++)
for (a = 1; a <= fe.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;
f -= fe.dNdX(a,i)*F(k,j)*S(i,j);
ES(nsd*(a-1)+k) += f*fe.detJxW;
}
}
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,detJW);
this->formBodyForce(*eS,fe.N,X,fe.detJxW);
return this->getIntegralResult(elmInt);
}

View File

@@ -49,12 +49,9 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Evaluates the secondary solution at a result point.

View File

@@ -13,6 +13,7 @@
#include "NonlinearElasticity.h"
#include "MaterialBase.h"
#include "FiniteElement.h"
#include "ElmMats.h"
#include "Tensor.h"
#include "Vec3Oper.h"
@@ -82,15 +83,15 @@ void NonlinearElasticityTL::setMode (SIM::SolutionMode mode)
}
bool NonlinearElasticityTL::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool NonlinearElasticityTL::evalInt (LocalIntegral*& elmInt,
const FiniteElement& fe,
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
Tensor F(nsd);
SymmTensor E(nsd), S(nsd);
if (!this->kinematics(dNdX,F,E))
if (!this->kinematics(fe.dNdX,F,E))
return false;
// Evaluate the constitutive relation
@@ -105,36 +106,36 @@ bool NonlinearElasticityTL::evalInt (LocalIntegral*& elmInt, double detJW,
if (eKm)
{
// Integrate the material stiffness matrix
CB.multiply(Cmat,Bmat).multiply(detJW); // CB = C*B*|J|*w
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
CB.multiply(Cmat,Bmat).multiply(fe.detJxW); // CB = C*B*|J|*w
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
}
if (eKg && lHaveStrains)
// Integrate the geometric stiffness matrix
this->formKG(*eKg,dNdX,S,detJW);
this->formKG(*eKg,fe.dNdX,S,fe.detJxW);
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N,X,detJW);
this->formMassMatrix(*eM,fe.N,X,fe.detJxW);
if (iS && lHaveStrains)
{
// Integrate the internal forces
S *= -detJW;
S *= -fe.detJxW;
if (!Bmat.multiply(S,*iS,true,true)) // ES -= B^T*S
return false;
}
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,detJW);
this->formBodyForce(*eS,fe.N,X,fe.detJxW);
return this->getIntegralResult(elmInt);
}
bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt,
const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
if (!tracFld)
@@ -163,7 +164,7 @@ bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt, double detJW,
// Compute the deformation gradient, F
Tensor F(nsd);
SymmTensor dummy(0);
if (!this->kinematics(dNdX,F,dummy)) return false;
if (!this->kinematics(fe.dNdX,F,dummy)) return false;
// Compute its inverse and determinant, J
double J = F.inverse();
@@ -180,9 +181,9 @@ bool NonlinearElasticityTL::evalBou (LocalIntegral*& elmInt, double detJW,
// Integrate the force vector
Vector& ES = *eS;
for (size_t a = 1; a <= N.size(); a++)
for (size_t a = 1; a <= fe.N.size(); a++)
for (i = 1; i <= nsd; i++)
ES(nsd*(a-1)+i) += T[i-1]*N(a)*detJW;
ES(nsd*(a-1)+i) += T[i-1]*fe.N(a)*fe.detJxW;
return this->getIntegralResult(elmInt);
}

View File

@@ -44,26 +44,20 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
//!
//! \details This method is reimplemented in this class to account for
//! possibly with-rotated traction fields in the Total-Lagrangian setting.
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
protected:

View File

@@ -13,6 +13,7 @@
#include "NonlinearElasticityUL.h"
#include "MaterialBase.h"
#include "FiniteElement.h"
#include "ElmMats.h"
#include "ElmNorm.h"
#include "TimeDomain.h"
@@ -101,14 +102,14 @@ void NonlinearElasticityUL::initResultPoints ()
bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const FiniteElement& fe,
const TimeDomain& prm,
const Vec3& X) const
{
// Evaluate the deformation gradient, F, and the Green-Lagrange strains, E
Tensor F(nsd);
SymmTensor E(nsd);
if (!this->kinematics(dNdX,F,E))
if (!this->kinematics(fe.dNdX,F,E))
return false;
bool lHaveStrains = !E.isZero();
@@ -121,12 +122,12 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt,
if (J == 0.0) return false;
// Scale with J=|F| since we are integrating over current configuration
detJW *= J;
const_cast<double&>(fe.detJxW) *= J;
if (eKm || iS)
{
// Push-forward the basis function gradients to current configuration
dNdx.multiply(dNdX,Fi); // dNdx = dNdX * F^-1
dNdx.multiply(fe.dNdX,Fi); // dNdx = dNdX * F^-1
// Compute the small-deformation strain-displacement matrix B from dNdx
if (!this->formBmatrix(dNdx)) return false;
#ifdef INT_DEBUG
@@ -137,7 +138,7 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt,
}
else if (eKm || iS)
// Initial state, no deformation yet
if (!this->formBmatrix(dNdX)) return false;
if (!this->formBmatrix(fe.dNdX)) return false;
// Evaluate the constitutive relation
SymmTensor sigma(nsd);
@@ -151,36 +152,36 @@ bool NonlinearElasticityUL::evalInt (LocalIntegral*& elmInt,
if (eKm)
{
// Integrate the material stiffness matrix
CB.multiply(Cmat,Bmat).multiply(detJW); // CB = C*B*|J|*w
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
CB.multiply(Cmat,Bmat).multiply(fe.detJxW); // CB = C*B*|J|*w
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
}
if (eKg && lHaveStrains)
// Integrate the geometric stiffness matrix
this->formKG(*eKg,dNdx,sigma,detJW);
this->formKG(*eKg,dNdx,sigma,fe.detJxW);
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N,X,detJW);
this->formMassMatrix(*eM,fe.N,X,fe.detJxW);
if (iS && lHaveStrains)
{
// Integrate the internal forces
sigma *= -detJW;
sigma *= -fe.detJxW;
if (!Bmat.multiply(sigma,*iS,true,true)) // ES -= B^T*sigma
return false;
}
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,detJW);
this->formBodyForce(*eS,fe.N,X,fe.detJxW);
return this->getIntegralResult(elmInt);
}
bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt,
const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
if (!tracFld)
@@ -207,7 +208,7 @@ bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
{
// Compute the deformation gradient, F
Tensor F(nsd);
if (!this->formDefGradient(dNdX,F)) return false;
if (!this->formDefGradient(fe.dNdX,F)) return false;
// Check for with-rotated pressure load
if (tracFld->isNormalPressure())
@@ -226,14 +227,14 @@ bool NonlinearElasticityUL::evalBou (LocalIntegral*& elmInt, double detJW,
}
else
// Scale with J=|F| since we are integrating over current configuration
detJW *= F.det();
const_cast<double&>(fe.detJxW) *= F.det();
}
// Integrate the force vector
Vector& ES = *eS;
for (size_t a = 1; a <= N.size(); a++)
for (size_t a = 1; a <= fe.N.size(); a++)
for (i = 1; i <= nsd; i++)
ES(nsd*(a-1)+i) += T[i-1]*N(a)*detJW;
ES(nsd*(a-1)+i) += T[i-1]*fe.N(a)*fe.detJxW;
return this->getIntegralResult(elmInt);
}
@@ -323,8 +324,8 @@ void ElasticityNormUL::initIntegration (const TimeDomain& prm)
bool ElasticityNormUL::evalInt (LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector&, const Matrix& dNdX,
const FiniteElement& fe,
const TimeDomain& prm,
const Vec3& X) const
{
ElmNorm& pnorm = ElasticityNorm::getElmNormBuffer(elmInt);
@@ -332,9 +333,9 @@ bool ElasticityNormUL::evalInt (LocalIntegral*& elmInt,
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,F,E))
Tensor F(fe.dNdX.cols());
SymmTensor E(fe.dNdX.cols());
if (!ulp->kinematics(fe.dNdX,F,E))
return false;
// Evaluate the 2nd Piola Kirchhoff stresses, S
@@ -346,7 +347,24 @@ bool ElasticityNormUL::evalInt (LocalIntegral*& elmInt,
// Integrate the energy norm a(u^h,u^h) = Int_Omega0 (S:E) dV0
if (U == 0.0) U = S.innerProd(E);
pnorm[0] += U*detJW;
pnorm[0] += U*fe.detJxW;
return true;
}
bool ElasticityNormUL::evalIntMx (LocalIntegral*& elmInt,
const MxFiniteElement& fe,
const TimeDomain& prm,
const Vec3& X) const
{
return this->evalInt(elmInt,fe,prm,X);
}
bool ElasticityNormUL::evalBouMx (LocalIntegral*& elmInt,
const MxFiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
return this->evalBou(elmInt,fe,X,normal);
}

View File

@@ -51,21 +51,15 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const;
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
//!
@@ -73,8 +67,7 @@ public:
//! possibly with-rotated traction fields (non-conservative loads).
//! For uni-directional (conservative) loads, it is similar to the
//! \a LinearElasticity::evalBou method.
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
//! \brief Returns a pointer to an Integrand for solution norm evaluation.
@@ -144,45 +137,26 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const;
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Evaluates the integrand at an interior point (mixed).
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N1 Basis function values for the displacement field
//! \param[in] dN1dX Basis function gradients for the displacement field
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N1, const Vector&,
const Matrix& dN1dX, const Matrix&,
const Vec3& X) const
{
return this->evalInt(elmInt,prm,detJW,N1,dN1dX,X);
}
virtual bool evalIntMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point (mixed).
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N1 Basis function values for the displacement field
//! \param[in] dN1dX Basis function gradients for the displacement field
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N1, const Vector&,
const Matrix& dN1dX, const Matrix&,
const Vec3& X, const Vec3& normal) const
{
return this->ElasticityNorm::evalBou(elmInt,detJW,N1,dN1dX,X,normal);
}
virtual bool evalBouMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
};
#endif

View File

@@ -13,6 +13,7 @@
#include "NonlinearElasticityULMX.h"
#include "MaterialBase.h"
#include "FiniteElement.h"
#include "ElmMats.h"
#include "ElmNorm.h"
#include "TimeDomain.h"
@@ -140,26 +141,25 @@ bool NonlinearElasticityULMX::initElement (const std::vector<int>& MNPC,
bool NonlinearElasticityULMX::evalInt (LocalIntegral*& elmInt,
const TimeDomain&, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const
const FiniteElement& fe,
const TimeDomain&, const Vec3& X) const
{
if (myMats->b.size() < 3) return false;
ItgPtData& ptData = myData[iP++];
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityUL::dNdX ="<< dNdX;
std::cout <<"NonlinearElasticityUL::dNdX ="<< fe.dNdX;
#endif
// Evaluate the deformation gradient, Fp, at previous configuration
const_cast<NonlinearElasticityULMX*>(this)->eV = &myMats->b[2];
if (!this->formDefGradient(dNdX,ptData.Fp))
if (!this->formDefGradient(fe.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,ptData.F))
if (!this->formDefGradient(fe.dNdX,ptData.F))
return false;
if (nsd == 2) // In 2D we always assume plane strain so set F(3,3)=1
@@ -174,10 +174,10 @@ bool NonlinearElasticityULMX::evalInt (LocalIntegral*& elmInt,
if (J == 0.0) return false;
// Push-forward the basis function gradients to current configuration
ptData.dNdx.multiply(dNdX,Fi); // dNdx = dNdX * F^-1
ptData.dNdx.multiply(fe.dNdX,Fi); // dNdx = dNdX * F^-1
ptData.X.assign(X);
ptData.detJW = detJW;
ptData.detJW = fe.detJxW;
// Evaluate the pressure modes (generalized coordinates)
Vec3 Xg = X-X0;
@@ -190,15 +190,15 @@ bool NonlinearElasticityULMX::evalInt (LocalIntegral*& elmInt,
if (Hh)
// Integrate the Hh-matrix
Hh->outer_product(ptData.Phi,ptData.Phi*detJW,true);
Hh->outer_product(ptData.Phi,ptData.Phi*fe.detJxW,true);
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N,X,J*detJW);
this->formMassMatrix(*eM,fe.N,X,J*fe.detJxW);
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,J*detJW);
this->formBodyForce(*eS,fe.N,X,J*fe.detJxW);
return this->getIntegralResult(elmInt);
}
@@ -470,12 +470,10 @@ bool ElasticityNormULMX::initElement (const std::vector<int>& MNPC,
bool ElasticityNormULMX::evalInt (LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const
const FiniteElement& fe,
const TimeDomain& td, const Vec3& X) const
{
NonlinearElasticityULMX& elp = static_cast<NonlinearElasticityULMX&>(problem);
return elp.evalInt(elmInt,prm,detJW,N,dNdX,X);
return static_cast<NonlinearElasticityULMX&>(problem).evalInt(elmInt,fe,td,X);
}

View File

@@ -63,20 +63,16 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
//!
//! \details This method mainly stores the integration point quantities
//! depending on the basis function values in the internal member \a myData.
//! The actual numerical integration of the tangent stiffness and internal
//! forces is then performed by the \a finalizeElement method.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const;
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Finalizes the element matrices after the numerical integration.
//! \details This method is used to implement the multiple integration point
@@ -131,20 +127,16 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
//!
//! \details This method just forwards to the \a evalInt method of the
//! corresponding NonlinearElasticityULMX object, for which this class is
//! declared as friend such that it can access the data members. The actual
//! norm integration us then performed by the \a finalizeElement method.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const;
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Finalizes the element norms after the numerical integration.
//! \details This method is used to implement the multiple integration point

View File

@@ -13,6 +13,7 @@
#include "NonlinearElasticityULMixed.h"
#include "MaterialBase.h"
#include "FiniteElement.h"
#include "ElmMats.h"
#include "Utilities.h"
@@ -290,25 +291,22 @@ bool NonlinearElasticityULMixed::initElementBou (const std::vector<int>& MNPC1,
}
bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N1,
const Vector& N2,
const Matrix& dNdX1,
const Matrix& dNdX2,
const Vec3& X) const
bool NonlinearElasticityULMixed::evalIntMx (LocalIntegral*& elmInt,
const MxFiniteElement& fe,
const TimeDomain& prm,
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,F,E))
if (!this->kinematics(fe.dN1dX,F,E))
return false;
bool lHaveStrains = !E.isZero();
// Evaluate the volumetric change and pressure fields
double Theta = N2.dot(myMats->b[T]) + 1.0;
double Press = N2.dot(myMats->b[P]);
double Theta = fe.N2.dot(myMats->b[T]) + 1.0;
double Press = fe.N2.dot(myMats->b[P]);
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityULMixed::b_theta ="<< myMats->b[T];
std::cout <<"NonlinearElasticityULMixed::b_p ="<< myMats->b[P];
@@ -316,7 +314,7 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt,
#endif
// Compute the mixed integration point volume
double dVol = Theta*detJW;
double dVol = Theta*fe.detJxW;
// Compute the mixed model deformation gradient, F_bar
Fbar = F; // notice that F_bar always has dimension 3
@@ -335,20 +333,20 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt,
if (J == 0.0) return false;
// Push-forward the basis function gradients to current configuration
dNdx.multiply(dNdX1,Fi); // dNdx = dNdX * F^-1
dNdx.multiply(fe.dN1dX,Fi); // dNdx = dNdX * F^-1
#if INT_DEBUG > 0
std::cout <<"NonlinearElasticityULMixed::dNdX ="<< dNdX1;
std::cout <<"NonlinearElasticityULMixed::dNdX ="<< fe.dN1dX;
std::cout <<"NonlinearElasticityULMixed::dNdx ="<< dNdx;
std::cout <<"NonlinearElasticityULMixed::Fbar ="<< Fbar;
#endif
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N1,X,J*detJW);
this->formMassMatrix(*eM,fe.N1,X,J*fe.detJxW);
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N1,X,J*detJW);
this->formBodyForce(*eS,fe.N1,X,J*fe.detJxW);
// Evaluate the constitutive relation
SymmTensor Eps(3), Sig(3), Sigma(nsd);
@@ -384,34 +382,34 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt,
// Integrate the material stiffness matrix
Dmat *= dVol;
if (nsd == 2)
acckm2d_(N1.size(),dNdx.ptr(),Dmat.ptr(),eKm->ptr());
acckm2d_(fe.N1.size(),dNdx.ptr(),Dmat.ptr(),eKm->ptr());
else
acckm3d_(N1.size(),dNdx.ptr(),Dmat.ptr(),eKm->ptr());
acckm3d_(fe.N1.size(),dNdx.ptr(),Dmat.ptr(),eKm->ptr());
#endif
// Integrate the volumetric change and pressure tangent terms
size_t a, b;
unsigned short int i, j, k;
for (a = 1; a <= N1.size(); a++)
for (b = 1; b <= N2.size(); b++)
for (a = 1; a <= fe.N1.size(); a++)
for (b = 1; b <= fe.N2.size(); b++)
for (i = 1; i <= nsd; i++)
{
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,i)*N2(b) * Dmat(i,7);
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,i)*fe.N2(b) * Dmat(i,7);
if (nsd == 2)
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,3-i)*N2(b) * Dmat(4,7);
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,3-i)*fe.N2(b) * Dmat(4,7);
else if (i < 3)
{
j = i + 1;
k = j%3 + 1;
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,3-i)*N2(b) * Dmat(4,7);
myMats->A[Kut](nsd*(a-1)+j,b) += dNdx(a,5-j)*N2(b) * Dmat(5,7);
myMats->A[Kut](nsd*(a-1)+k,b) += dNdx(a,4-k)*N2(b) * Dmat(6,7);
myMats->A[Kut](nsd*(a-1)+i,b) += dNdx(a,3-i)*fe.N2(b) * Dmat(4,7);
myMats->A[Kut](nsd*(a-1)+j,b) += dNdx(a,5-j)*fe.N2(b) * Dmat(5,7);
myMats->A[Kut](nsd*(a-1)+k,b) += dNdx(a,4-k)*fe.N2(b) * Dmat(6,7);
}
myMats->A[Kup](nsd*(a-1)+i,b) += dNdx(a,i)*N2(b) * dVol;
myMats->A[Kup](nsd*(a-1)+i,b) += dNdx(a,i)*fe.N2(b) * dVol;
}
myMats->A[Ktt].outer_product(N2,N2*Dmat(7,7),true); // Ktt += N2*N2^T * D77
myMats->A[Ktp].outer_product(N2,N2*(-detJW),true); // Ktp -= N2*N2^T * detJW
myMats->A[Ktt].outer_product(fe.N2,fe.N2*Dmat(7,7),true); // += N2*N2^T*D77
myMats->A[Ktp].outer_product(fe.N2,fe.N2*(-fe.detJxW),true); // -= N2*N2^T*|J|
if (lHaveStrains)
{
@@ -420,13 +418,28 @@ bool NonlinearElasticityULMixed::evalInt (LocalIntegral*& elmInt,
// Integrate the internal forces
Sigma *= -dVol;
if (!Bmat.multiply(Sigma,myMats->b[Ru],true,true)) // Ru -= B^T * sigma
if (!Bmat.multiply(Sigma,myMats->b[Ru],true,true)) // -= B^T*sigma
return false;
// Integrate the volumetric change and pressure forces
myMats->b[Rt].add(N2,(Press - Bpres)*detJW); // Rt += N2 * (p-pBar)
myMats->b[Rp].add(N2,(Theta - J)*detJW); // Rp += N2 * (Theta-J)
myMats->b[Rt].add(fe.N2,(Press - Bpres)*fe.detJxW); // += N2*(p-pBar)*|J|
myMats->b[Rp].add(fe.N2,(Theta - J)*fe.detJxW); // += N2*(Theta-J)*|J|
}
return this->getIntegralResult(elmInt);
}
/*!
The boundary integral is the same as that of the parent class. It does not
depend on the pressure and volumetric change fields. Thus, this call is
forwarded to the corresponding single-field method of the parent class.
*/
bool NonlinearElasticityULMixed::evalBouMx (LocalIntegral*& elmInt,
const MxFiniteElement& fe,
const Vec3& X,
const Vec3& normal) const
{
return this->evalBou(elmInt,fe,X,normal);
}

View File

@@ -70,37 +70,19 @@ public:
//! \brief Evaluates the mixed field problem integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] prm Nonlinear solution algorithm parameters
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N1 Basis function values, field 1 (displacements)
//! \param[in] N2 Basis function values, field 2 (pressure and volume change)
//! \param[in] dN1dX Basis function gradients, field 1
//! \param[in] dN2dX Basis function gradients, field 2
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& prm, double detJW,
const Vector& N1, const Vector& N2,
const Matrix& dN1dX, const Matrix& dN2dX,
const Vec3& X) const;
virtual bool evalIntMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const TimeDomain& prm, const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N1 Basis function values, field 1
//! \param[in] dN1dX Basis function gradients, field 1
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
//!
//! \details The boundary integral is the same as that of the parent class.
//! It does not depend on the pressure and volumetric change fields.
//! Thus, this call is forwarded to the single-field parent class method.
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N1, const Vector&,
const Matrix& dN1dX, const Matrix&,
const Vec3& X, const Vec3& normal) const
{
return this->NonlinearElasticityUL::evalBou(elmInt,detJW,N1,dN1dX,X,normal);
}
virtual bool evalBouMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
protected:
mutable Tensor Fbar; //!< Mixed model deformation gradient

View File

@@ -16,6 +16,7 @@
#include "ASMs1D.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -467,22 +468,21 @@ bool ASMs1D::integrate (Integrand& integrand,
const int p1 = curv->order();
const int n1 = curv->numCoefs();
Vector gpar;
int pm1 = p1 - 1;
int nCol = n1 - pm1;
Matrix gpar(nGauss,nCol);
DoubleIter uit = curv->basis().begin() + pm1;
double ucurr, uprev = *(uit++);
int nCol = n1 - pm1;
gpar.reserve(nGauss*nCol);
for (int j = 1; j <= nCol; uit++, j++)
{
ucurr = *uit;
for (int i = 0; i < nGauss; i++)
gpar.push_back(0.5*((ucurr-uprev)*xg[i] + ucurr+uprev));
for (int i = 1; i <= nGauss; i++)
gpar(i,j) = 0.5*((ucurr-uprev)*xg[i-1] + ucurr+uprev);
uprev = ucurr;
}
Vector N;
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1);
Matrix dNdu, Xnod, Jac;
Vec4 X;
@@ -514,21 +514,22 @@ bool ASMs1D::integrate (Integrand& integrand,
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = 0.5*dL*wg[i];
// Parameter value of current integration point
fe.u = gpar(i+1,iel);
// Compute basis functions and derivatives
this->extractBasis(gpar((iel-1)*nGauss+i+1),N,dNdu);
this->extractBasis(fe.u,fe.N,dNdu);
// Compute derivatives in terms of physical co-ordinates
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,X))
fe.detJxW *= 0.5*dL*wg[i];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -584,16 +585,16 @@ bool ASMs1D::integrate (Integrand& integrand, int lIndex,
LocalIntegral* elmInt = locInt.empty() ? 0 : locInt[MLGE[iel-1]-1];
// Evaluate basis functions and corresponding derivatives
Vector N;
FiniteElement fe;
Matrix dNdu;
this->extractBasis(param,N,dNdu);
this->extractBasis(param,fe.N,dNdu);
// Cartesian coordinates of current integration point
Vec4 X(Xnod*N,time.t);
Vec4 X(Xnod*fe.N,time.t);
// Compute basis function derivatives
Matrix Jac, dNdX;
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
// Set up the normal vector
Vec3 normal;
@@ -603,7 +604,7 @@ bool ASMs1D::integrate (Integrand& integrand, int lIndex,
normal.x = copysign(1.0,Jac(1,1));
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,1.0,N,dNdX,X,normal))
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
// Assembly of global system integral
@@ -623,12 +624,14 @@ bool ASMs1D::getGridParameters (RealArray& prm, int nSegPerSpan) const
}
DoubleIter uit = curv->basis().begin();
double ucurr, uprev = *(uit++);
double ucurr = 0.0, uprev = *(uit++);
while (uit != curv->basis().end())
{
ucurr = *(uit++);
if (ucurr > uprev)
for (int i = 0; i < nSegPerSpan; i++)
if (nSegPerSpan == 1)
prm.push_back(uprev);
else for (int i = 0; i < nSegPerSpan; i++)
{
double xg = (double)(2*i-nSegPerSpan)/(double)nSegPerSpan;
prm.push_back(0.5*(ucurr*(1.0+xg) + uprev*(1.0-xg)));
@@ -636,7 +639,8 @@ bool ASMs1D::getGridParameters (RealArray& prm, int nSegPerSpan) const
uprev = ucurr;
}
prm.push_back(curv->basis().endparam());
if (ucurr > prm.back())
prm.push_back(ucurr);
return true;
}
@@ -732,7 +736,7 @@ bool ASMs1D::evalSolution (Matrix& sField, const Integrand& integrand,
if (npe)
{
// Compute parameter values of the result sampling points
DoubleVec gpar;
RealArray gpar;
if (this->getGridParameters(gpar,npe[0]-1))
// Evaluate the secondary solution at all sampling points
return this->evalSolution(sField,integrand,gpar);

View File

@@ -16,6 +16,7 @@
#include "ASMs1DLag.h"
#include "Lagrange.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -150,11 +151,15 @@ bool ASMs1DLag::integrate (Integrand& integrand,
const double* wg = GaussQuadrature::getWeight(nGauss);
if (!xg || !wg) return false;
// Get parametric coordinates of the elements
RealArray gpar;
this->getGridParameters(gpar,1);
// Order of basis (order = degree + 1)
const int p1 = curv->order();
Vector N(p1);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1);
Matrix dNdu, Xnod, Jac;
Vec4 X;
@@ -162,45 +167,48 @@ bool ASMs1DLag::integrate (Integrand& integrand,
const int nel = this->getNoElms();
for (int iel = 1; iel <= nel; iel++)
{
// Set up control point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
if (!integrand.initElement(MNPC[iel-1])) return false;
// Caution: Unless locInt is empty, we assume it points to an array of
// LocalIntegral pointers, of length at least the number of elements in
// the model (as defined by the highest number in the MLGE array).
// If the array is shorter than this, expect a segmentation fault.
LocalIntegral* elmInt = locInt.empty() ? 0 : locInt[MLGE[iel-1]-1];
// --- Integration loop over all Gauss points in each direction ------------
for (int i = 0; i < nGauss; i++)
{
// Set up control point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Parameter value of current integration point
fe.u = 0.5*(gpar[iel-1]*(1.0-xg[i]) + gpar[iel]*(1.0+xg[i]));
// Initialize element quantities
if (!integrand.initElement(MNPC[iel-1])) return false;
// Compute basis function derivatives at current integration point
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xg[i]))
return false;
// Caution: Unless locInt is empty, we assume it points to an array of
// LocalIntegral pointers, of length at least the number of elements in
// the model (as defined by the highest number in the MLGE array).
// If the array is shorter than this, expect a segmentation fault.
LocalIntegral* elmInt = locInt.empty() ? 0 : locInt[MLGE[iel-1]-1];
// Compute Jacobian inverse of coordinate mapping and derivatives
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu)*wg[i];
// Cartesian coordinates of current integration point
X = Xnod * fe.N;
X.t = time.t;
// --- Integration loop over all Gauss points in each direction ----------
for (int i = 0; i < nGauss; i++)
{
// Compute basis function derivatives at current integration point
if (!Lagrange::computeBasis(N,dNdu,p1,xg[i]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
// Cartesian coordinates of current integration point
X = Xnod * N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*wg[i],N,dNdX,X))
return false;
}
// Assembly of global system integral
if (!glInt.assemble(elmInt,MLGE[iel-1]))
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
// Assembly of global system integral
if (!glInt.assemble(elmInt,MLGE[iel-1]))
return false;
}
return true;
}
@@ -250,16 +258,15 @@ bool ASMs1DLag::integrate (Integrand& integrand, int lIndex,
LocalIntegral* elmInt = locInt.empty() ? 0 : locInt[MLGE[iel-1]-1];
// Evaluate basis functions and corresponding derivatives
Vector N;
Matrix dNdu;
if (!Lagrange::computeBasis(N,dNdu,p1,x)) return false;
FiniteElement fe;
Matrix dNdu, Jac;
if (!Lagrange::computeBasis(fe.N,dNdu,p1,x)) return false;
// Cartesian coordinates of current integration point
Vec4 X(Xnod*N,time.t);
Vec4 X(Xnod*fe.N,time.t);
// Compute basis function derivatives
Matrix Jac, dNdX;
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
// Set up the normal vector
Vec3 normal;
@@ -269,7 +276,7 @@ bool ASMs1DLag::integrate (Integrand& integrand, int lIndex,
normal.x = copysign(1.0,Jac(1,1));
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,1.0,N,dNdX,X,normal))
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
// Assembly of global system integral

View File

@@ -15,6 +15,7 @@
#include "ASMs1DSpec.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -83,8 +84,8 @@ bool ASMs1DSpec::integrate (Integrand& integrand,
if (!Legendre::GL(wg1,xg1,n1))
return false;
Vector N(p1);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1);
Matrix dNdu, Xnod, Jac;
Vec4 X;
@@ -110,29 +111,27 @@ bool ASMs1DSpec::integrate (Integrand& integrand,
for (int i = 0; i < n1; i++)
{
// Weight of current integration point
double weight = wg1[i];
// Compute basis function derivatives at current integration point
if (nGauss < 1)
{
N.fill(0.0);
N(i+1) = 1.0;
fe.N.fill(0.0);
fe.N(i+1) = 1.0;
dNdu.fillColumn(1,D1.getRow(i+1));
}
else
if (!Lagrange::computeBasis(N,dNdu,points1,xg1[i]))
if (!Lagrange::computeBasis(fe.N,dNdu,points1,xg1[i]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
// Cartesian coordinates of current integration point
X = Xnod*N;
X = Xnod*fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,X))
fe.detJxW *= wg1[i];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}

View File

@@ -17,6 +17,7 @@
#include "ASMs2D.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -819,10 +820,9 @@ bool ASMs2D::integrate (Integrand& integrand,
const int n2 = surf->numCoefs_v();
const int nel1 = n1 - p1 + 1;
Vector N(p1*p2), Navg;
Matrix dNdu, dNdX, Xnod, Jac;
Matrix3D d2Ndu2, d2NdX2, Hess;
double h = 0.0;
FiniteElement fe(p1*p2);
Matrix dNdu, Xnod, Jac;
Matrix3D d2Ndu2, Hess;
Vec4 X;
@@ -843,33 +843,33 @@ bool ASMs2D::integrate (Integrand& integrand,
// Compute characteristic element length, if needed
if (integrand.getIntegrandType() == 2)
h = getElmSize(p1,p2,Xnod);
fe.h = getElmSize(p1,p2,Xnod);
else if (integrand.getIntegrandType() == 3)
{
// --- Compute average value of basis functions over the element -------
Navg.resize(p1*p2,true);
fe.Navg.resize(p1*p2,true);
double area = 0.0;
int ip = ((i2-p2)*nGauss*nel1 + i1-p1)*nGauss;
for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Fetch basis function derivatives at current integration point
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute Jacobian determinant of coordinate mapping
// and multiply by weight of current integration point
double detJac = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu,false);
double weight = 0.25*dA*wg[i]*wg[j];
double detJxW = utl::Jacobian(Jac,dNdX,Xnod,dNdu,false)*weight;
// Numerical quadrature
Navg += N*detJxW;
area += detJxW;
fe.Navg.add(fe.N,detJac*weight);
area += detJac*weight;
}
// Divide by element area
Navg /= area;
fe.Navg /= area;
}
else if (integrand.getIntegrandType() == 4)
@@ -899,47 +899,38 @@ bool ASMs2D::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.25*dA*wg[i]*wg[j];
// Parameter values of current integration point
fe.u = gpar[0](i+1,i1-p1+1);
fe.v = gpar[1](j+1,i2-p2+1);
// Fetch basis function derivatives at current integration point
if (integrand.getIntegrandType() == 2)
extractBasis(spline2[ip],N,dNdu,d2Ndu2);
extractBasis(spline2[ip],fe.N,dNdu,d2Ndu2);
else
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (detJ == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Compute Hessian of coordinate mapping and 2nd order derivatives
if (integrand.getIntegrandType() == 2)
if (!utl::Hessian(Hess,d2NdX2,Jac,Xnod,d2Ndu2,dNdu))
if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xnod,d2Ndu2,dNdu))
return false;
#if SP_DEBUG > 4
std::cout <<"\niel, ip = "<< iel <<" "<< ip
<<"\nN ="<< N <<"dNdX ="<< dNdX << std::endl;
<<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX << std::endl;
#endif
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
bool ok = false;
switch (integrand.getIntegrandType())
{
case 2:
ok = integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,d2NdX2,X,h);
break;
case 3:
ok = integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,Navg,X);
break;
default:
ok = integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,X);
}
if (!ok) return false;
fe.detJxW *= 0.25*dA*wg[i]*wg[j];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
// Finalize the element quantities
@@ -1013,8 +1004,8 @@ bool ASMs2D::integrate (Integrand& integrand, int lIndex,
const int n1 = surf->numCoefs_u();
const int n2 = surf->numCoefs_v();
Vector N(p1*p2);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 normal;
@@ -1060,24 +1051,22 @@ bool ASMs2D::integrate (Integrand& integrand, int lIndex,
int ip = (abs(edgeDir) == 1 ? i2-p2 : i1-p1)*nGauss;
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.5*dS*wg[i];
// Fetch basis function derivatives at current integration point
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute basis function derivatives and the edge normal
double dT = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dT == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (edgeDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dT*weight,N,dNdX,X,normal))
fe.detJxW *= 0.5*dS*wg[i];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}
@@ -1102,12 +1091,14 @@ bool ASMs2D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
}
DoubleIter uit = surf->basis(dir).begin();
double ucurr, uprev = *(uit++);
double ucurr = 0.0, uprev = *(uit++);
while (uit != surf->basis(dir).end())
{
ucurr = *(uit++);
if (ucurr > uprev)
for (int i = 0; i < nSegPerSpan; i++)
if (nSegPerSpan == 1)
prm.push_back(uprev);
else for (int i = 0; i < nSegPerSpan; i++)
{
double xg = (double)(2*i-nSegPerSpan)/(double)nSegPerSpan;
prm.push_back(0.5*(ucurr*(1.0+xg) + uprev*(1.0-xg)));
@@ -1115,7 +1106,8 @@ bool ASMs2D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
uprev = ucurr;
}
prm.push_back(surf->basis(dir).endparam());
if (ucurr > prm.back())
prm.push_back(ucurr);
return true;
}
@@ -1236,7 +1228,7 @@ bool ASMs2D::evalSolution (Matrix& sField, const Integrand& integrand,
if (npe)
{
// Compute parameter values of the result sampling points
DoubleVec gpar[2];
RealArray gpar[2];
for (int dir = 0; dir < 2 && retVal; dir++)
retVal = this->getGridParameters(gpar[dir],dir,npe[dir]-1);

View File

@@ -16,6 +16,7 @@
#include "ASMs2DLag.h"
#include "Lagrange.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -176,19 +177,29 @@ bool ASMs2DLag::integrate (Integrand& integrand,
const double* wg = GaussQuadrature::getWeight(nGauss);
if (!xg || !wg) return false;
// Get parametric coordinates of the elements
RealArray upar, vpar;
this->getGridParameters(upar,0,1);
this->getGridParameters(vpar,1,1);
// Number of elements in each direction
const int nelx = upar.size() - 1;
const int nely = vpar.size() - 1;
// Order of basis in the two parametric directions (order = degree + 1)
const int p1 = surf->order_u();
const int p2 = surf->order_v();
Vector N(p1*p2);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2);
Matrix dNdu, Xnod, Jac;
Vec4 X;
// === Assembly loop over all elements in the patch ==========================
const int nel = this->getNoElms();
for (int iel = 1; iel <= nel; iel++)
int iel = 1;
for (int i2 = 0; i2 < nely; i2++)
for (int i1 = 0; i1 < nelx; i1++, iel++)
{
// Set up control point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
@@ -219,24 +230,26 @@ bool ASMs2DLag::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j];
// Parameter value of current integration point
fe.u = 0.5*(upar[i1]*(1.0-xg[i]) + upar[i1+1]*(1.0+xg[i]));
fe.v = 0.5*(vpar[i2]*(1.0-xg[j]) + vpar[i2+1]*(1.0+xg[j]));
// Compute basis function derivatives at current integration point
// using tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N,dNdu,p1,xg[i],p2,xg[j]))
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xg[i],p2,xg[j]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double dA = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (dA == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,dA*weight,N,dNdX,X))
fe.detJxW *= wg[i]*wg[j];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -279,8 +292,8 @@ bool ASMs2DLag::integrate (Integrand& integrand, int lIndex,
const int nelx = (nx-1)/(p1-1);
const int nely = (ny-1)/(p2-1);
Vector N(p1*p2);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 normal;
double xi[2];
@@ -326,21 +339,22 @@ bool ASMs2DLag::integrate (Integrand& integrand, int lIndex,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N,dNdu,p1,xi[0],p2,xi[1]))
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xi[0],p2,xi[1]))
return false;
// Compute basis function derivatives and the edge normal
double dS = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (edgeDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*wg[i],N,dNdX,X,normal))
fe.detJxW *= wg[i];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}

View File

@@ -15,6 +15,7 @@
#include "ASMs2DSpec.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -95,9 +96,8 @@ bool ASMs2DSpec::integrate (Integrand& integrand,
if (!Legendre::basisDerivatives(p1,D1)) return false;
if (!Legendre::basisDerivatives(p2,D2)) return false;
Vector N (p1*p2);
Matrix dNdu(p1*p2,2);
Matrix dNdX, Xnod, Jac;
FiniteElement fe(p1*p2);
Matrix dNdu(p1*p2,2), Xnod, Jac;
Vec4 X;
@@ -125,16 +125,13 @@ bool ASMs2DSpec::integrate (Integrand& integrand,
for (int j = 1; j <= p2; j++)
for (int i = 1; i <= p1; i++, count++)
{
// Weight of current integration point
double weight = wg1(i)*wg2(j);
// Evaluate the basis functions and gradients using
// tensor product of one-dimensional Lagrange polynomials
evalBasis(i,j,p1,p2,D1,D2,N,dNdu);
evalBasis(i,j,p1,p2,D1,D2,fe.N,dNdu);
// Compute Jacobian inverse of coordinate mapping and derivatives
double dA = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (dA == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X.x = Xnod(1,count);
@@ -142,7 +139,8 @@ bool ASMs2DSpec::integrate (Integrand& integrand,
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,dA*weight,N,dNdX,X))
fe.detJxW *= wg1(i)*wg2(j);
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -191,9 +189,8 @@ bool ASMs2DSpec::integrate (Integrand& integrand, int lIndex,
int nen = p[0]*p[1];
Vector N(nen);
Matrix dNdu(nen,2);
Matrix dNdX, Xnod, Jac;
FiniteElement fe(nen);
Matrix dNdu(nen,2), Xnod, Jac;
Vec4 X;
Vec3 normal;
int xi[2];
@@ -233,29 +230,27 @@ bool ASMs2DSpec::integrate (Integrand& integrand, int lIndex,
for (int i = 0; i < p[t2-1]; i++)
{
// Weight of current integration point
double weight = wg[t2-1][i];
// "Coordinates" along the edge
xi[t1-1] = edgeDir < 0 ? 1 : p[t1-1];
xi[t2-1] = i+1;
// Evaluate the basis functions and gradients using
// tensor product of one-dimensional Lagrange polynomials
evalBasis(xi[0],xi[1],p[0],p[1],D1,D2,N,dNdu);
evalBasis(xi[0],xi[1],p[0],p[1],D1,D2,fe.N,dNdu);
// Compute basis function derivatives and the edge normal
double dS = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (edgeDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,N,dNdX,X,normal))
fe.detJxW *= wg[t2-1][i];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}

View File

@@ -15,6 +15,7 @@
#include "ASMs2Dmx.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -400,11 +401,10 @@ bool ASMs2Dmx::integrate (Integrand& integrand,
const int n2 = surf->numCoefs_v();
const int nel1 = n1 - p1 + 1;
Vector N1(basis1->order_u()*basis1->order_v());
Vector N2(basis2->order_u()*basis2->order_v());
Matrix dN1du, dN1dX, dN2du, dN2dX, Xnod, Jac;
MxFiniteElement fe(basis1->order_u()*basis1->order_v(),
basis2->order_u()*basis2->order_v());
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
double detJ;
// === Assembly loop over all elements in the patch ==========================
@@ -423,7 +423,7 @@ bool ASMs2Dmx::integrate (Integrand& integrand,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElement(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -441,33 +441,35 @@ bool ASMs2Dmx::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.25*dA*wg[i]*wg[j];
// Parameter values of current integration point
fe.u = gpar[0](i+1,i1-p1+1);
fe.v = gpar[1](j+1,i2-p2+1);
// Fetch basis function derivatives at current integration point
extractBasis(spline1[ip],N1,dN1du);
extractBasis(spline2[ip],N2,dN2du);
extractBasis(spline1[ip],fe.N1,dN1du);
extractBasis(spline2[ip],fe.N2,dN2du);
// Compute Jacobian inverse of the coordinate mapping and
// basis function derivatives w.r.t. Cartesian coordinates
if (geoUsesBasis1)
{
detJ = utl::Jacobian(Jac,dN1dX,Xnod,dN1du);
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.detJxW = utl::Jacobian(Jac,fe.dN1dX,Xnod,dN1du);
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
}
else
{
detJ = utl::Jacobian(Jac,dN2dX,Xnod,dN2du);
dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
fe.detJxW = utl::Jacobian(Jac,fe.dN2dX,Xnod,dN2du);
fe.dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
}
if (detJ == 0.0) continue; // skip singular points
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * (geoUsesBasis1 ? N1 : N2);
X = Xnod * (geoUsesBasis1 ? fe.N1 : fe.N2);
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,N1,N2,dN1dX,dN2dX,X))
fe.detJxW *= 0.25*dA*wg[i]*wg[j];
if (!integrand.evalIntMx(elmInt,fe,time,X))
return false;
}
@@ -540,12 +542,11 @@ bool ASMs2Dmx::integrate (Integrand& integrand, int lIndex,
const int n1 = surf->numCoefs_u();
const int n2 = surf->numCoefs_v();
Vector N1(basis1->order_u()*basis1->order_v());
Vector N2(basis2->order_u()*basis2->order_v());
Matrix dN1du, dN1dX, dN2du, dN2dX, Xnod, Jac;
MxFiniteElement fe(basis1->order_u()*basis1->order_v(),
basis2->order_u()*basis2->order_v());
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
Vec3 normal;
double detJ;
// === Assembly loop over all elements on the patch edge =====================
@@ -575,7 +576,7 @@ bool ASMs2Dmx::integrate (Integrand& integrand, int lIndex,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElementBou(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -592,36 +593,33 @@ bool ASMs2Dmx::integrate (Integrand& integrand, int lIndex,
int ip = (abs(edgeDir) == 1 ? i2-p2 : i1-p1)*nGauss;
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.5*dS*wg[i];
// Fetch basis function derivatives at current integration point
extractBasis(spline1[ip],N1,dN1du);
extractBasis(spline2[ip],N2,dN2du);
extractBasis(spline1[ip],fe.N1,dN1du);
extractBasis(spline2[ip],fe.N2,dN2du);
// Compute Jacobian inverse of the coordinate mapping and
// basis function derivatives w.r.t. Cartesian coordinates
if (geoUsesBasis1)
{
detJ = utl::Jacobian(Jac,normal,dN1dX,Xnod,dN1du,t1,t2);
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN1dX,Xnod,dN1du,t1,t2);
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
}
else
{
detJ = utl::Jacobian(Jac,normal,dN2dX,Xnod,dN2du,t1,t2);
dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN2dX,Xnod,dN2du,t1,t2);
fe.dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
}
if (detJ == 0.0) continue; // skip singular points
if (fe.detJxW == 0.0) continue; // skip singular points
if (edgeDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * (geoUsesBasis1 ? N1 : N2);
X = Xnod * (geoUsesBasis1 ? fe.N1 : fe.N2);
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,detJ*weight,
N1,N2,dN1dX,dN2dX,X,normal))
fe.detJxW *= 0.5*dS*wg[i];
if (!integrand.evalBouMx(elmInt,fe,time,X,normal))
return false;
}

View File

@@ -16,6 +16,7 @@
#include "ASMs2DmxLag.h"
#include "Lagrange.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -175,6 +176,15 @@ bool ASMs2DmxLag::integrate (Integrand& integrand,
const double* wg = GaussQuadrature::getWeight(nGauss);
if (!xg || !wg) return false;
// Get parametric coordinates of the elements
RealArray upar, vpar;
this->getGridParameters(upar,0,1);
this->getGridParameters(vpar,1,1);
// Number of elements in each direction
const int nelx = upar.size() - 1;
const int nely = vpar.size() - 1;
// Order of basis in the two parametric directions (order = degree + 1)
const int p1 = surf->order_u();
const int p2 = surf->order_v();
@@ -182,21 +192,22 @@ bool ASMs2DmxLag::integrate (Integrand& integrand,
const int q1 = p1 - 1;
const int q2 = p2 - 1;
Vector N1(p1*p2), N2(q1*q2);
Matrix dN1du, dN2du, dN1dX, dN2dX, Xnod, Jac;
MxFiniteElement fe(p1*p2,q1*q2);
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
// === Assembly loop over all elements in the patch ==========================
const int nel = this->getNoElms();
for (int iel = 1; iel <= nel; iel++)
int iel = 1;
for (int i2 = 0; i2 < nely; i2++)
for (int i1 = 0; i1 < nelx; i1++, iel++)
{
// Set up control point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElement(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -213,28 +224,30 @@ bool ASMs2DmxLag::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j];
// Parameter value of current integration point
fe.u = 0.5*(upar[i1]*(1.0-xg[i]) + upar[i1+1]*(1.0+xg[i]));
fe.v = 0.5*(vpar[i2]*(1.0-xg[j]) + vpar[i2+1]*(1.0+xg[j]));
// Compute basis function derivatives at current integration point
// using tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N1,dN1du,p1,xg[i],p2,xg[j]))
if (!Lagrange::computeBasis(fe.N1,dN1du,p1,xg[i],p2,xg[j]))
return false;
if (!Lagrange::computeBasis(N2,dN2du,q1,xg[i],q2,xg[j]))
if (!Lagrange::computeBasis(fe.N2,dN2du,q1,xg[i],q2,xg[j]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double dA = utl::Jacobian(Jac,dN1dX,Xnod,dN1du);
if (dA == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dN1dX,Xnod,dN1du);
if (fe.detJxW == 0.0) continue; // skip singular points
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
// Cartesian coordinates of current integration point
X = Xnod * N1;
X = Xnod * fe.N1;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,dA*weight,N1,N2,dN1dX,dN2dX,X))
fe.detJxW *= wg[i]*wg[j];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -276,8 +289,8 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
const int nelx = (nx2-1)/(q1-1);
const int nely = (ny2-1)/(q2-1);
Vector N1(p1*p2), N2(q1*q2);
Matrix dN1du, dN2du, dN1dX, dN2dX, Xnod, Jac;
MxFiniteElement fe(p1*p2,q1*q2);
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
Vec3 normal;
double xi[2];
@@ -304,7 +317,7 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElementBou(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -326,26 +339,26 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N1,dN1du,p1,xi[0],p2,xi[1]))
if (!Lagrange::computeBasis(fe.N1,dN1du,p1,xi[0],p2,xi[1]))
return false;
if (!Lagrange::computeBasis(N2,dN2du,q1,xi[0],q2,xi[1]))
if (!Lagrange::computeBasis(fe.N2,dN2du,q1,xi[0],q2,xi[1]))
return false;
// Compute basis function derivatives and the edge normal
double dS = utl::Jacobian(Jac,normal,dN1dX,Xnod,dN1du,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN1dX,Xnod,dN1du,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
if (edgeDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N1;
X = Xnod * fe.N1;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*wg[i],
N1,N2,dN1dX,dN2dX,X,normal))
fe.detJxW *= wg[i];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}

View File

@@ -17,6 +17,7 @@
#include "ASMs3D.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -1132,10 +1133,9 @@ bool ASMs3D::integrate (Integrand& integrand,
const int nel1 = n1 - p1 + 1;
const int nel2 = n2 - p2 + 1;
Vector N(p1*p2*p3), Navg;
Matrix dNdu, dNdX, Xnod, Jac;
Matrix3D d2Ndu2, d2NdX2, Hess;
double h = 0.0;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Matrix3D d2Ndu2, Hess;
Vec4 X;
@@ -1157,13 +1157,13 @@ bool ASMs3D::integrate (Integrand& integrand,
// Compute characteristic element length, if needed
if (integrand.getIntegrandType() == 2)
h = getElmSize(p1,p2,p3,Xnod);
fe.h = getElmSize(p1,p2,p3,Xnod);
else if (integrand.getIntegrandType() == 3)
{
// --- Compute average value of basis functions over the element -----
Navg.resize(p1*p2*p3,true);
fe.Navg.resize(p1*p2*p3,true);
double vol = 0.0;
int ip = (((i3-p3)*nGauss*nel2 + i2-p2)*nGauss*nel1 + i1-p1)*nGauss;
for (int k = 0; k < nGauss; k++, ip += nGauss*(nel2-1)*nGauss*nel1)
@@ -1171,20 +1171,20 @@ bool ASMs3D::integrate (Integrand& integrand,
for (int i = 0; i < nGauss; i++, ip++)
{
// Fetch basis function derivatives at current integration point
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute Jacobian determinant of coordinate mapping
// and multiply by weight of current integration point
double detJac = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu,false);
double weight = 0.125*dV*wg[i]*wg[j]*wg[k];
double detJxW = utl::Jacobian(Jac,dNdX,Xnod,dNdu,false)*weight;
// Numerical quadrature
Navg += N*detJxW;
vol += detJxW;
fe.Navg.add(fe.N,detJac*weight);
vol += detJac*weight;
}
// Divide by element volume
Navg /= vol;
fe.Navg /= vol;
}
else if (integrand.getIntegrandType() == 4)
@@ -1218,50 +1218,39 @@ bool ASMs3D::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.125*dV*wg[i]*wg[j]*wg[k];
// Parameter values of current integration point
fe.u = gpar[0](i+1,i1-p1+1);
fe.v = gpar[1](j+1,i2-p2+1);
fe.w = gpar[2](k+1,i3-p3+1);
// Fetch basis function derivatives at current integration point
if (integrand.getIntegrandType() == 2)
extractBasis(spline2[ip],N,dNdu,d2Ndu2);
extractBasis(spline2[ip],fe.N,dNdu,d2Ndu2);
else
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (detJ == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Compute Hessian of coordinate mapping and 2nd order derivatives
if (integrand.getIntegrandType() == 2)
if (!utl::Hessian(Hess,d2NdX2,Jac,Xnod,d2Ndu2,dNdu))
if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xnod,d2Ndu2,dNdu))
return false;
#if SP_DEBUG > 4
std::cout <<"\niel, ip = "<< iel <<" "<< ip
<<"\nN ="<< N <<"dNdX ="<< dNdX << std::endl;
<<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX << std::endl;
#endif
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
bool ok = false;
switch (integrand.getIntegrandType())
{
case 2:
ok = integrand.evalInt(elmInt,time,detJ*weight,
N,dNdX,d2NdX2,X,h);
break;
case 3:
ok = integrand.evalInt(elmInt,time,detJ*weight,
N,dNdX,Navg,X);
break;
default:
ok = integrand.evalInt(elmInt,time,detJ*weight,
N,dNdX,X);
}
if (!ok) return false;
fe.detJxW *= 0.125*dV*wg[i]*wg[j]*wg[k];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
// Finalize the element quantities
@@ -1344,8 +1333,8 @@ bool ASMs3D::integrate (Integrand& integrand, int lIndex,
const int nel1 = n1 - p1 + 1;
const int nel2 = n2 - p2 + 1;
Vector N(p1*p2*p3);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 normal;
@@ -1405,24 +1394,22 @@ bool ASMs3D::integrate (Integrand& integrand, int lIndex,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nf1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.25*dA*wg[i]*wg[j];
// Fetch basis function derivatives at current integration point
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute basis function derivatives and the face normal
double dS = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (faceDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,N,dNdX,X,normal))
fe.detJxW *= 0.25*dA*wg[i]*wg[j];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}
@@ -1496,10 +1483,10 @@ bool ASMs3D::integrateEdge (Integrand& integrand, int lEdge,
const int p2 = svol->order(1);
const int p3 = svol->order(2);
Vector N(p1*p2*p3);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 tangent;
Vec3 tang;
// === Assembly loop over all elements on the patch edge =====================
@@ -1564,22 +1551,20 @@ bool ASMs3D::integrateEdge (Integrand& integrand, int lEdge,
LocalIntegral* elmInt = 0;
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.5*dS*wg[i];
// Fetch basis function derivatives at current integration point
extractBasis(spline[ip],N,dNdu);
extractBasis(spline[ip],fe.N,dNdu);
// Compute basis function derivatives and the edge tangent
double dT = utl::Jacobian(Jac,tangent,dNdX,Xnod,dNdu,1+(lEdge-1)/4);
if (dT == 0.0) continue; // skip singular points
// Compute basis function derivatives and the edge tang
fe.detJxW = utl::Jacobian(Jac,tang,fe.dNdX,Xnod,dNdu,1+(lEdge-1)/4);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dT*weight,N,dNdX,X,tangent))
fe.detJxW *= 0.5*dS*wg[i];
if (!integrand.evalBou(elmInt,fe,time,X,tang))
return false;
}
@@ -1604,12 +1589,14 @@ bool ASMs3D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
}
DoubleIter uit = svol->basis(dir).begin();
double ucurr, uprev = *(uit++);
double ucurr = 0.0, uprev = *(uit++);
while (uit != svol->basis(dir).end())
{
ucurr = *(uit++);
if (ucurr > uprev)
for (int i = 0; i < nSegPerSpan; i++)
if (nSegPerSpan == 1)
prm.push_back(uprev);
else for (int i = 0; i < nSegPerSpan; i++)
{
double xg = (double)(2*i-nSegPerSpan)/(double)nSegPerSpan;
prm.push_back(0.5*(ucurr*(1.0+xg) + uprev*(1.0-xg)));
@@ -1617,7 +1604,8 @@ bool ASMs3D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
uprev = ucurr;
}
prm.push_back(svol->basis(dir).endparam());
if (ucurr > prm.back())
prm.push_back(ucurr);
return true;
}
@@ -1745,7 +1733,7 @@ bool ASMs3D::evalSolution (Matrix& sField, const Integrand& integrand,
if (npe)
{
// Compute parameter values of the result sampling points
DoubleVec gpar[3];
RealArray gpar[3];
for (int dir = 0; dir < 3 && retVal; dir++)
retVal = this->getGridParameters(gpar[dir],dir,npe[dir]-1);

View File

@@ -16,6 +16,7 @@
#include "ASMs3DLag.h"
#include "Lagrange.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -104,7 +105,7 @@ bool ASMs3DLag::generateFEMTopology()
int i, j, k, a, b, c, iel = 0;
for (k = 0; k < nelz; k++)
for (j = 0; j < nely; j++)
for ( i = 0; i < nelx; i++, iel++)
for (i = 0; i < nelx; i++, iel++)
{
MLGE[iel] = ++gEl;
MNPC[iel].resize(nen);
@@ -191,21 +192,34 @@ bool ASMs3DLag::integrate (Integrand& integrand,
const double* wg = GaussQuadrature::getWeight(nGauss);
if (!xg || !wg) return false;
// Get parametric coordinates of the elements
RealArray upar, vpar, wpar;
this->getGridParameters(upar,0,1);
this->getGridParameters(vpar,1,1);
this->getGridParameters(wpar,2,1);
// Number of elements in each direction
const int nelx = upar.size() - 1;
const int nely = vpar.size() - 1;
const int nelz = wpar.size() - 1;
// Order of basis in the three parametric directions (order = degree + 1)
const int p1 = svol->order(0);
const int p2 = svol->order(1);
const int p3 = svol->order(2);
Vector N(p1*p2*p3);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Vec4 X;
// === Assembly loop over all elements in the patch ==========================
const int nel = this->getNoElms();
for (int iel = 1; iel <= nel; iel++)
{
int iel = 1;
for (int i3 = 0; i3 < nelz; i3++)
for (int i2 = 0; i2 < nely; i2++)
for (int i1 = 0; i1 < nelx; i1++, iel++)
{
// Set up nodal point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
@@ -237,24 +251,27 @@ bool ASMs3DLag::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j]*wg[k];
// Parameter value of current integration point
fe.u = 0.5*(upar[i1]*(1.0-xg[i]) + upar[i1+1]*(1.0+xg[i]));
fe.v = 0.5*(vpar[i2]*(1.0-xg[j]) + vpar[i2+1]*(1.0+xg[j]));
fe.w = 0.5*(wpar[i3]*(1.0-xg[k]) + wpar[i3+1]*(1.0+xg[k]));
// Compute basis function derivatives at current integration point
// using tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N,dNdu,p1,xg[i],p2,xg[j],p3,xg[k]))
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xg[i],p2,xg[j],p3,xg[k]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (detJ == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,X))
fe.detJxW *= wg[i]*wg[j]*wg[k];
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -265,7 +282,7 @@ bool ASMs3DLag::integrate (Integrand& integrand,
// Assembly of global system integral
if (!glInt.assemble(elmInt,MLGE[iel-1]))
return false;
}
}
return true;
}
@@ -300,8 +317,8 @@ bool ASMs3DLag::integrate (Integrand& integrand, int lIndex,
const int nely = (ny-1)/(p2-1);
const int nelz = (nz-1)/(p3-1);
Vector N(p1*p2*p3);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 normal;
double xi[3];
@@ -345,9 +362,6 @@ bool ASMs3DLag::integrate (Integrand& integrand, int lIndex,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j];
// Gauss point coordinates on the face
xi[t0-1] = faceDir < 0 ? -1.0 : 1.0;
xi[t1-1] = xg[i];
@@ -355,21 +369,22 @@ bool ASMs3DLag::integrate (Integrand& integrand, int lIndex,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N,dNdu,p1,xi[0],p2,xi[1],p3,xi[2]))
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xi[0],p2,xi[1],p3,xi[2]))
return false;
// Compute basis function derivatives and the face normal
double dS = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (faceDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,N,dNdX,X,normal))
fe.detJxW *= wg[i]*wg[j];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}
@@ -406,8 +421,8 @@ bool ASMs3DLag::integrateEdge (Integrand& integrand, int lEdge,
const int nely = (ny-1)/(p2-1);
const int nelz = (nz-1)/(p3-1);
Vector N(p1*p2*p3);
Matrix dNdu, dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu, Xnod, Jac;
Vec4 X;
Vec3 tangent;
double xi[3];
@@ -472,19 +487,19 @@ bool ASMs3DLag::integrateEdge (Integrand& integrand, int lEdge,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N,dNdu,p1,xi[0],p2,xi[1],p3,xi[2]))
if (!Lagrange::computeBasis(fe.N,dNdu,p1,xi[0],p2,xi[1],p3,xi[2]))
return false;
// Compute basis function derivatives and the edge tangent
double dS = utl::Jacobian(Jac,tangent,dNdX,Xnod,dNdu,1+lDir);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,tangent,fe.dNdX,Xnod,dNdu,1+lDir);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*wg[i],N,dNdX,X,tangent))
if (!integrand.evalBou(elmInt,fe,time,X,tangent))
return false;
}

View File

@@ -15,6 +15,7 @@
#include "ASMs3DSpec.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -100,9 +101,8 @@ bool ASMs3DSpec::integrate (Integrand& integrand,
if (!Legendre::basisDerivatives(p2,D2)) return false;
if (!Legendre::basisDerivatives(p3,D3)) return false;
Vector N(p1*p2*p3);
Matrix dNdu(p1*p2*p3,3);
Matrix dNdX, Xnod, Jac;
FiniteElement fe(p1*p2*p3);
Matrix dNdu(p1*p2*p3,3), Xnod, Jac;
Vec4 X;
@@ -131,16 +131,13 @@ bool ASMs3DSpec::integrate (Integrand& integrand,
for (int j = 1; j <= p2; j++)
for (int i = 1; i <= p1; i++, count++)
{
// Weight of current integration point
double weight = wg1(i)*wg2(j)*wg3(k);
// Evaluate the basis functions and gradients using tensor product
// of the one-dimensional Lagrange polynomials
evalBasis(i,j,k,p1,p2,p3,D1,D2,D3,N,dNdu);
evalBasis(i,j,k,p1,p2,p3,D1,D2,D3,fe.N,dNdu);
// Compute Jacobian inverse of coordinate mapping and derivatives
double detJ = utl::Jacobian(Jac,dNdX,Xnod,dNdu);
if (detJ == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X.x = Xnod(1,count);
@@ -149,7 +146,8 @@ bool ASMs3DSpec::integrate (Integrand& integrand,
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,N,dNdX,X))
fe.detJxW *= wg1(i)*wg2(j)*wg3(k);
if (!integrand.evalInt(elmInt,fe,time,X))
return false;
}
@@ -203,9 +201,8 @@ bool ASMs3DSpec::integrate (Integrand& integrand, int lIndex,
int nen = p[0]*p[1]*p[2];
Vector N(nen);
Matrix dNdu(nen,3);
Matrix dNdX, Xnod, Jac;
FiniteElement fe(nen);
Matrix dNdu(nen,3), Xnod, Jac;
Vec4 X;
Vec3 normal;
int xi[3];
@@ -249,9 +246,6 @@ bool ASMs3DSpec::integrate (Integrand& integrand, int lIndex,
for (int j = 0; j < p[t2-1]; j++)
for (int i = 0; i < p[t1-1]; i++)
{
// Weight of current integration point
double weight = wg[t1-1][i]*wg[t2-1][j];
// "Coordinates" on the face
xi[t0-1] = faceDir < 0 ? 1 : p[t0-1];
xi[t1-1] = i+1;
@@ -259,20 +253,21 @@ bool ASMs3DSpec::integrate (Integrand& integrand, int lIndex,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
evalBasis(xi[0],xi[1],xi[2],p[0],p[1],p[2],D1,D2,D3,N,dNdu);
evalBasis(xi[0],xi[1],xi[2],p[0],p[1],p[2],D1,D2,D3,fe.N,dNdu);
// Compute basis function derivatives and the face normal
double dS = utl::Jacobian(Jac,normal,dNdX,Xnod,dNdu,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dNdX,Xnod,dNdu,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
if (faceDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,N,dNdX,X,normal))
fe.detJxW *= wg[t1-1][i]*wg[t2-1][j];
if (!integrand.evalBou(elmInt,fe,time,X,normal))
return false;
}
@@ -321,9 +316,8 @@ bool ASMs3DSpec::integrateEdge (Integrand& integrand, int lEdge,
const int nen = p1*p2*p3;
Vector N(nen);
Matrix dNdu(nen,3);
Matrix dNdX, Xnod, Jac;
FiniteElement fe(nen);
Matrix dNdu(nen,3), Xnod, Jac;
Vec4 X;
Vec3 tangent;
int xi[3];
@@ -388,18 +382,19 @@ bool ASMs3DSpec::integrateEdge (Integrand& integrand, int lEdge,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
evalBasis(xi[0],xi[1],xi[2],p1,p2,p3,D1,D2,D3,N,dNdu);
evalBasis(xi[0],xi[1],xi[2],p1,p2,p3,D1,D2,D3,fe.N,dNdu);
// Compute basis function derivatives and the edge tangent
double dS = utl::Jacobian(Jac,tangent,dNdX,Xnod,dNdu,1+lDir);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,tangent,fe.dNdX,Xnod,dNdu,1+lDir);
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * N;
X = Xnod * fe.N;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*wg[lDir][i],N,dNdX,X,tangent))
fe.detJxW *= wg[lDir][i];
if (!integrand.evalBou(elmInt,fe,time,X,tangent))
return false;
}
@@ -434,9 +429,9 @@ bool ASMs3DSpec::evalSolution (Matrix& sField, const Integrand& integrand,
size_t nPoints = this->getNoNodes();
IntVec check(nPoints,0);
Vector N(p1*p2*p3), solPt;
std::vector<Vector> globSolPt(nPoints);
Matrix dNdu(p1*p2*p3,3), dNdX, Xnod, Jac;
Vector N(p1*p2*p3), solPt;
Vectors globSolPt(nPoints);
Matrix dNdu(p1*p2*p3,3), dNdX, Xnod, Jac;
// Evaluate the secondary solution field at each point
const int nel = this->getNoElms();

View File

@@ -15,6 +15,7 @@
#include "ASMs3Dmx.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -429,11 +430,10 @@ bool ASMs3Dmx::integrate (Integrand& integrand,
const int nel1 = n1 - p1 + 1;
const int nel2 = n2 - p2 + 1;
Vector N1(basis1->order(0)*basis1->order(1)*basis1->order(2));
Vector N2(basis2->order(0)*basis2->order(1)*basis2->order(2));
Matrix dN1du, dN1dX, dN2du, dN2dX, Xnod, Jac;
MxFiniteElement fe(basis1->order(0)*basis1->order(1)*basis1->order(2),
basis2->order(0)*basis2->order(1)*basis2->order(2));
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
double detJ;
// === Assembly loop over all elements in the patch ==========================
@@ -453,7 +453,7 @@ bool ASMs3Dmx::integrate (Integrand& integrand,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElement(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -472,34 +472,36 @@ bool ASMs3Dmx::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.125*dV*wg[i]*wg[j]*wg[k];
// Parameter values of current integration point
fe.u = gpar[0](i+1,i1-p1+1);
fe.v = gpar[1](j+1,i2-p2+1);
fe.w = gpar[2](k+1,i3-p3+1);
// Fetch basis function derivatives at current integration point
extractBasis(spline1[ip],N1,dN1du);
extractBasis(spline2[ip],N2,dN2du);
extractBasis(spline1[ip],fe.N1,dN1du);
extractBasis(spline2[ip],fe.N2,dN2du);
// Compute Jacobian inverse of the coordinate mapping and
// basis function derivatives w.r.t. Cartesian coordinates
if (geoUsesBasis1)
{
detJ = utl::Jacobian(Jac,dN1dX,Xnod,dN1du);
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.detJxW = utl::Jacobian(Jac,fe.dN1dX,Xnod,dN1du);
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
}
else
{
detJ = utl::Jacobian(Jac,dN2dX,Xnod,dN2du);
dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
fe.detJxW = utl::Jacobian(Jac,fe.dN2dX,Xnod,dN2du);
fe.dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
}
if (detJ == 0.0) continue; // skip singular points
if (fe.detJxW == 0.0) continue; // skip singular points
// Cartesian coordinates of current integration point
X = Xnod * (geoUsesBasis1 ? N1 : N2);
X = Xnod * (geoUsesBasis1 ? fe.N1 : fe.N2);
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,detJ*weight,
N1,N2,dN1dX,dN2dX,X))
fe.detJxW *= 0.125*dV*wg[i]*wg[j]*wg[k];
if (!integrand.evalIntMx(elmInt,fe,time,X))
return false;
}
@@ -533,7 +535,7 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
const int t1 = 1 + abs(faceDir)%3; // first tangent direction
const int t2 = 1 + t1%3; // second tangent direction
// Compute parameter values of the Gauss points along the whole patch edge
// Compute parameter values of the Gauss points over the whole patch face
Matrix gpar[3];
for (int d = 0; d < 3; d++)
if (-1-d == faceDir)
@@ -578,12 +580,12 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
const int nel1 = n1 - p1 + 1;
const int nel2 = n2 - p2 + 1;
Vector N1(basis1->order(0)*basis1->order(1)*basis1->order(2));
Vector N2(basis2->order(0)*basis2->order(1)*basis2->order(2));
Matrix dN1du, dN1dX, dN2du, dN2dX, Xnod, Jac;
MxFiniteElement fe(basis1->order(0)*basis1->order(1)*basis1->order(2),
basis2->order(0)*basis2->order(1)*basis2->order(2));
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
Vec3 normal;
double dS;
// === Assembly loop over all elements on the patch face =====================
@@ -616,7 +618,7 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElementBou(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -644,36 +646,33 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
for (int j = 0; j < nGauss; j++, ip += nGauss*(nf1-1))
for (int i = 0; i < nGauss; i++, ip++)
{
// Weight of current integration point
double weight = 0.25*dA*wg[i]*wg[j];
// Fetch basis function derivatives at current integration point
extractBasis(spline1[ip],N1,dN1du);
extractBasis(spline2[ip],N2,dN2du);
extractBasis(spline1[ip],fe.N1,dN1du);
extractBasis(spline2[ip],fe.N2,dN2du);
// Compute Jacobian inverse of the coordinate mapping and
// basis function derivatives w.r.t. Cartesian coordinates
if (geoUsesBasis1)
{
dS = utl::Jacobian(Jac,normal,dN1dX,Xnod,dN1du,t1,t2);
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN1dX,Xnod,dN1du,t1,t2);
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
}
else
{
dS = utl::Jacobian(Jac,normal,dN2dX,Xnod,dN2du,t1,t2);
dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN2dX,Xnod,dN2du,t1,t2);
fe.dN1dX.multiply(dN1du,Jac); // dN1dX = dN1du * J^-1
}
if (dS == 0.0) continue; // skip singular points
if (fe.detJxW == 0.0) continue; // skip singular points
if (faceDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * (geoUsesBasis1 ? N1 : N2);
X = Xnod * (geoUsesBasis1 ? fe.N1 : fe.N2);
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,
N1,N2,dN1dX,dN2dX,X,normal))
fe.detJxW *= 0.25*dA*wg[i]*wg[j];
if (!integrand.evalBouMx(elmInt,fe,time,X,normal))
return false;
}

View File

@@ -16,6 +16,7 @@
#include "ASMs3DmxLag.h"
#include "Lagrange.h"
#include "TimeDomain.h"
#include "FiniteElement.h"
#include "GlobalIntegral.h"
#include "IntegrandBase.h"
#include "CoordinateMapping.h"
@@ -186,9 +187,20 @@ bool ASMs3DmxLag::integrate (Integrand& integrand,
if (!svol) return true; // silently ignore empty patches
// Get Gaussian quadrature points and weights
const double* xg = GaussQuadrature::getCoord(nGauss);
const double* wg = GaussQuadrature::getWeight(nGauss);
if (!xg || !wg) return false;
const double* x = GaussQuadrature::getCoord(nGauss);
const double* w = GaussQuadrature::getWeight(nGauss);
if (!x || !w) return false;
// Get parametric coordinates of the elements
RealArray upar, vpar, wpar;
this->getGridParameters(upar,0,1);
this->getGridParameters(vpar,1,1);
this->getGridParameters(wpar,2,1);
// Number of elements in each direction
const int nelx = upar.size() - 1;
const int nely = vpar.size() - 1;
const int nelz = wpar.size() - 1;
// Order of basis in the two parametric directions (order = degree + 1)
const int p1 = svol->order(0);
@@ -199,21 +211,23 @@ bool ASMs3DmxLag::integrate (Integrand& integrand,
const int q2 = p2 - 1;
const int q3 = p3 - 1;
Vector N1(p1*p2*p3), N2(q1*q2*q3);
Matrix dN1du, dN2du, dN1dX, dN2dX, Xnod, Jac;
MxFiniteElement fe(p1*p2*p3,q1*q2*q3);
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
// === Assembly loop over all elements in the patch ==========================
const int nel = this->getNoElms();
for (int iel = 1; iel <= nel; iel++)
{
int iel = 1;
for (int i3 = 0; i3 < nelz; i3++)
for (int i2 = 0; i2 < nely; i2++)
for (int i1 = 0; i1 < nelx; i1++, iel++)
{
// Set up control point coordinates for current element
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElement(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -231,35 +245,38 @@ bool ASMs3DmxLag::integrate (Integrand& integrand,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j]*wg[k];
// Parameter value of current integration point
fe.u = 0.5*(upar[i1]*(1.0-x[i]) + upar[i1+1]*(1.0+x[i]));
fe.v = 0.5*(vpar[i2]*(1.0-x[j]) + vpar[i2+1]*(1.0+x[j]));
fe.w = 0.5*(wpar[i3]*(1.0-x[k]) + wpar[i3+1]*(1.0+x[k]));
// Compute basis function derivatives at current integration point
// using tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N1,dN1du,p1,xg[i],p2,xg[j],p3,xg[k]))
if (!Lagrange::computeBasis(fe.N1,dN1du,p1,x[i],p2,x[j],p3,x[k]))
return false;
if (!Lagrange::computeBasis(N2,dN2du,q1,xg[i],q2,xg[j],q3,xg[k]))
if (!Lagrange::computeBasis(fe.N2,dN2du,q1,x[i],q2,x[j],q3,x[k]))
return false;
// Compute Jacobian inverse of coordinate mapping and derivatives
double dA = utl::Jacobian(Jac,dN1dX,Xnod,dN1du);
if (dA == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,fe.dN1dX,Xnod,dN1du);
if (fe.detJxW == 0.0) continue; // skip singular points
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
// Cartesian coordinates of current integration point
X = Xnod * N1;
X = Xnod * fe.N1;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalInt(elmInt,time,dA*weight,N1,N2,dN1dX,dN2dX,X))
fe.detJxW *= w[i]*w[j]*w[k];
if (!integrand.evalIntMx(elmInt,fe,time,X))
return false;
}
// Assembly of global system integral
if (!glInt.assemble(elmInt,MLGE[iel-1]))
return false;
}
}
return true;
}
@@ -298,8 +315,8 @@ bool ASMs3DmxLag::integrate (Integrand& integrand, int lIndex,
const int nely = (ny2-1)/(q2-1);
const int nelz = (nz2-1)/(q3-1);
Vector N1(p1*p2*p3), N2(q1*q2*q3);
Matrix dN1du, dN2du, dN1dX, dN2dX, Xnod, Jac;
MxFiniteElement fe(p1*p2*p3,q1*q2*q3);
Matrix dN1du, dN2du, Xnod, Jac;
Vec4 X;
Vec3 normal;
double xi[3];
@@ -329,7 +346,7 @@ bool ASMs3DmxLag::integrate (Integrand& integrand, int lIndex,
if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities
IntVec::iterator f2start = MNPC[iel-1].begin() + N1.size();
IntVec::iterator f2start = MNPC[iel-1].begin() + fe.N1.size();
if (!integrand.initElementBou(IntVec(MNPC[iel-1].begin(),f2start),
IntVec(f2start,MNPC[iel-1].end()),nb1))
return false;
@@ -346,9 +363,6 @@ bool ASMs3DmxLag::integrate (Integrand& integrand, int lIndex,
for (int j = 0; j < nGauss; j++)
for (int i = 0; i < nGauss; i++)
{
// Weight of current integration point
double weight = wg[i]*wg[j];
// Gauss point coordinates on the face
xi[t0-1] = faceDir < 0 ? -1.0 : 1.0;
xi[t1-1] = xg[i];
@@ -356,26 +370,26 @@ bool ASMs3DmxLag::integrate (Integrand& integrand, int lIndex,
// Compute the basis functions and their derivatives, using
// tensor product of one-dimensional Lagrange polynomials
if (!Lagrange::computeBasis(N1,dN1du,p1,xi[0],p2,xi[1],p3,xi[2]))
if (!Lagrange::computeBasis(fe.N1,dN1du,p1,xi[0],p2,xi[1],p3,xi[2]))
return false;
if (!Lagrange::computeBasis(N2,dN2du,q1,xi[0],q2,xi[1],q3,xi[2]))
if (!Lagrange::computeBasis(fe.N2,dN2du,q1,xi[0],q2,xi[1],q3,xi[2]))
return false;
// Compute basis function derivatives and the edge normal
double dS = utl::Jacobian(Jac,normal,dN1dX,Xnod,dN1du,t1,t2);
if (dS == 0.0) continue; // skip singular points
fe.detJxW = utl::Jacobian(Jac,normal,fe.dN1dX,Xnod,dN1du,t1,t2);
if (fe.detJxW == 0.0) continue; // skip singular points
dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
fe.dN2dX.multiply(dN2du,Jac); // dN2dX = dN2du * J^-1
if (faceDir < 0) normal *= -1.0;
// Cartesian coordinates of current integration point
X = Xnod * N1;
X = Xnod * fe.N1;
X.t = time.t;
// Evaluate the integrand and accumulate element contributions
if (!integrand.evalBou(elmInt,time,dS*weight,
N1,N2,dN1dX,dN2dX,X,normal))
fe.detJxW *= wg[i]*wg[j];
if (!integrand.evalBouMx(elmInt,fe,time,X,normal))
return false;
}

59
src/ASM/FiniteElement.h Normal file
View File

@@ -0,0 +1,59 @@
// $Id$
//==============================================================================
//!
//! \file FiniteElement.h
//!
//! \date Mar 30 2011
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Finite element quantities at an integration point.
//!
//==============================================================================
#ifndef _FINITE_ELEMENT_H
#define _FINITE_ELEMENT_H
#include "MatVec.h"
/*!
\brief Class representing a finite element.
*/
class FiniteElement
{
public:
//! \brief Default constructor.
FiniteElement(size_t nb = 0) : h(0.0), N(nb), detJxW(1.0) {}
double u; //!< First parameter of current point
double v; //!< Second parameter of current point
double w; //!< Third parameter of current point
double h; //!< Characteristic element size
Vector N; //!< Basis function values
Vector Navg; //!< Volume-averaged basis function values
Matrix dNdX; //!< First derivatives (gradient) of the basis functions
Matrix3D d2NdX2; //!< Second derivates of the basis functions
double detJxW; //!< Weighted determinant of the coordinate mapping
};
/*!
\brief Class representing a mixed finite element.
*/
class MxFiniteElement : public FiniteElement
{
public:
//! \brief Default constructor.
MxFiniteElement(size_t nb1 = 0, size_t nb2 = 0) : FiniteElement(nb1),
N1(N), N2(nb2), dN1dX(dNdX) {}
Vector& N1; //!< Basis function values for the first basis
Vector N2; //!< Basis function values for the second basis
Matrix& dN1dX; //!< Basis function gradients for the first basis
Matrix dN2dX; //!< Basis function gradients for the second basis
};
#endif

View File

@@ -19,6 +19,8 @@
#include "MatVec.h"
struct TimeDomain;
class FiniteElement;
class MxFiniteElement;
class LocalIntegral;
class NormBase;
class AnaSol;
@@ -134,159 +136,80 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
//!
//! \details This interface is used when \a getIntegrandType returns 1.
//! The default implementation forwards to the stationary version.
//! \details The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& time, const Vec3& X) const
{
return this->evalInt(elmInt,detJW,N,dNdX,X);
return this->evalInt(elmInt,fe,X);
}
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] d2NdX2 Basis function second derivatives
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] h Characteristic element length
//!
//! \details This interface is used when \a getIntegrandType returns 2.
//! The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N, const Matrix& dNdX,
const Matrix3D& d2NdX2, const Vec3& X,
double h = 0.0) const
{
return this->evalInt(elmInt,detJW,N,dNdX,d2NdX2,X,h);
}
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] Navg Volume-averaged basis function values over the element
//! \param[in] X Cartesian coordinates of current integration point
//!
//! \details This interface is used when \a getIntegrandType returns 3.
//! Use when the integrand requires second-derivatives of the basis functions.
//! The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N, const Matrix& dNdX,
const Vector& Navg, const Vec3& X) const
{
return this->evalInt(elmInt,detJW,N,dNdX,Navg,X);
}
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N1 Basis function values, field 1
//! \param[in] N2 Basis function values, field 2
//! \param[in] dN1dX Basis function gradients, field 1
//! \param[in] dN2dX Basis function gradients, field 2
//! \param[in] X Cartesian coordinates of current integration point
//!
//! \details This interface is used for mixed formulations only.
//! The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalInt(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N1, const Vector& N2,
const Matrix& dN1dX, const Matrix& dN2dX,
const Vec3& X) const
virtual bool evalIntMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const TimeDomain& time, const Vec3& X) const
{
return this->evalInt(elmInt,detJW,N1,N2,dN1dX,dN2dX,X);
return this->evalIntMx(elmInt,fe,X);
}
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] fe Finite element data of current integration point
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
//!
//! \details The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalBou(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const TimeDomain& time,
const Vec3& X, const Vec3& normal) const
{
return this->evalBou(elmInt,detJW,N,dNdX,X,normal);
return this->evalBou(elmInt,fe,X,normal);
}
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] fe Mixed finite element data of current integration point
//! \param[in] time Parameters for nonlinear and time-dependent simulations
//! \param[in] N1 Basis function values, field 1
//! \param[in] N2 Basis function values, field 2
//! \param[in] dN1dX Basis function gradients, field 1
//! \param[in] dN2dX Basis function gradients, field 2
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
//!
//! \details This interface is used for mixed formulations.
//! The default implementation forwards to the stationary version.
//! Reimplement this method for time-dependent or non-linear problems.
virtual bool evalBou(LocalIntegral*& elmInt,
const TimeDomain& time, double detJW,
const Vector& N1, const Vector& N2,
const Matrix& dN1dX, const Matrix& dN2dX,
const Vec3& X, const Vec3& normal) const
virtual bool evalBouMx(LocalIntegral*& elmInt, const MxFiniteElement& fe,
const TimeDomain& time,
const Vec3& X, const Vec3& normal) const
{
return this->evalBou(elmInt,detJW,N1,N2,dN1dX,dN2dX,X,normal);
return this->evalBouMx(elmInt,fe,X,normal);
}
protected:
//! \brief Evaluates the integrand at interior points for stationary problems.
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
const Vec3& X) const { return false; }
virtual bool evalInt(LocalIntegral*&, const FiniteElement& fe,
const Vec3&) const { return false; }
//! \brief Evaluates the integrand at interior points for stationary problems.
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
const Matrix3D& d2NdX2, const Vec3& X,
double h = 0.0) const { return false; }
//! \brief Evaluates the integrand at interior points for stationary problems.
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX, const Vector& Navg,
const Vec3& X) const { return false; }
//! \brief Evaluates the integrand at interior points for stationary problems.
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N1, const Vector& N2,
const Matrix& dN1dX, const Matrix& dN2dX,
const Vec3& X) const { return false; }
virtual bool evalIntMx(LocalIntegral*&, const MxFiniteElement& fe,
const Vec3&) const { return false; }
//! \brief Evaluates the integrand at boundary points for stationary problems.
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX, const Vec3& X,
const Vec3& normal) const { return false; }
virtual bool evalBou(LocalIntegral*&, const FiniteElement&,
const Vec3&, const Vec3&) const { return false; }
//! \brief Evaluates the integrand at boundary points for stationary problems.
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N1, const Vector& N2,
const Matrix& dN1dX, const Matrix& dN2dX, const Vec3& X,
const Vec3& normal) const { return false; }
virtual bool evalBouMx(LocalIntegral*&, const MxFiniteElement&,
const Vec3&, const Vec3&) const { return false; }
public:
//! \brief Evaluates the secondary solution at a result point.

View File

@@ -12,7 +12,8 @@
//==============================================================================
#include "Elasticity.h"
#include "MaterialBase.h"
#include "LinIsotropic.h"
#include "FiniteElement.h"
#include "Utilities.h"
#include "ElmMats.h"
#include "ElmNorm.h"
@@ -51,7 +52,13 @@ void Elasticity::print (std::ostream& os) const
for (unsigned short int d = 0; d < nsd; d++)
std::cout <<" "<< grav[d];
std::cout << std::endl;
if (material) material->print(os);
if (!material)
{
static LinIsotropic defaultMat;
const_cast<Elasticity*>(this)->material = &defaultMat;
}
material->print(os);
}
@@ -575,8 +582,7 @@ ElmNorm& ElasticityNorm::getElmNormBuffer (LocalIntegral*& elmInt)
}
bool ElasticityNorm::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool ElasticityNorm::evalInt (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const
{
ElmNorm& pnorm = ElasticityNorm::getElmNormBuffer(elmInt);
@@ -587,19 +593,19 @@ bool ElasticityNorm::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the finite element stress field
Vector sigmah, sigma;
if (!problem.evalSol(sigmah,dNdX,X)) return false;
if (!problem.evalSol(sigmah,fe.dNdX,X)) return false;
// Integrate the energy norm a(u^h,u^h)
pnorm[0] += sigmah.dot(Cinv*sigmah)*detJW;
pnorm[0] += sigmah.dot(Cinv*sigmah)*fe.detJxW;
if (problem.haveLoads())
{
// Evaluate the body load
Vec3 f = problem.getBodyforce(X);
// Evaluate the displacement field
Vec3 u = problem.evalSol(N);
Vec3 u = problem.evalSol(fe.N);
// Integrate the external energy (f,u^h)
pnorm[1] += f*u*detJW;
pnorm[1] += f*u*fe.detJxW;
}
if (anasol)
@@ -607,18 +613,17 @@ bool ElasticityNorm::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the analytical stress field
sigma = (*anasol)(X);
// Integrate the energy norm a(u,u)
pnorm[2] += sigma.dot(Cinv*sigma)*detJW;
pnorm[2] += sigma.dot(Cinv*sigma)*fe.detJxW;
// Integrate the error in energy norm a(u-u^h,u-u^h)
sigma -= sigmah;
pnorm[3] += sigma.dot(Cinv*sigma)*detJW;
pnorm[3] += sigma.dot(Cinv*sigma)*fe.detJxW;
}
return true;
}
bool ElasticityNorm::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix&,
bool ElasticityNorm::evalBou (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
if (!problem.haveLoads()) return true;
@@ -628,9 +633,9 @@ bool ElasticityNorm::evalBou (LocalIntegral*& elmInt, double detJW,
// Evaluate the surface traction
Vec3 T = problem.getTraction(X,normal);
// Evaluate the displacement field
Vec3 u = problem.evalSol(N);
Vec3 u = problem.evalSol(fe.N);
// Integrate the external energy
pnorm[1] += T*u*detJW;
pnorm[1] += T*u*fe.detJxW;
return true;
}

View File

@@ -240,23 +240,17 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
//! \brief Returns the number of norm quantities.

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "LinearElasticity.h"
#include "FiniteElement.h"
#include "MaterialBase.h"
#include "Tensor.h"
#include "Vec3Oper.h"
@@ -24,8 +25,7 @@ LinearElasticity::LinearElasticity (unsigned short int n) : Elasticity(n)
}
bool LinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool LinearElasticity::evalInt (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const
{
bool lHaveStrains = false;
@@ -35,7 +35,7 @@ bool LinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
{
// Compute the strain-displacement matrix B from dNdX
// and evaluate the symmetric strain tensor if displacements are available
if (!this->kinematics(dNdX,eps,eps)) return false;
if (!this->kinematics(fe.dNdX,eps,eps)) return false;
if (!eps.isZero(1.0e-16)) lHaveStrains = true;
// Evaluate the constitutive matrix and the stress tensor at this point
@@ -47,36 +47,35 @@ bool LinearElasticity::evalInt (LocalIntegral*& elmInt, double detJW,
if (eKm)
{
// Integrate the material stiffness matrix
CB.multiply(Cmat,Bmat).multiply(detJW); // CB = C*B*|J|*w
CB.multiply(Cmat,Bmat).multiply(fe.detJxW); // CB = C*B*|J|*w
eKm->multiply(Bmat,CB,true,false,true); // EK += B^T * CB
}
if (eKg && lHaveStrains)
// Integrate the geometric stiffness matrix
this->formKG(*eKg,dNdX,sigma,detJW);
this->formKG(*eKg,fe.dNdX,sigma,fe.detJxW);
if (eM)
// Integrate the mass matrix
this->formMassMatrix(*eM,N,X,detJW);
this->formMassMatrix(*eM,fe.N,X,fe.detJxW);
if (iS && lHaveStrains)
{
// Integrate the internal forces
sigma *= -detJW;
sigma *= -fe.detJxW;
if (!Bmat.multiply(sigma,*iS,true,true)) // ES -= B^T*sigma
return false;
}
if (eS)
// Integrate the load vector due to gravitation and other body forces
this->formBodyForce(*eS,N,X,detJW);
this->formBodyForce(*eS,fe.N,X,fe.detJxW);
return this->getIntegralResult(elmInt);
}
bool LinearElasticity::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool LinearElasticity::evalBou (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
if (!tracFld)
@@ -98,9 +97,9 @@ bool LinearElasticity::evalBou (LocalIntegral*& elmInt, double detJW,
// Integrate the force vector
Vector& ES = *eS;
for (size_t a = 1; a <= N.size(); a++)
for (size_t a = 1; a <= fe.N.size(); a++)
for (unsigned short int i = 1; i <= nsd; i++)
ES(nsd*(a-1)+i) += T[i-1]*N(a)*detJW;
ES(nsd*(a-1)+i) += T[i-1]*fe.N(a)*fe.detJxW;
return this->getIntegralResult(elmInt);
}

View File

@@ -32,23 +32,17 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
private:

View File

@@ -12,6 +12,7 @@
//==============================================================================
#include "Poisson.h"
#include "FiniteElement.h"
#include "Utilities.h"
#include "ElmNorm.h"
#include "Tensor.h"
@@ -105,8 +106,7 @@ bool Poisson::initElementBou (const std::vector<int>& MNPC)
}
bool Poisson::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool Poisson::evalInt (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const
{
elmInt = &myMats;
@@ -116,20 +116,19 @@ bool Poisson::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the constitutive matrix at this point
if (!this->formCmatrix(C,X)) return false;
CB.multiply(C,dNdX,false,true).multiply(detJW); // CB = C*dNdX^T*|J|*w
eM->multiply(dNdX,CB,false,false,true); // EK += dNdX * CB
CB.multiply(C,fe.dNdX,false,true).multiply(fe.detJxW); // = C*dNdX^T*|J|*w
eM->multiply(fe.dNdX,CB,false,false,true); // EK += dNdX * CB
}
// Integrate heat source if defined
if (eS && heatSrc)
eS->add(N,(*heatSrc)(X)*detJW);
eS->add(fe.N,(*heatSrc)(X)*fe.detJxW);
return true;
}
bool Poisson::evalBou (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool Poisson::evalBou (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const
{
elmInt = &myMats;
@@ -155,7 +154,7 @@ bool Poisson::evalBou (LocalIntegral*& elmInt, double detJW,
tracVal.insert(std::make_pair(X,trac*normal));
// Integrate the Neumann value
eS->add(N,trac*detJW);
eS->add(fe.N,trac*fe.detJxW);
return true;
}
@@ -278,8 +277,7 @@ bool PoissonNorm::initElement (const std::vector<int>& MNPC)
}
bool PoissonNorm::evalInt (LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
bool PoissonNorm::evalInt (LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const
{
ElmNorm* eNorm = dynamic_cast<ElmNorm*>(elmInt);
@@ -295,20 +293,20 @@ bool PoissonNorm::evalInt (LocalIntegral*& elmInt, double detJW,
// Evaluate the finite element heat flux field
Vector sigmah;
if (!problem.evalSol(sigmah,dNdX,X)) return false;
if (!problem.evalSol(sigmah,fe.dNdX,X)) return false;
// Integrate the energy norm a(u^h,u^h)
ElmNorm& pnorm = *eNorm;
pnorm[0] += sigmah.dot(Cinv*sigmah)*detJW;
pnorm[0] += sigmah.dot(Cinv*sigmah)*fe.detJxW;
if (anasol)
{
// Evaluate the analytical heat flux
Vector sigma((*anasol)(X).ptr(),sigmah.size());
// Integrate the energy norm a(u,u)
pnorm[1] += sigma.dot(Cinv*sigma)*detJW;
pnorm[1] += sigma.dot(Cinv*sigma)*fe.detJxW;
// Integrate the error in energy norm a(u-u^h,u-u^h)
sigma -= sigmah;
pnorm[2] += sigma.dot(Cinv*sigma)*detJW;
pnorm[2] += sigma.dot(Cinv*sigma)*fe.detJxW;
}
return true;

View File

@@ -61,23 +61,17 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
//! \param[in] normal Boundary normal vector at current integration point
virtual bool evalBou(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalBou(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X, const Vec3& normal) const;
//! \brief Evaluates the secondary solution at a result point.
@@ -178,12 +172,9 @@ public:
//! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] detJW Jacobian determinant times integration point weight
//! \param[in] N Basis function values
//! \param[in] dNdX Basis function gradients
//! \param[in] fe Finite element data of current integration point
//! \param[in] X Cartesian coordinates of current integration point
virtual bool evalInt(LocalIntegral*& elmInt, double detJW,
const Vector& N, const Matrix& dNdX,
virtual bool evalInt(LocalIntegral*& elmInt, const FiniteElement& fe,
const Vec3& X) const;
//! \brief Returns the number of norm quantities.