added: FiniteElement::Jacobian for use on boundaries
This commit is contained in:
parent
89c065edc4
commit
95afb36eb2
@ -22,29 +22,30 @@ const auto check_matrix_equal = [](const Matrix& A, const DoubleVec& B)
|
||||
ASSERT_NEAR(A(i,j), B[i-1][j-1], 1e-13);
|
||||
};
|
||||
|
||||
static MxFiniteElement getFE()
|
||||
class MyFiniteElement : public MxFiniteElement
|
||||
{
|
||||
MxFiniteElement fe({6,6,4});
|
||||
for (size_t i = 1; i <= 2; ++i) {
|
||||
fe.grad(i).resize(6,2);
|
||||
fe.basis(i).resize(6);
|
||||
for (size_t j = 1; j <= 6; ++j) {
|
||||
fe.grad(i)(j,1) = 1.0+12*(i-1)+2*(j-1);
|
||||
fe.grad(i)(j,2) = 2.0+12*(i-1)+2*(j-1);
|
||||
fe.basis(i)(j) = j + 6*(i-1);
|
||||
public:
|
||||
MyFiniteElement() : MxFiniteElement({6,6,4})
|
||||
{
|
||||
for (size_t i = 1; i <= 2; ++i) {
|
||||
this->grad(i).resize(6,2);
|
||||
this->basis(i).resize(6);
|
||||
for (size_t j = 1; j <= 6; ++j) {
|
||||
this->grad(i)(j,1) = 1.0+12*(i-1)+2*(j-1);
|
||||
this->grad(i)(j,2) = 2.0+12*(i-1)+2*(j-1);
|
||||
this->basis(i)(j) = j + 6*(i-1);
|
||||
}
|
||||
}
|
||||
|
||||
this->grad(3).resize(4,2);
|
||||
this->basis(3).resize(4);
|
||||
for (size_t j = 1; j <= 4; ++j) {
|
||||
this->grad(3)(j,1) = 1.0 + 14.0 + 2*(j-1);
|
||||
this->grad(3)(j,2) = 2.0 + 14.0 + 2*(j-1);
|
||||
this->basis(3)(j) = 12 + j;
|
||||
}
|
||||
}
|
||||
|
||||
fe.grad(3).resize(4,2);
|
||||
fe.basis(3).resize(4);
|
||||
for (size_t j = 1; j <= 4; ++j) {
|
||||
fe.grad(3)(j,1) = 1.0 + 14.0 + 2*(j-1);
|
||||
fe.grad(3)(j,2) = 2.0 + 14.0 + 2*(j-1);
|
||||
fe.basis(3)(j) = 12 + j;
|
||||
}
|
||||
|
||||
return fe;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
@ -118,7 +119,7 @@ TESTI(TestEqualOrderOperators, Gradient)
|
||||
|
||||
TEST(TestCompatibleOperators, Laplacian)
|
||||
{
|
||||
MxFiniteElement fe = getFE();
|
||||
MyFiniteElement fe;
|
||||
|
||||
std::vector<Matrix> EM(3);
|
||||
EM[1].resize(6,6);
|
||||
@ -174,7 +175,7 @@ TEST(TestCompatibleOperators, Laplacian)
|
||||
|
||||
TEST(TestCompatibleOperators, Mass)
|
||||
{
|
||||
MxFiniteElement fe = getFE();
|
||||
MyFiniteElement fe;
|
||||
|
||||
std::vector<Matrix> EM_vec(3);
|
||||
EM_vec[1].resize(6,6);
|
||||
@ -204,7 +205,7 @@ TEST(TestCompatibleOperators, Mass)
|
||||
|
||||
TEST(TestCompatibleOperators, Source)
|
||||
{
|
||||
MxFiniteElement fe = getFE();
|
||||
MyFiniteElement fe;
|
||||
|
||||
Vectors EV_scalar(3);
|
||||
EV_scalar[1].resize(6);
|
||||
|
@ -691,41 +691,36 @@ bool ASMs2Dmx::integrate (Integrand& integrand, int lIndex,
|
||||
|
||||
for (int i = 0; i < nGauss && ok; i++, ip++, fe.iGP++)
|
||||
{
|
||||
// Local element coordinates and parameter values
|
||||
// Local element coordinates and parameter values
|
||||
// of current integration point
|
||||
if (gpar[0].size() > 1)
|
||||
{
|
||||
if (gpar[0].size() > 1)
|
||||
{
|
||||
fe.xi = xg[i];
|
||||
fe.u = param[0] = gpar[0](i+1,i1-p1+1);
|
||||
}
|
||||
if (gpar[1].size() > 1)
|
||||
{
|
||||
}
|
||||
if (gpar[1].size() > 1)
|
||||
{
|
||||
fe.eta = xg[i];
|
||||
fe.v = param[1] = gpar[1](i+1,i2-p2+1);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch basis function derivatives at current integration point
|
||||
// Fetch basis function derivatives at current integration point
|
||||
for (size_t b = 0; b < m_basis.size(); ++b)
|
||||
SplineUtils::extractBasis(splinex[b][ip],fe.basis(b+1),dNxdu[b]);
|
||||
|
||||
// Compute Jacobian inverse of the coordinate mapping and
|
||||
// basis function derivatives w.r.t. Cartesian coordinates
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
// Compute Jacobian inverse of the coordinate mapping and
|
||||
// basis function derivatives w.r.t. Cartesian coordinates
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
for (size_t b = 0; b < m_basis.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1)
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
if (edgeDir < 0) normal *= -1.0;
|
||||
|
||||
if (edgeDir < 0) normal *= -1.0;
|
||||
// Cartesian coordinates of current integration point
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
|
||||
// Cartesian coordinates of current integration point
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
|
||||
// Evaluate the integrand and accumulate element contributions
|
||||
fe.detJxW *= dS*wg[i];
|
||||
ok = integrand.evalBouMx(*A,fe,time,X,normal);
|
||||
// Evaluate the integrand and accumulate element contributions
|
||||
fe.detJxW *= dS*wg[i];
|
||||
ok = integrand.evalBouMx(*A,fe,time,X,normal);
|
||||
}
|
||||
|
||||
// Finalize the element quantities
|
||||
@ -777,9 +772,10 @@ bool ASMs2Dmx::integrate (Integrand& integrand,
|
||||
const int p2 = surf->order_v();
|
||||
const int n1 = surf->numCoefs_u();
|
||||
const int n2 = surf->numCoefs_v();
|
||||
const size_t nB = m_basis.size();
|
||||
|
||||
std::vector<size_t> elem_sizes2(elem_size);
|
||||
std::copy(elem_size.begin(), elem_size.end(), std::back_inserter(elem_sizes2));
|
||||
std::copy(elem_size.begin(),elem_size.end(),std::back_inserter(elem_sizes2));
|
||||
|
||||
MxFiniteElement fe(elem_sizes2);
|
||||
Matrix dNdu, Xnod, Jac;
|
||||
@ -877,27 +873,18 @@ bool ASMs2Dmx::integrate (Integrand& integrand,
|
||||
}
|
||||
|
||||
// Fetch basis function derivatives at current integration point
|
||||
Matrices dNxdu(m_basis.size()*2);
|
||||
for (size_t b = 0; b < m_basis.size(); ++b) {
|
||||
Matrices dNxdu(2*nB);
|
||||
for (size_t b = 1; b <= nB; b++) {
|
||||
Go::BasisDerivsSf spline;
|
||||
this->getBasis(b+1)->computeBasis(fe.u, fe.v, spline, edgeDir < 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b+1), dNxdu[b]);
|
||||
this->getBasis(b+1)->computeBasis(fe.u, fe.v, spline, edgeDir > 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b+1+m_basis.size()),
|
||||
dNxdu[b+m_basis.size()]);
|
||||
this->getBasis(b)->computeBasis(fe.u, fe.v, spline, edgeDir < 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b), dNxdu[b-1]);
|
||||
this->getBasis(b)->computeBasis(fe.u, fe.v, spline, edgeDir > 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(nB+b), dNxdu[nB+b-1]);
|
||||
}
|
||||
|
||||
// Compute basis function derivatives and the edge normal
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis+m_basis.size()),Xnod,
|
||||
dNxdu[itgBasis-1+m_basis.size()],t1,t2);
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
for (size_t b = 0; b < m_basis.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1) {
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
fe.grad(b+1+m_basis.size()).multiply(dNxdu[b+m_basis.size()],Jac);
|
||||
}
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2,nB))
|
||||
continue; // skip singular points
|
||||
|
||||
if (edgeDir < 0) normal *= -1.0;
|
||||
|
||||
|
@ -415,12 +415,12 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
|
||||
|
||||
for (int i = 0; i < nGauss && ok; i++, fe.iGP++)
|
||||
{
|
||||
// Gauss point coordinates along the edge
|
||||
xi[t1-1] = edgeDir < 0 ? -1.0 : 1.0;
|
||||
xi[t2-1] = xg[i];
|
||||
// Gauss point coordinates along the edge
|
||||
xi[t1-1] = edgeDir < 0 ? -1.0 : 1.0;
|
||||
xi[t2-1] = xg[i];
|
||||
|
||||
// Compute the basis functions and their derivatives, using
|
||||
// tensor product of one-dimensional Lagrange polynomials
|
||||
// Compute the basis functions and their derivatives, using
|
||||
// tensor product of one-dimensional Lagrange polynomials
|
||||
for (size_t b = 0; b < nxx.size(); ++b)
|
||||
if (!Lagrange::computeBasis(fe.basis(b+1),dNxdu[b],
|
||||
elem_sizes[b][0],xi[0],
|
||||
@ -428,23 +428,18 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
|
||||
ok = false;
|
||||
|
||||
// Compute basis function derivatives and the edge normal
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
for (size_t b = 0; b < nxx.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1)
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
if (edgeDir < 0) normal *= -1.0;
|
||||
|
||||
if (edgeDir < 0) normal *= -1.0;
|
||||
// Cartesian coordinates of current integration point
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
|
||||
// Cartesian coordinates of current integration point
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
|
||||
// Evaluate the integrand and accumulate element contributions
|
||||
fe.detJxW *= wg[i];
|
||||
if (ok && !integrand.evalBouMx(*A,fe,time,X,normal))
|
||||
ok = false;
|
||||
// Evaluate the integrand and accumulate element contributions
|
||||
fe.detJxW *= wg[i];
|
||||
if (ok && !integrand.evalBouMx(*A,fe,time,X,normal))
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// Finalize the element quantities
|
||||
@ -453,7 +448,7 @@ bool ASMs2DmxLag::integrate (Integrand& integrand, int lIndex,
|
||||
|
||||
// Assembly of global system integral
|
||||
if (ok && !glInt.assemble(A->ref(),fe.iel))
|
||||
ok = false;
|
||||
ok = false;
|
||||
|
||||
A->destruct();
|
||||
|
||||
|
@ -822,13 +822,8 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
|
||||
|
||||
// Compute Jacobian inverse of the coordinate mapping and
|
||||
// basis function derivatives w.r.t. Cartesian coordinates
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
|
||||
for (size_t b = 0; b < m_basis.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1)
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
if (faceDir < 0) normal *= -1.0;
|
||||
|
||||
@ -894,6 +889,7 @@ bool ASMs3Dmx::integrate (Integrand& integrand,
|
||||
const int n3 = svol->numCoefs(2);
|
||||
const int nel1 = n1 - p1 + 1;
|
||||
const int nel2 = n2 - p2 + 1;
|
||||
const size_t nB = m_basis.size();
|
||||
|
||||
std::vector<size_t> elem_sizes2(elem_size);
|
||||
std::copy(elem_size.begin(), elem_size.end(), std::back_inserter(elem_sizes2));
|
||||
@ -1028,27 +1024,18 @@ bool ASMs3Dmx::integrate (Integrand& integrand,
|
||||
}
|
||||
|
||||
// Fetch basis function derivatives at current integration point
|
||||
Matrices dNxdu(m_basis.size()*2);
|
||||
for (size_t b = 0; b < m_basis.size(); ++b) {
|
||||
Matrices dNxdu(2*nB);
|
||||
for (size_t b = 1; b <= nB; b++) {
|
||||
Go::BasisDerivs spline;
|
||||
this->getBasis(b+1)->computeBasis(fe.u, fe.v, fe.w, spline, faceDir < 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b+1), dNxdu[b]);
|
||||
this->getBasis(b+1)->computeBasis(fe.u, fe.v, fe.w, spline, faceDir > 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b+1+m_basis.size()),
|
||||
dNxdu[b+m_basis.size()]);
|
||||
this->getBasis(b)->computeBasis(fe.u, fe.v, fe.w, spline, faceDir < 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(b), dNxdu[b-1]);
|
||||
this->getBasis(b)->computeBasis(fe.u, fe.v, fe.w, spline, faceDir > 0);
|
||||
SplineUtils::extractBasis(spline, fe.basis(nB+b), dNxdu[nB+b-1]);
|
||||
}
|
||||
|
||||
// Compute basis function derivatives and the edge normal
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis+m_basis.size()),
|
||||
Xnod,dNxdu[itgBasis-1+m_basis.size()],t1,t2);
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
for (size_t b = 0; b < m_basis.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1) {
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
fe.grad(b+1+m_basis.size()).multiply(dNxdu[b+m_basis.size()],Jac);
|
||||
}
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2,nB))
|
||||
continue; // skip singular points
|
||||
|
||||
if (faceDir < 0) normal *= -1.0;
|
||||
|
||||
|
@ -493,19 +493,14 @@ bool ASMs3DmxLag::integrate (Integrand& integrand, int lIndex,
|
||||
elem_sizes[b][2],xi[2]))
|
||||
ok = false;
|
||||
|
||||
// Compute basis function derivatives and the edge normal
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
// Compute basis function derivatives and the edge normal
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
for (size_t b = 0; b < nxx.size(); ++b)
|
||||
if (b != (size_t)itgBasis-1)
|
||||
fe.grad(b+1).multiply(dNxdu[b],Jac);
|
||||
|
||||
if (faceDir < 0) normal *= -1.0;
|
||||
if (faceDir < 0) normal *= -1.0;
|
||||
|
||||
// Cartesian coordinates of current integration point
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
X.assign(Xnod * fe.basis(itgBasis));
|
||||
|
||||
// Evaluate the integrand and accumulate element contributions
|
||||
fe.detJxW *= wg[i]*wg[j];
|
||||
|
@ -98,6 +98,51 @@ bool MxFiniteElement::Jacobian (Matrix& Jac, const Matrix& Xnod,
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
If the input argument \a nBasis is half (or less than half) of the size of
|
||||
the internal basis function value array, it is used to flag that we are doing
|
||||
element interface terms, and the basis function values of both elements
|
||||
sharing the interface are stored internally. If \a nBasis is zero (default),
|
||||
it is reset to the size of the \a dNxdu argument, which will fit normal cases.
|
||||
*/
|
||||
|
||||
bool MxFiniteElement::Jacobian (Matrix& Jac, Vec3& n,
|
||||
const Matrix& Xnod,
|
||||
unsigned short int gBasis,
|
||||
const std::vector<Matrix>& dNxdu,
|
||||
size_t t1, size_t t2, size_t nBasis,
|
||||
const Matrix* Xnod2)
|
||||
{
|
||||
if (nBasis == 0) nBasis = dNxdu.size();
|
||||
const bool separateGeometry = nBasis > this->getNoBasis();
|
||||
if (separateGeometry) gBasis = nBasis;
|
||||
|
||||
Matrix dummy;
|
||||
if (2*nBasis <= this->getNoBasis())
|
||||
{
|
||||
// We are are doing interface terms, evaluate for the second element first
|
||||
detJxW = utl::Jacobian(Jac,n,this->grad(nBasis+gBasis),
|
||||
Xnod2 ? *Xnod2 : Xnod,
|
||||
dNxdu[nBasis+gBasis-1],t1,t2);
|
||||
|
||||
for (size_t b = 1; b <= nBasis; ++b)
|
||||
if (b != gBasis)
|
||||
this->grad(nBasis+b).multiply(dNxdu[nBasis+b-1],Jac);
|
||||
}
|
||||
else if (separateGeometry)
|
||||
nBasis = this->getNoBasis();
|
||||
|
||||
Matrix& dX = separateGeometry ? dummy : this->grad(gBasis);
|
||||
detJxW = utl::Jacobian(Jac,n,dX,Xnod,dNxdu[gBasis-1],t1,t2);
|
||||
|
||||
for (size_t b = 1; b <= nBasis; ++b)
|
||||
if (b != gBasis || separateGeometry)
|
||||
this->grad(b).multiply(dNxdu[b-1],Jac);
|
||||
|
||||
return detJxW != 0.0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
This method also calculates the second-derivatives of the basis functions
|
||||
with respect to the Cartesian coordinates, using the same geometry mapping
|
||||
@ -114,12 +159,11 @@ bool MxFiniteElement::Hessian (Matrix3D& Hess, const Matrix& Jac,
|
||||
const bool separateGeometry = nBasis > this->getNoBasis();
|
||||
bool ok;
|
||||
if (separateGeometry)
|
||||
ok = Hess.multiply(Xnod, (bf ? bf->back()->d2Ndu2 : d2Nxdu2->back()));
|
||||
else {
|
||||
ok = Hess.multiply(Xnod, bf ? bf->back()->d2Ndu2 : d2Nxdu2->back());
|
||||
else
|
||||
ok = utl::Hessian(Hess, this->hess(gBasis), Jac, Xnod,
|
||||
bf ? (*bf)[gBasis-1]->d2Ndu2 : (*d2Nxdu2)[gBasis-1],
|
||||
this->grad(gBasis));
|
||||
}
|
||||
|
||||
for (size_t b = 1; b <= this->getNoBasis() && ok; b++)
|
||||
if (b != gBasis || separateGeometry)
|
||||
|
@ -46,17 +46,17 @@ public:
|
||||
|
||||
//! \brief Returns a const reference to the basis function derivatives.
|
||||
virtual const Matrix& grad(char) const { return dNdX; }
|
||||
//! \brief Returns a reference to the basis function derivatives.
|
||||
virtual Matrix& grad(char) { return dNdX; }
|
||||
|
||||
//! \brief Returns a const reference to the basis function 2nd-derivatives.
|
||||
virtual const Matrix3D& hess(char) const { return d2NdX2; }
|
||||
//! \brief Returns a reference to the basis function 2nd-derivatives.
|
||||
virtual Matrix3D& hess(char) { return d2NdX2; }
|
||||
//! \brief Returns a const reference to the basis function 3nd-derivatives.
|
||||
virtual const Matrix4D& hess2(char) const { return d3NdX3; }
|
||||
|
||||
protected:
|
||||
//! \brief Returns a reference to the basis function derivatives.
|
||||
virtual Matrix& grad(char) { return dNdX; }
|
||||
//! \brief Returns a reference to the basis function 2nd-derivatives.
|
||||
virtual Matrix3D& hess(char) { return d2NdX2; }
|
||||
|
||||
//! \brief Writes the finite element object to the given output stream.
|
||||
virtual std::ostream& write(std::ostream& os) const;
|
||||
|
||||
@ -112,13 +112,8 @@ public:
|
||||
|
||||
//! \brief Returns a const reference to the basis function derivatives.
|
||||
virtual const Matrix& grad(char b) const { return b < 2 ? dNdX : dMdX[b-2]; }
|
||||
//! \brief Returns a reference to the basis function derivatives.
|
||||
virtual Matrix& grad(char b) { return b < 2 ? dNdX : dMdX[b-2]; }
|
||||
|
||||
//! \brief Returns a const reference to the basis function 2nd-derivatives.
|
||||
virtual const Matrix3D& hess(char b) const { return b < 2 ? d2NdX2 : d2MdX2[b-2]; }
|
||||
//! \brief Returns a reference to the basis function 2nd-derivatives.
|
||||
virtual Matrix3D& hess(char b) { return b < 2 ? d2NdX2 : d2MdX2[b-2]; }
|
||||
//! \brief Returns a const reference to the basis function 3rd-derivatives.
|
||||
virtual const Matrix4D& hess2(char b) const { return b < 2 ? d3NdX3 : d3MdX3[b-2]; }
|
||||
|
||||
@ -133,6 +128,22 @@ public:
|
||||
const std::vector<const BasisFunctionVals*>* bf,
|
||||
const std::vector<Matrix>* dNxdu = nullptr);
|
||||
|
||||
//! \brief Sets up the Jacobian matrix of the coordinate mapping on a boundary.
|
||||
//! \param[out] Jac The inverse of the Jacobian matrix
|
||||
//! \param[out] n Outward-directed unit normal vector on the boundary
|
||||
//! \param[in] Xnod Matrix of element nodal coordinates
|
||||
//! \param[in] gBasis 1-based index of basis representing the geometry
|
||||
//! \param[in] dNxdu First order derivatives of basis functions
|
||||
//! \param[in] t1 First parametric tangent direction of the boundary
|
||||
//! \param[in] t2 Second parametric tangent direction of the boundary
|
||||
//! \param[in] nBasis Number of basis functions
|
||||
//! \param[in] Xnod2 Matrix of element nodal coordinates for neighbor element
|
||||
bool Jacobian(Matrix& Jac, Vec3& n, const Matrix& Xnod,
|
||||
unsigned short int gBasis,
|
||||
const std::vector<Matrix>& dNxdu,
|
||||
size_t t1, size_t t2, size_t nBasis = 0,
|
||||
const Matrix* Xnod2 = nullptr);
|
||||
|
||||
//! \brief Sets up the Hessian matrix of the coordinate mapping.
|
||||
//! \param[out] Hess The Hessian matrix
|
||||
//! \param[in] Jac The inverse of the Jacobian matrix
|
||||
@ -146,6 +157,11 @@ public:
|
||||
const std::vector<Matrix3D>* d2Nxdu2 = nullptr);
|
||||
|
||||
protected:
|
||||
//! \brief Returns a reference to the basis function derivatives.
|
||||
virtual Matrix& grad(char b) { return b < 2 ? dNdX : dMdX[b-2]; }
|
||||
//! \brief Returns a reference to the basis function 2nd-derivatives.
|
||||
virtual Matrix3D& hess(char b) { return b < 2 ? d2NdX2 : d2MdX2[b-2]; }
|
||||
|
||||
//! \brief Writes the finite element object to the given output stream.
|
||||
virtual std::ostream& write(std::ostream& os) const;
|
||||
|
||||
|
@ -574,13 +574,8 @@ bool ASMu2Dmx::integrate (Integrand& integrand, int lIndex,
|
||||
|
||||
// Compute Jacobian inverse of the coordinate mapping and
|
||||
// basis function derivatives w.r.t. Cartesian coordinates
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
|
||||
for (size_t b = 1; b <= m_basis.size(); ++b)
|
||||
if ((int)b != itgBasis)
|
||||
fe.grad(b).multiply(dNxdu[b-1],Jac);
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
if (edgeDir < 0)
|
||||
normal *= -1.0;
|
||||
@ -632,6 +627,8 @@ bool ASMu2Dmx::integrate (Integrand& integrand,
|
||||
const double* wg = GaussQuadrature::getWeight(nGP);
|
||||
if (!xg || !wg) return false;
|
||||
|
||||
const size_t nB = m_basis.size();
|
||||
|
||||
Matrix Xnod, Jac;
|
||||
Vec4 X(nullptr,time.t);
|
||||
Vec3 normal;
|
||||
@ -747,31 +744,18 @@ bool ASMu2Dmx::integrate (Integrand& integrand,
|
||||
fe.v = gpar[1][g];
|
||||
|
||||
// Evaluate basis function derivatives at current integration points
|
||||
std::vector<Matrix> dNxdu(m_basis.size()*2);
|
||||
for (size_t b=0; b < m_basis.size(); ++b) {
|
||||
std::vector<Matrix> dNxdu(2*nB);
|
||||
for (size_t b = 0; b < nB; b++) {
|
||||
Go::BasisDerivsSf spline;
|
||||
this->computeBasis(fe.u+epsu, fe.v+epsv, spline, els[b]-1, m_basis[b].get());
|
||||
SplineUtils::extractBasis(spline,fe.basis(b+1),dNxdu[b]);
|
||||
this->computeBasis(fe.u-epsu, fe.v-epsv, spline, els2[b]-1, m_basis[b].get());
|
||||
SplineUtils::extractBasis(spline,fe.basis(b+1+m_basis.size()),
|
||||
dNxdu[b+m_basis.size()]);
|
||||
SplineUtils::extractBasis(spline,fe.basis(nB+b+1),dNxdu[nB+b]);
|
||||
}
|
||||
|
||||
// Compute Jacobian inverse of the coordinate mapping and
|
||||
// basis function derivatives w.r.t. Cartesian coordinates
|
||||
fe.detJxW = utl::Jacobian(Jac2,normal,
|
||||
fe.grad(itgBasis+m_basis.size()),Xnod2,
|
||||
dNxdu[itgBasis-1+m_basis.size()],t1,t2);
|
||||
fe.detJxW = utl::Jacobian(Jac,normal,
|
||||
fe.grad(itgBasis),Xnod,
|
||||
dNxdu[itgBasis-1],t1,t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
|
||||
for (size_t b = 1; b <= m_basis.size(); ++b)
|
||||
if ((int)b != itgBasis) {
|
||||
fe.grad(b).multiply(dNxdu[b-1],Jac);
|
||||
fe.grad(b+m_basis.size()).multiply(dNxdu[b-1+m_basis.size()],Jac);
|
||||
}
|
||||
// Compute basis function derivatives and the edge normal
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2,nB,&Xnod2))
|
||||
continue; // skip singular points
|
||||
|
||||
if (edgeDir < 0)
|
||||
normal *= -1.0;
|
||||
|
@ -376,6 +376,7 @@ bool ASMu3Dmx::integrate (Integrand& integrand,
|
||||
{
|
||||
// --- Compute average value of basis functions over the element -----
|
||||
|
||||
Matrix dNdX;
|
||||
fe.Navg.resize(elem_sizes[0],true);
|
||||
double vol = 0.0;
|
||||
size_t jp = 0;
|
||||
@ -388,8 +389,7 @@ bool ASMu3Dmx::integrate (Integrand& integrand,
|
||||
|
||||
// Compute Jacobian determinant of coordinate mapping
|
||||
// and multiply by weight of current integration point
|
||||
double detJac = utl::Jacobian(Jac,fe.grad(itgBasis),
|
||||
Xnod,bfs.dNdu,false);
|
||||
double detJac = utl::Jacobian(Jac,dNdX,Xnod,bfs.dNdu,false);
|
||||
double weight = dV*wg[0][i]*wg[1][j]*wg[2][k];
|
||||
|
||||
// Numerical quadrature
|
||||
@ -634,13 +634,8 @@ bool ASMu3Dmx::integrate (Integrand& integrand, int lIndex,
|
||||
this->evaluateBasis(iEl, fe, dNxdu[b-1], b);
|
||||
|
||||
// Compute basis function derivatives and the face normal
|
||||
fe.detJxW = utl::Jacobian(Jac, normal, fe.grad(itgBasis), Xnod,
|
||||
dNxdu[itgBasis-1], t1, t2);
|
||||
if (fe.detJxW == 0.0) continue; // skip singular points
|
||||
|
||||
for (size_t b = 1; b <= m_basis.size(); ++b)
|
||||
if ((int)b != itgBasis)
|
||||
fe.grad(b).multiply(dNxdu[b-1],Jac);
|
||||
if (!fe.Jacobian(Jac,normal,Xnod,itgBasis,dNxdu,t1,t2))
|
||||
continue; // skip singular points
|
||||
|
||||
if (faceDir < 0) normal *= -1.0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user