Skip to content

Commit

Permalink
Merge pull request #189 from labmec/hcurl-changes
Browse files Browse the repository at this point in the history
Hcurl changes
  • Loading branch information
orlandini authored Sep 19, 2023
2 parents 9aa8e48 + 93aaa01 commit 5ffb547
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 120 deletions.
100 changes: 28 additions & 72 deletions Mesh/TPZCompElHCurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,29 +151,11 @@ int TPZCompElHCurl<TSHAPE>::SideConnectLocId(int con,int side) const {
return -1;
}
#endif
int conSide = -1;
TPZStack<int> sideClosure;
TSHAPE::LowerDimensionSides(side,sideClosure);
sideClosure.Push(side);
int iCon = -1;
for(auto &subSide :sideClosure){
if(TSHAPE::SideDimension(subSide)) iCon++;
if(iCon == con) {
conSide = subSide;
break;
}
}
if(conSide<0){
std::stringstream sout;
sout << __PRETTY_FUNCTION__ << " ERROR: could not find subside associated with connect "<<con<<" on side "<<side << std::endl;
PZError<<sout.str();
#ifdef PZ_LOG
LOGPZ_ERROR(logger,sout.str())
#endif
DebugStop();
return -1;
}
return conSide-TSHAPE::NCornerNodes;

const auto nnodes = TSHAPE::NCornerNodes;
const auto nsidenodes = TSHAPE::NSideNodes(side);
const auto locside = TSHAPE::ContainedSideLocId(side,nsidenodes+con);
return locside - nnodes;
}

template<class TSHAPE>
Expand All @@ -188,14 +170,9 @@ int TPZCompElHCurl<TSHAPE>::NSideConnects(int side) const{
#endif
}
#endif
int nCons = 0;
TPZStack<int> sideClosure;
TSHAPE::LowerDimensionSides(side,sideClosure);
sideClosure.Push(side);
for(auto &subSide :sideClosure){
if(TSHAPE::SideDimension(subSide)) nCons++;
}
return nCons;
const auto nsidenodes = TSHAPE::NSideNodes(side);
const auto nsidesides = TSHAPE::NContainedSides(side);
return nsidesides - nsidenodes;
}

template<class TSHAPE>
Expand Down Expand Up @@ -269,21 +246,7 @@ int TPZCompElHCurl<TSHAPE>::ConnectOrder(int connect) const {
template<class TSHAPE>
int TPZCompElHCurl<TSHAPE>::EffectiveSideOrder(int side) const{
if(!NSideConnects(side)) return -1;
const auto connect = this->MidSideConnectLocId( side);
if(connect >= 0 || connect < NConnects()){
return ConnectOrder(connect);
}
else{
std::stringstream sout;
sout << __PRETTY_FUNCTION__<<std::endl;
sout << "Connect index out of range connect " << connect << " nconnects " << NConnects();
PZError<<sout.str()<<std::endl;
#ifdef PZ_LOG
LOGPZ_ERROR(logger, sout.str())
#endif
DebugStop();
}
return -1;
return ConnectOrder(side-TSHAPE::NCornerNodes);
}

template<class TSHAPE>
Expand All @@ -310,25 +273,12 @@ void TPZCompElHCurl<TSHAPE>::SetSideOrder(int side, int order){
TPZConnect &c = this->Connect(connect);
c.SetOrder(order,this->fConnectIndexes[connect]);
int64_t seqnum = c.SequenceNumber();
const int nStateVars = [&](){
TPZMaterial * mat =this-> Material();
if(mat) return mat->NStateVariables();
else {
#ifdef PZ_LOG
std::stringstream sout;
sout << __PRETTY_FUNCTION__<<"\tAssuming only one state variable since no material has been set";
LOGPZ_DEBUG(logger,sout.str())
#endif
return 1;
}
}();
c.SetNState(nStateVars);
TPZMaterial * mat =this-> Material();
const int nvars = mat ? mat->NStateVariables() : 1;
c.SetNState(nvars);
const int nshape =this->NConnectShapeF(connect,order);
c.SetNShape(nshape);
this-> Mesh()->Block().Set(seqnum,nshape*nStateVars);
this->AdjustIntegrationRule();
//for the hcurl and hdiv spaces to be compatible, the approximation order of a face must be max(k,ke), where
//k is the (attempted) order of the face, and ke the maximum order of the edges contained in it.
this->Mesh()->Block().Set(seqnum,nshape*nvars);
}

template<class TSHAPE>
Expand Down Expand Up @@ -416,8 +366,8 @@ void TPZCompElHCurl<TSHAPE>::ComputeShape(TPZVec<REAL> &qsi, TPZMaterialData &da
// }();

const int nshape = this->NShapeF();
TPZFNMatrix<dim*80,REAL> phiref(dim,nshape);
TPZFNMatrix<curldim*80,REAL> curlphiref(curldim,nshape);
TPZFNMatrix<dim*80,REAL> phiref(dim,nshape,0.);
TPZFNMatrix<curldim*80,REAL> curlphiref(curldim,nshape,0.);

TPZShapeData &shapedata = data;
switch (fhcurlfam)
Expand Down Expand Up @@ -559,8 +509,8 @@ void TPZCompElHCurl<TSHAPE>::SideShapeFunction(int side,TPZVec<REAL> &point,TPZF
}
}();

TPZFMatrix<REAL> phiref(sidedim,nshape);
TPZFMatrix<REAL> curlphiref(curldim,nshape);
TPZFNMatrix<1000, REAL> phiref(sidedim,nshape,0.);
TPZFNMatrix<1000, REAL> curlphiref(curldim,nshape,0.);

switch(sidetype){
case EOned:
Expand All @@ -580,7 +530,7 @@ void TPZCompElHCurl<TSHAPE>::SideShapeFunction(int side,TPZVec<REAL> &point,TPZF

//get the jacobian of the side transformation
TPZGeoElSide gelside = TPZGeoElSide(this->Reference(),side);
TPZFNMatrix<9,REAL> jac(sideDim,sideDim),jacinv(sideDim,sideDim),axes(sideDim,3);
TPZFNMatrix<9,REAL> jac(sideDim,sideDim,0.),jacinv(sideDim,sideDim,0.),axes(sideDim,3,0.);
REAL detjac = 0;
gelside.Jacobian(point, jac, axes, detjac, jacinv);

Expand Down Expand Up @@ -613,11 +563,17 @@ void TPZCompElHCurl<TSHAPE>::TransformShape(const TPZFMatrix<REAL> &phiref,
{

//applies covariant piola transform and compute the deformed vectors
TPZFMatrix<REAL> axest, jacinvt;
TPZFNMatrix<9,REAL> axest, jacinvt;
jacinv.Transpose(&jacinvt);
axes.Transpose(&axest);

(axest * (jacinvt * phiref)).Transpose(&phi);
//2000 should take care of up to a 6th order tetrahedral el
TPZFNMatrix<2000,REAL> tmp1,tmp2;
//we want to do (axest * (jacinvt * phiref)).Transpose(&phi);
//with no mem alloc
jacinvt.Multiply(phiref, tmp1);
axest.Multiply(tmp1,tmp2);
tmp2.Transpose(&phi);
}

template<class TSHAPE>
Expand All @@ -628,7 +584,7 @@ void TPZCompElHCurl<TSHAPE>::TransformCurl(const TPZFMatrix<REAL> &curlphiref,
TPZFMatrix<REAL> &curlphi)
{
if constexpr(TDIM==3){
curlphi = jacobian * curlphiref;
jacobian.Multiply(curlphiref, curlphi);
curlphi *= 1./detjac;
}else {
curlphi = curlphiref;
Expand All @@ -641,7 +597,7 @@ template<class TSHAPE>
void TPZCompElHCurl<TSHAPE>::CreateHCurlConnects(TPZCompMesh &mesh){
constexpr int nNodes = TSHAPE::NCornerNodes;
constexpr int nConnects = TSHAPE::NSides - nNodes;
this->fConnectIndexes.Resize(nConnects);

for(auto i = 0; i < nConnects; i++){
const int sideId = nNodes + i;
this->fConnectIndexes[i] = this->CreateMidSideConnect(sideId);
Expand Down
91 changes: 45 additions & 46 deletions Shape/TPZShapeHCurl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ void TPZShapeHCurl<TSHAPE>::Shape(const TPZVec<T> &pt, TPZShapeData &data, TPZFM
constexpr int nvol = dim == 3 ? 1 : 0;
constexpr int nedges = nsides - nvol - nfaces - ncorner;

TPZFNMatrix<100,T> locphi(data.fPhi.Rows(),data.fPhi.Cols());
TPZFNMatrix<100*dim,T> dphi(data.fDPhi.Rows(),data.fDPhi.Cols());
TPZFNMatrix<100,T> locphi(data.fPhi.Rows(),data.fPhi.Cols(),0.);
TPZFNMatrix<100*dim,T> dphi(data.fDPhi.Rows(),data.fDPhi.Cols(),0.);

TPZShapeH1<TSHAPE>::Shape(pt,data, locphi, dphi);

Expand Down Expand Up @@ -207,55 +207,43 @@ void TPZShapeHCurl<TSHAPE>::Shape(const TPZVec<T> &pt, TPZShapeData &data, TPZFM
int vs_index = 0;
int phi_index = 0;

//tmp phi and curlphi
TPZFNMatrix<dim,T> phi_1(dim,1),phi_2(dim,1);
TPZFNMatrix<curldim,T> cphi_1(curldim,1),cphi_2(curldim,1);
//we iterate through edges...
for(int icon = 0; icon < nedges; icon++){
const auto order = connectorders[icon];
//low order funcs
TPZFNMatrix<dim*nedges,T> phi_lo(dim,nedges,0.);
TPZFNMatrix<curldim*nedges,T> curlphi_lo(curldim,nedges,0.);

{//gets phi_1
const auto &itf = data.fSDVecShapeIndex[vs_index];
const int fv = itf.first;
const int fs = itf.second;
ComputeShape(phi_1,0,fs,fv);
ComputeCurl(cphi_1,0,fs,fv);
}
TSHAPE::ComputeConstantHCurl(pt, phi_lo, curlphi_lo, data.fSideTransformationId);

{//gets phi_2
const auto &its = data.fSDVecShapeIndex[vs_index+1];
const int sv = its.first;
const int ss = its.second;
ComputeShape(phi_2,0,ss,sv);
ComputeCurl(cphi_2,0,ss,sv);
}

//constant trace
TPZManVector<int64_t,nedges> firstH1edgeFunc(nedges,0);
firstH1edgeFunc[0] = ncorner;
for (int icon = 1; icon < nedges; icon++){
firstH1edgeFunc[icon] = firstH1edgeFunc[icon-1] + data.fH1NumConnectShape[icon-1];
}

//we iterate through edges...
for(int icon = 0; icon < nedges; icon++){
const auto order = connectorders[icon];
//constant traces
for(auto x = 0; x < dim; x++){
phi(x,phi_index) = phi_1.GetVal(x,0) + phi_2.GetVal(x,0);
phi(x,phi_index) = phi_lo.GetVal(x,icon);
}
for(auto x = 0; x < curldim; x++){
curlphi(x,phi_index) = cphi_1.GetVal(x,0) + cphi_2.GetVal(x,0);
curlphi(x,phi_index) = curlphi_lo.GetVal(x,icon);
}
phi_index++;
if(order>0){
//linear traces
phi_index++;vs_index++;

if(order==0){vs_index++;}
vs_index += order;

const int firstedgefunc = firstH1edgeFunc[icon];
for(int ord = 1; ord < order+1; ord++, phi_index++){
const int scalindex = firstedgefunc + ord-1;
for(auto x = 0; x < dim; x++){
phi(x,phi_index) = phi_1.GetVal(x,0) - phi_2.GetVal(x,0);
phi(x,phi_index) = dphi.GetVal(x,scalindex);
}
for(auto x = 0; x < curldim; x++){
curlphi(x,phi_index) = cphi_1.GetVal(x,0) - cphi_2.GetVal(x,0);
curlphi(x,phi_index) = 0;
}
phi_index++;
}
vs_index+=2;
//higher order edge functions
for(int ord = 2; ord < order+1; ord++, phi_index++, vs_index++){
const auto &it = data.fSDVecShapeIndex[vs_index];
const int vecindex = it.first;
const int scalindex = it.second;
ComputeShape(phi,phi_index,scalindex,vecindex);
ComputeCurl(curlphi,phi_index,scalindex,vecindex);
}
}

Expand All @@ -269,8 +257,14 @@ void TPZShapeHCurl<TSHAPE>::Shape(const TPZVec<T> &pt, TPZShapeData &data, TPZFM
ComputeShape(phi,phi_index,scalindex,vecindex);
ComputeCurl(curlphi,phi_index,scalindex,vecindex);
}


// #ifdef PZDEBUG
if(vs_index!=data.fSDVecShapeIndex.size()){
DebugStop();
}
if(phi_index != phi.Cols()){
DebugStop();
}
// #endif
}


Expand Down Expand Up @@ -348,19 +342,23 @@ void TPZShapeHCurl<TSHAPE>::CalcH1ShapeOrders(
for(auto iCon = 0; iCon < nConnects; iCon++){
const auto iSide = iCon + TSHAPE::NCornerNodes;
const auto sideDim = TSHAPE::SideDimension(iSide);
const bool quadSide =
const bool quadSideOrEdge =
TSHAPE::Type(iSide) == EOned ||
TSHAPE::Type(iSide) == EQuadrilateral ||
TSHAPE::Type(iSide) == ECube ||
TSHAPE::Type(iSide) == EPrisma;
/*some H1 functions associated with the side iSide of dimension dim
/*
some H1 functions associated with the side iSide of dimension dim
might be needed for computing the shape functions of a side with
dimension dim+1 that contains the side iSide.
for instance, p+1 h1 edge functions are needed for p hcurl elements
It is also worth noting that quadrilateral sides require functions
of ordH1er k+1*/
TPZStack<int> highDimSides;
TSHAPE::HigherDimensionSides(iSide, highDimSides);
const auto sideOrder = ordHCurl[iCon];
auto maxOrder = quadSide ? sideOrder + 1: sideOrder;
auto maxOrder = quadSideOrEdge ? sideOrder + 1: sideOrder;
for(auto &ihSide : highDimSides){
if(TSHAPE::SideDimension(ihSide) != sideDim+1) break;
else {
Expand Down Expand Up @@ -836,7 +834,8 @@ void TPZShapeHCurl<TSHAPE>::StaticIndexShapeToVec(TPZShapeData &data) {
template<class TSHAPE>
int TPZShapeHCurl<TSHAPE>::MaxOrder(const int ordh1){

if constexpr (std::is_same_v<TSHAPE,pzshape::TPZShapeCube> ||
if constexpr (std::is_same_v<TSHAPE,pzshape::TPZShapePrism> ||
std::is_same_v<TSHAPE,pzshape::TPZShapeCube> ||
std::is_same_v<TSHAPE,pzshape::TPZShapeQuad>){
return ordh1+1;
}else{
Expand Down
57 changes: 57 additions & 0 deletions Shape/pzshapelinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,63 @@ namespace pzshape {
#endif

} //end of method

void TPZShapeLinear::IntegratedLegendre(REAL x,int num,TPZFMatrix<REAL> &phi,TPZFMatrix<REAL> &dphi){
if (num <= 0) return;
phi.Put(0, 0, 1.0);
dphi.Put(0, 0, 0.0);

if (num == 1) return;

phi.Put(1, 0, x);
dphi.Put(0, 1, 1.0);

if(num == 2) return;

phi.Put(2,0,0.5*(x*x-1));
dphi.Put(0,2,x);

for (auto ord = 3; ord < num; ord++)
{
const auto coeff1 = 2*(ord-1)-1;
const auto coeff2 = ord-3;
const auto val = coeff1*x*phi.GetVal(ord-1,0) - coeff2*phi.GetVal(ord-2,0);
phi.Put(ord, 0, val/ord);

const auto deriv = coeff1*phi.GetVal(ord-1,0) + coeff1*x*dphi.GetVal(0,ord-1)
- coeff2*dphi.GetVal(0,ord-2);
dphi.Put(0, ord, deriv/ord);
}
}
void TPZShapeLinear::ScaledIntegratedLegendre(const REAL x,const REAL t, int num,TPZFMatrix<REAL> &phi,TPZFMatrix<REAL> &dphi){
if (num <= 0) return;
phi.Put(0, 0, 1.0);
dphi.Put(0, 0, 0.0);

if (num == 1) return;

phi.Put(1, 0, x);
dphi.Put(0, 1, 1.0);

if(num == 2) return;

phi.Put(2,0,0.5*(x*x-t*t));
dphi.Put(0,2,x);

TPZFNMatrix<300,REAL> phi_leg(num,1,0), dphi_leg(1,num,0);
TPZShapeLinear::IntegratedLegendre(x, num, phi_leg, dphi_leg);
for (auto ord = 3; ord < num; ord++)
{
const auto coeff1 = 2*(ord-1)-1;
const auto coeff2 = (ord-3)*t*t;
const auto val = coeff1*x*phi_leg.GetVal(ord-1,0) - coeff2*phi_leg.GetVal(ord-2,0);
phi.Put(ord, 0, val/ord);

const auto deriv = coeff1*phi_leg.GetVal(ord-1,0) + coeff1*x*dphi_leg.GetVal(0,ord-1)
- coeff2*dphi_leg.GetVal(0,ord-2);
dphi.Put(0, ord, deriv/ord);
}
}

void TPZShapeLinear::Legendre(REAL x,int num,TPZFMatrix<REAL> &phi,TPZFMatrix<REAL> &dphi, int nderiv){

Expand Down
Loading

0 comments on commit 5ffb547

Please sign in to comment.