Added: Geometry mapping for shells (two-parametric models in 3D space).

Changed: No need to provide the basis size to FiniteElement constructor.
This commit is contained in:
Knut Morten Okstad 2018-02-10 07:43:57 +01:00
parent a1199376e2
commit f9754b1912
4 changed files with 148 additions and 61 deletions

View File

@ -1663,6 +1663,9 @@ bool ASMs2D::integrate (Integrand& integrand,
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu); fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points if (fe.detJxW == 0.0) continue; // skip singular points
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
X.assign(Xnod * fe.N); X.assign(Xnod * fe.N);
X.t = time.t; X.t = time.t;
@ -1710,6 +1713,8 @@ bool ASMs2D::integrate (Integrand& integrand,
// Compute G-matrix // Compute G-matrix
if (integrand.getIntegrandType() & Integrand::G_MATRIX) if (integrand.getIntegrandType() & Integrand::G_MATRIX)
utl::getGmat(Jac,dXidu,fe.G); utl::getGmat(Jac,dXidu,fe.G);
else if (nsd > 2)
fe.G = Jac; // Store tangent vectors in fe.G for shells
#if SP_DEBUG > 4 #if SP_DEBUG > 4
if (iel == dbgElm || iel == -dbgElm || dbgElm == 0) if (iel == dbgElm || iel == -dbgElm || dbgElm == 0)
@ -1718,6 +1723,8 @@ bool ASMs2D::integrate (Integrand& integrand,
<<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX; <<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX;
if (!fe.d2NdX2.empty()) if (!fe.d2NdX2.empty())
std::cout <<"d2NdX2 ="<< fe.d2NdX2; std::cout <<"d2NdX2 ="<< fe.d2NdX2;
if (!fe.G.empty())
std::cout <<"G ="<< fe.G;
} }
#endif #endif
@ -1745,7 +1752,7 @@ bool ASMs2D::integrate (Integrand& integrand,
A->destruct(); A->destruct();
#ifdef SP_DEBUG #ifdef SP_DEBUG
if (iel == -dbgElm) break; // Skipping all elements, except for -dbgElm if (iel == -dbgElm) break; // Skipping all elements, except for -dbgElm
#endif #endif
} }
} }
@ -1900,6 +1907,8 @@ bool ASMs2D::integrate (Integrand& integrand,
// Compute G-matrix // Compute G-matrix
if (integrand.getIntegrandType() & Integrand::G_MATRIX) if (integrand.getIntegrandType() & Integrand::G_MATRIX)
utl::getGmat(Jac,dXidu,fe.G); utl::getGmat(Jac,dXidu,fe.G);
else if (nsd > 2)
fe.G = Jac; // Store tangent vectors in fe.G for shells
#if SP_DEBUG > 4 #if SP_DEBUG > 4
if (iel == dbgElm || iel == -dbgElm || dbgElm == 0) if (iel == dbgElm || iel == -dbgElm || dbgElm == 0)
@ -1932,7 +1941,7 @@ bool ASMs2D::integrate (Integrand& integrand,
A->destruct(); A->destruct();
#ifdef SP_DEBUG #ifdef SP_DEBUG
if (iel == -dbgElm) break; // Skipping all elements, except for -dbgElm if (iel == -dbgElm) break; // Skipping all elements, except for -dbgElm
#endif #endif
} }
} }
@ -2056,6 +2065,9 @@ bool ASMs2D::integrate (Integrand& integrand,
if (edgeDir < 0) normal *= -1.0; if (edgeDir < 0) normal *= -1.0;
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
X.assign(Xnod * fe.N); X.assign(Xnod * fe.N);
X.t = time.t; X.t = time.t;
@ -2253,6 +2265,8 @@ bool ASMs2D::integrate (Integrand& integrand, int lIndex,
// Compute G-matrix // Compute G-matrix
if (integrand.getIntegrandType() & Integrand::G_MATRIX) if (integrand.getIntegrandType() & Integrand::G_MATRIX)
utl::getGmat(Jac,dXidu,fe.G); utl::getGmat(Jac,dXidu,fe.G);
else if (nsd > 2)
fe.G = Jac; // Store tangent vectors in fe.G for shells
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
X.assign(Xnod * fe.N); X.assign(Xnod * fe.N);
@ -2643,6 +2657,9 @@ bool ASMs2D::evalSolution (Matrix& sField, const IntegrandBase& integrand,
if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xtmp,d2Ndu2,fe.dNdX)) if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xtmp,d2Ndu2,fe.dNdX))
continue; continue;
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Now evaluate the solution field // Now evaluate the solution field
if (!integrand.evalSol(solPt,fe,Xtmp*fe.N,ip)) if (!integrand.evalSol(solPt,fe,Xtmp*fe.N,ip))
return false; return false;

View File

@ -337,7 +337,7 @@ bool ASMu2D::checkElementSize (int elmId, bool globalNum) const
elmId = it - MLGE.begin(); elmId = it - MLGE.begin();
} }
if (elmId < lrspline->nElements()) if (elmId >= 0 && elmId < lrspline->nElements())
return lrspline->getElement(elmId)->area() > aMin+1.0e-12; return lrspline->getElement(elmId)->area() > aMin+1.0e-12;
else else
return false; return false;
@ -406,7 +406,7 @@ bool ASMu2D::raiseOrder (int ru, int rv)
bool ASMu2D::evaluateBasis (FiniteElement& fe, int derivs) const bool ASMu2D::evaluateBasis (FiniteElement& fe, int derivs) const
{ {
LR::Element* el = lrspline->getElement(fe.iel-1); const LR::Element* el = lrspline->getElement(fe.iel-1);
if (!el) return false; if (!el) return false;
fe.xi = 2.0*(fe.u - el->umin()) / (el->umax() - el->umin()) - 1.0; fe.xi = 2.0*(fe.u - el->umin()) / (el->umax() - el->umin()) - 1.0;
@ -870,7 +870,7 @@ double ASMu2D::getParametricLength (int iel, int dir) const
} }
#endif #endif
LR::Element* el = lrspline->getElement(iel-1); const LR::Element* el = lrspline->getElement(iel-1);
switch (dir) switch (dir)
{ {
case 1: return el->vmax() - el->vmin(); case 1: return el->vmax() - el->vmin();
@ -894,7 +894,7 @@ bool ASMu2D::getElementCoordinates (Matrix& X, int iel) const
} }
#endif #endif
LR::Element* el = lrspline->getElement(iel-1); const LR::Element* el = lrspline->getElement(iel-1);
X.resize(nsd,el->nBasisFunctions()); X.resize(nsd,el->nBasisFunctions());
int n = 1; int n = 1;
@ -979,7 +979,7 @@ double ASMu2D::getElementCorners (int iel, Vec3Vec& XC) const
} }
#endif #endif
LR::Element* el = lrspline->getElement(iel-1); const LR::Element* el = lrspline->getElement(iel-1);
double u[4] = { el->umin(), el->umax(), el->umin(), el->umax() }; double u[4] = { el->umin(), el->umax(), el->umin(), el->umax() };
double v[4] = { el->vmin(), el->vmin(), el->vmax(), el->vmax() }; double v[4] = { el->vmin(), el->vmin(), el->vmax(), el->vmax() };
@ -1036,12 +1036,12 @@ bool ASMu2D::integrate (Integrand& integrand,
continue; continue;
int iel = threadGroups[0][t][e] + 1; int iel = threadGroups[0][t][e] + 1;
#ifdef SP_DEBUG #ifdef SP_DEBUG
if (dbgElm < 0 && iel != -dbgElm) if (dbgElm < 0 && iel != -dbgElm)
continue; // Skipping all elements, except for -dbgElm continue; // Skipping all elements, except for -dbgElm
#endif #endif
FiniteElement fe(MNPC[iel-1].size());
FiniteElement fe;
fe.iel = MLGE[iel-1]; fe.iel = MLGE[iel-1];
Matrix dNdu, Xnod, Jac; Matrix dNdu, Xnod, Jac;
Matrix3D d2Ndu2, Hess; Matrix3D d2Ndu2, Hess;
@ -1083,21 +1083,22 @@ bool ASMu2D::integrate (Integrand& integrand,
double u0 = 0.5*(gpar[0].front() + gpar[0].back()); double u0 = 0.5*(gpar[0].front() + gpar[0].back());
double v0 = 0.5*(gpar[1].front() + gpar[1].back()); double v0 = 0.5*(gpar[1].front() + gpar[1].back());
lrspline->point(X0,u0,v0); lrspline->point(X0,u0,v0);
for (unsigned char i = 0; i < nsd; i++) X = SplineUtils::toVec3(X0,nsd);
X[i] = X0[i];
} }
if (integrand.getIntegrandType() & Integrand::G_MATRIX) if (integrand.getIntegrandType() & Integrand::G_MATRIX)
{ {
// Element size in parametric space // Element size in parametric space
dXidu[0] = lrspline->getElement(iel-1)->umax()-lrspline->getElement(iel-1)->umin(); const LR::Element* el = lrspline->getElement(iel-1);
dXidu[1] = lrspline->getElement(iel-1)->vmax()-lrspline->getElement(iel-1)->vmin(); dXidu[0] = el->umax() - el->umin();
dXidu[1] = el->vmax() - el->vmin();
} }
// Initialize element quantities // Initialize element quantities
LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel); LocalIntegral* A = integrand.getLocalIntegral(MNPC[iel-1].size(),fe.iel);
if (!integrand.initElement(MNPC[iel-1],fe,X,nRed*nRed,*A)) if (!integrand.initElement(MNPC[iel-1],fe,X,nRed*nRed,*A))
{ {
A->destruct();
ok = false; ok = false;
continue; continue;
} }
@ -1124,6 +1125,10 @@ bool ASMu2D::integrate (Integrand& integrand,
// Compute Jacobian inverse and derivatives // Compute Jacobian inverse and derivatives
fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu); fe.detJxW = utl::Jacobian(Jac,fe.dNdX,Xnod,dNdu);
if (fe.detJxW == 0.0) continue; // skip singular points
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
X.assign(Xnod * fe.N); X.assign(Xnod * fe.N);
@ -1132,10 +1137,7 @@ bool ASMu2D::integrate (Integrand& integrand,
// Compute the reduced integration terms of the integrand // Compute the reduced integration terms of the integrand
fe.detJxW *= 0.25*dA*wr[i]*wr[j]; fe.detJxW *= 0.25*dA*wr[i]*wr[j];
if (!integrand.reducedInt(*A,fe,X)) if (!integrand.reducedInt(*A,fe,X))
{
ok = false; ok = false;
continue;
}
} }
} }
@ -1197,10 +1199,12 @@ bool ASMu2D::integrate (Integrand& integrand,
// Compute G-matrix // Compute G-matrix
if (integrand.getIntegrandType() & Integrand::G_MATRIX) if (integrand.getIntegrandType() & Integrand::G_MATRIX)
utl::getGmat(Jac,dXidu,fe.G); utl::getGmat(Jac,dXidu,fe.G);
else if (nsd > 2)
fe.G = Jac; // Store tangent vectors in fe.G for shells
#if SP_DEBUG > 4 #if SP_DEBUG > 4
if (iel == dbgElm || iel == -dbgElm || dbgElm == 0) if (iel == dbgElm || iel == -dbgElm || dbgElm == 0)
std::cout <<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX; std::cout <<"\n"<< fe;
#endif #endif
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
@ -1209,33 +1213,26 @@ bool ASMu2D::integrate (Integrand& integrand,
// Evaluate the integrand and accumulate element contributions // Evaluate the integrand and accumulate element contributions
fe.detJxW *= 0.25*dA*wg[i]*wg[j]; fe.detJxW *= 0.25*dA*wg[i]*wg[j];
#ifndef USE_OPENMP
PROFILE3("Integrand::evalInt"); PROFILE3("Integrand::evalInt");
#endif
if (!integrand.evalInt(*A,fe,time,X)) if (!integrand.evalInt(*A,fe,time,X))
{
ok = false; ok = false;
continue;
}
} }
// Finalize the element quantities // Finalize the element quantities
if (!integrand.finalizeElement(*A,time,firstIp+jp)) if (ok && !integrand.finalizeElement(*A,time,firstIp+jp))
{
ok = false; ok = false;
continue;
}
// Assembly of global system integral // Assembly of global system integral
if (!glInt.assemble(A->ref(),fe.iel)) if (ok && !glInt.assemble(A->ref(),fe.iel))
{
ok = false; ok = false;
continue;
}
A->destruct(); A->destruct();
#ifdef SP_DEBUG #ifdef SP_DEBUG
if (iel == -dbgElm) if (iel == -dbgElm)
continue; // Skipping all elements, except for -dbgElm break; // Skipping all elements, except for -dbgElm
#endif #endif
} }
} }
@ -1281,7 +1278,8 @@ bool ASMu2D::integrate (Integrand& integrand,
if (dbgElm < 0 && iel != -dbgElm) if (dbgElm < 0 && iel != -dbgElm)
continue; // Skipping all elements, except for -dbgElm continue; // Skipping all elements, except for -dbgElm
#endif #endif
FiniteElement fe(MNPC[iel-1].size());
FiniteElement fe;
fe.iel = MLGE[iel-1]; fe.iel = MLGE[iel-1];
Matrix dNdu, Xnod, Jac; Matrix dNdu, Xnod, Jac;
Matrix3D d2Ndu2, Hess; Matrix3D d2Ndu2, Hess;
@ -1313,7 +1311,7 @@ bool ASMu2D::integrate (Integrand& integrand,
} }
// Initialize element quantities // Initialize element quantities
LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel); LocalIntegral* A = integrand.getLocalIntegral(MNPC[iel-1].size(),fe.iel);
if (!integrand.initElement(MNPC[iel-1],fe,X,0,*A)) if (!integrand.initElement(MNPC[iel-1],fe,X,0,*A))
{ {
ok = false; ok = false;
@ -1332,7 +1330,7 @@ bool ASMu2D::integrate (Integrand& integrand,
fe.u = elmPts[ip][0]; fe.u = elmPts[ip][0];
fe.v = elmPts[ip][1]; fe.v = elmPts[ip][1];
// Compute basis function derivatives at current integration point // Compute basis function derivatives at current integration point
if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES) { if (integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES) {
Go::BasisDerivsSf2 spline; Go::BasisDerivsSf2 spline;
lrspline->computeBasis(fe.u,fe.v,spline,iel-1); lrspline->computeBasis(fe.u,fe.v,spline,iel-1);
@ -1356,10 +1354,12 @@ bool ASMu2D::integrate (Integrand& integrand,
continue; continue;
} }
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
#if SP_DEBUG > 4 #if SP_DEBUG > 4
if (iel == dbgElm || iel == -dbgElm || dbgElm == 0) if (iel == dbgElm || iel == -dbgElm || dbgElm == 0)
std::cout <<"\niel, ip = "<< iel <<" "<< ip std::cout <<"\n"<< fe;
<<"\nN ="<< fe.N <<"dNdX ="<< fe.dNdX;
#endif #endif
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
@ -1369,29 +1369,27 @@ bool ASMu2D::integrate (Integrand& integrand,
// Evaluate the integrand and accumulate element contributions // Evaluate the integrand and accumulate element contributions
fe.detJxW *= 0.25*dA*elmPts[ip][2]; fe.detJxW *= 0.25*dA*elmPts[ip][2];
#ifndef USE_OPENMP
PROFILE3("Integrand::evalInt"); PROFILE3("Integrand::evalInt");
#endif
if (!integrand.evalInt(*A,fe,time,X)) if (!integrand.evalInt(*A,fe,time,X))
{
ok = false; ok = false;
continue;
}
} }
// Finalize the element quantities // Finalize the element quantities
if (!integrand.finalizeElement(*A,time,firstIp+MPitg[iel])) if (ok && !integrand.finalizeElement(*A,time,firstIp+MPitg[iel]))
{
ok = false; ok = false;
continue;
}
// Assembly of global system integral // Assembly of global system integral
if (!glInt.assemble(A->ref(),fe.iel)) if (ok && !glInt.assemble(A->ref(),fe.iel))
{
ok = false; ok = false;
continue;
}
A->destruct(); A->destruct();
#ifdef SP_DEBUG
if (iel == -dbgElm)
break; // Skipping all elements, except for -dbgElm
#endif
} }
} }
@ -1438,6 +1436,7 @@ bool ASMu2D::integrate (Integrand& integrand, int lIndex,
std::map<char,size_t>::const_iterator iit = firstBp.find(lIndex%10); std::map<char,size_t>::const_iterator iit = firstBp.find(lIndex%10);
size_t firstp = iit == firstBp.end() ? 0 : iit->second; size_t firstp = iit == firstBp.end() ? 0 : iit->second;
FiniteElement fe;
Matrix dNdu, Xnod, Jac; Matrix dNdu, Xnod, Jac;
double param[3] = { 0.0, 0.0, 0.0 }; double param[3] = { 0.0, 0.0, 0.0 };
Vec4 X(param); Vec4 X(param);
@ -1473,10 +1472,10 @@ bool ASMu2D::integrate (Integrand& integrand, int lIndex,
if (!this->getElementCoordinates(Xnod,iel)) return false; if (!this->getElementCoordinates(Xnod,iel)) return false;
// Initialize element quantities // Initialize element quantities
FiniteElement fe((**el).nBasisFunctions());
fe.iel = MLGE[iel-1]; fe.iel = MLGE[iel-1];
fe.xi = fe.eta = edgeDir < 0 ? -1.0 : 1.0; fe.xi = fe.eta = edgeDir < 0 ? -1.0 : 1.0;
LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel,true); LocalIntegral* A = integrand.getLocalIntegral(MNPC[iel-1].size(),
fe.iel,true);
if (!integrand.initElementBou(MNPC[iel-1],*A)) return false; if (!integrand.initElementBou(MNPC[iel-1],*A)) return false;
// Get integration gauss points over this element // Get integration gauss points over this element
@ -1512,6 +1511,9 @@ bool ASMu2D::integrate (Integrand& integrand, int lIndex,
if (edgeDir < 0) normal *= -1.0; if (edgeDir < 0) normal *= -1.0;
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Cartesian coordinates of current integration point // Cartesian coordinates of current integration point
X.assign(Xnod * fe.N); X.assign(Xnod * fe.N);
X.t = time.t; X.t = time.t;
@ -1666,6 +1668,7 @@ bool ASMu2D::tesselate (ElementBlock& grid, const int* npe) const
grid.unStructResize(nElements * nSubElPerElement, grid.unStructResize(nElements * nSubElPerElement,
nElements * nNodesPerElement); nElements * nNodesPerElement);
Go::Point pt;
std::vector<LR::Element*>::iterator el; std::vector<LR::Element*>::iterator el;
int inod = 0; int inod = 0;
int iel = 0; int iel = 0;
@ -1676,15 +1679,12 @@ bool ASMu2D::tesselate (ElementBlock& grid, const int* npe) const
double vmin = (**el).vmin(); double vmin = (**el).vmin();
double vmax = (**el).vmax(); double vmax = (**el).vmax();
for(int iv=0; iv<npe[1]; iv++) { for(int iv=0; iv<npe[1]; iv++) {
for(int iu=0; iu<npe[0]; iu++) { for(int iu=0; iu<npe[0]; iu++, inod++) {
double u = umin + (umax-umin)/(npe[0]-1)*iu; double u = umin + (umax-umin)/(npe[0]-1)*iu;
double v = vmin + (vmax-vmin)/(npe[1]-1)*iv; double v = vmin + (vmax-vmin)/(npe[1]-1)*iv;
Go::Point pt;
lrspline->point(pt, u,v, iel, iu!=npe[0]-1, iv!=npe[1]-1); lrspline->point(pt, u,v, iel, iu!=npe[0]-1, iv!=npe[1]-1);
grid.setCoor(inod, SplineUtils::toVec3(pt,nsd));
grid.setParams(inod, u, v); grid.setParams(inod, u, v);
for(int dim=0; dim<nsd; dim++)
grid.setCoor(inod, dim, pt[dim]);
inod++;
} }
} }
} }
@ -1741,6 +1741,7 @@ bool ASMu2D::evalSolution (Matrix& sField, const Vector& locSol,
if (nPoints != gpar[1].size()) if (nPoints != gpar[1].size())
return false; return false;
FiniteElement fe;
Vector ptSol; Vector ptSol;
Matrix dNdu, dNdX, Jac, Xnod, eSol, ptDer; Matrix dNdu, dNdX, Jac, Xnod, eSol, ptDer;
Matrix3D d2Ndu2, d2NdX2, Hess, ptDer2; Matrix3D d2Ndu2, d2NdX2, Hess, ptDer2;
@ -1756,7 +1757,6 @@ bool ASMu2D::evalSolution (Matrix& sField, const Vector& locSol,
// Fetch element containing evaluation point. // Fetch element containing evaluation point.
// Sadly, points are not always ordered in the same way as the elements. // Sadly, points are not always ordered in the same way as the elements.
int iel = lrspline->getElementContaining(gpar[0][i],gpar[1][i]); int iel = lrspline->getElementContaining(gpar[0][i],gpar[1][i]);
FiniteElement fe(lrspline->getElement(iel)->nBasisFunctions());
fe.iel = iel + 1; fe.iel = iel + 1;
fe.u = gpar[0][i]; fe.u = gpar[0][i];
fe.v = gpar[1][i]; fe.v = gpar[1][i];
@ -1881,19 +1881,19 @@ bool ASMu2D::evalSolution (Matrix& sField, const IntegrandBase& integrand,
if (nPoints != gpar[1].size()) if (nPoints != gpar[1].size())
return false; return false;
FiniteElement fe(0,firstIp);
Vector solPt; Vector solPt;
Matrix dNdu, Jac, Xnod; Matrix dNdu, Jac, Xnod;
Matrix3D d2Ndu2, Hess; Matrix3D d2Ndu2, Hess;
// Evaluate the secondary solution field at each point // Evaluate the secondary solution field at each point
for (size_t i = 0; i < nPoints; i++) for (size_t i = 0; i < nPoints; i++, fe.iGP++)
{ {
// Fetch element containing evaluation point // Fetch element containing evaluation point
// sadly, points are not always ordered in the same way as the elements // sadly, points are not always ordered in the same way as the elements
int iel = lrspline->getElementContaining(gpar[0][i],gpar[1][i]); int iel = lrspline->getElementContaining(gpar[0][i],gpar[1][i]);
// Evaluate the basis functions at current parametric point // Evaluate the basis functions at current parametric point
FiniteElement fe(lrspline->getElement(iel)->nBasisFunctions(),firstIp+i);
if (use2ndDer) if (use2ndDer)
{ {
Go::BasisDerivsSf2 spline; Go::BasisDerivsSf2 spline;
@ -1918,6 +1918,9 @@ bool ASMu2D::evalSolution (Matrix& sField, const IntegrandBase& integrand,
if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xnod,d2Ndu2,dNdu)) if (!utl::Hessian(Hess,fe.d2NdX2,Jac,Xnod,d2Ndu2,dNdu))
continue; continue;
// Store tangent vectors in fe.G for shells
if (nsd > 2) fe.G = Jac;
// Now evaluate the solution field // Now evaluate the solution field
if (!integrand.evalSol(solPt,fe,Xnod*fe.N,MNPC[iel])) if (!integrand.evalSol(solPt,fe,Xnod*fe.N,MNPC[iel]))
return false; return false;

View File

@ -36,6 +36,20 @@ Real utl::Jacobian (matrix<Real>& J, matrix<Real>& dNdX,
// Compute the length of the tangent vector {X},u // Compute the length of the tangent vector {X},u
detJ = J.getColumn(1).norm2(); // |J| = sqrt(X,u*X,u + Y,u*Y,u + Z,u*Z,u) detJ = J.getColumn(1).norm2(); // |J| = sqrt(X,u*X,u + Y,u*Y,u + Z,u*Z,u)
} }
else if (J.cols() == 2 && J.rows() > 2)
{
// Special for two-parametric elements in 3-dimensional space (shell)
dNdX = dNdu;
// Compute the length of the normal vector {X},u x {X},v
Vec3 a1 = J.getColumn(1);
Vec3 a2 = J.getColumn(2);
detJ = Vec3(a1,a2).length();
// Store the two tangent vectors in J
a1.normalize();
a2.normalize();
J.fillColumn(1,a1.ptr());
J.fillColumn(2,a2.ptr());
}
else else
{ {
// Compute the Jacobian determinant and inverse // Compute the Jacobian determinant and inverse
@ -97,6 +111,15 @@ Real utl::Jacobian (matrix<Real>& J, Vec3& n, matrix<Real>& dNdX,
dS = v2.normalize(); // dA = |v2| dS = v2.normalize(); // dA = |v2|
v3.normalize(); v3.normalize();
n.cross(v2,v3); // n = v2 x v3 / (|v2|*|v3|) n.cross(v2,v3); // n = v2 x v3 / (|v2|*|v3|)
if (J.rows() > 2)
{
// Special treatment for two-parametric elements in 3D space (shells)
dNdX = dNdu;
v1.normalize();
J.fillColumn(t1,v1.ptr());
J.fillColumn(t2,v2.ptr());
return dS;
}
} }
else else
{ {
@ -135,7 +158,7 @@ bool utl::Hessian (matrix3d<Real>& H, matrix3d<Real>& d2NdX2,
d2NdX2.resize(0,0,0,true); d2NdX2.resize(0,0,0,true);
return true; return true;
} }
else if (Ji.cols() == 1 && Ji.rows() > 1) else if (Ji.cols() <= 2 && Ji.rows() > Ji.cols())
{ {
// Special treatment for one-parametric elements in multi-dimension space // Special treatment for one-parametric elements in multi-dimension space
d2NdX2 = d2Ndu2; d2NdX2 = d2Ndu2;
@ -181,13 +204,12 @@ void utl::getGmat (const matrix<Real>& Ji, const Real* du, matrix<Real>& G)
size_t nsd = Ji.cols(); size_t nsd = Ji.cols();
G.resize(nsd,nsd,true); G.resize(nsd,nsd,true);
Real domain = pow(2.0,nsd);
for (size_t k = 1; k <= nsd; k++) for (size_t k = 1; k <= nsd; k++)
for (size_t l = 1; l <= nsd; l++) for (size_t l = 1; l <= nsd; l++)
{ {
Real scale = Real(1)/(du[k-1]*du[l-1]); Real scale = domain/(du[k-1]*du[l-1]);
for (size_t m = 1; m <= nsd; m++) for (size_t m = 1; m <= nsd; m++)
G(k,l) += Ji(m,k)*Ji(m,l)*scale; G(k,l) += Ji(m,k)*Ji(m,l)*scale;
} }
G *= pow(2, nsd);
} }

View File

@ -208,6 +208,51 @@ TEST(TestCoordinateMapping, Hessian2D)
} }
class SIMShell : public SIM2D
{
public:
SIMShell() { nsd = 3; }
virtual ~SIMShell() {}
};
TEST(TestCoordinateMapping, JacobianShell)
{
SIMShell sim;
ASSERT_TRUE(sim.createDefaultModel());
ASMs2D& p = static_cast<ASMs2D&>(*sim.getPatch(1));
ASSERT_TRUE(p.uniformRefine(0,3));
ASSERT_TRUE(p.uniformRefine(1,3));
ASSERT_TRUE(sim.createFEMmodel());
Vector N;
Matrix X, dNdU;
p.extractBasis(0.25, 0.25, N, dNdU);
p.getElementCoordinates(X, 2);
Matrix J, dNdX;
Real det = utl::Jacobian(J, dNdX, X, dNdU, true);
const double dndx[] = {
-4.0, 4.0, 0.0, 0.0,
-4.0, 0.0, 4.0, 0.0
};
EXPECT_FLOAT_EQ(det, 1.0);
EXPECT_EQ(J.rows(), 3U);
EXPECT_EQ(J.cols(), 2U);
for (size_t i = 1; i <= J.rows(); i++)
for (size_t j = 1; j <= J.cols(); j++)
EXPECT_FLOAT_EQ(J(i,j), i == j ? 1.0 : 0.0);
size_t i = 0;
EXPECT_EQ(dNdX.rows(), 4U);
EXPECT_EQ(dNdX.cols(), 2U);
for (double v : dNdX)
EXPECT_FLOAT_EQ(dndx[i++], v);
}
TEST(TestCoordinateMapping, Hessian2D_mixed) TEST(TestCoordinateMapping, Hessian2D_mixed)
{ {
SIM2D sim({1,1}); SIM2D sim({1,1});