From 4192ff7553b09b4c6fa7af93b3fc5fd27d16795d Mon Sep 17 00:00:00 2001 From: Koen Hillewaert <koen.hillewaert@cenaero.be> Date: Mon, 4 Aug 2014 16:26:49 +0000 Subject: [PATCH] Integrated adaptive views for the pyramids --- Numeric/pyramidalBasis.cpp | 35 ++++- Numeric/pyramidalBasis.h | 5 + Plugin/Levelset.cpp | 48 +++++++ Post/PViewDataGModel.cpp | 53 ++++++-- Post/PViewDataList.cpp | 2 +- Post/adaptiveData.cpp | 262 +++++++++++++++++++++++++++++++++++++ Post/adaptiveData.h | 51 ++++++++ 7 files changed, 435 insertions(+), 21 deletions(-) diff --git a/Numeric/pyramidalBasis.cpp b/Numeric/pyramidalBasis.cpp index 634ab598fe..aa9c8b2c93 100644 --- a/Numeric/pyramidalBasis.cpp +++ b/Numeric/pyramidalBasis.cpp @@ -18,7 +18,7 @@ pyramidalBasis::pyramidalBasis(int tag) : nodalBasis(tag) int num_points = points.size1(); - coefficients.resize(num_points, num_points); + bergotCoefficients.resize(num_points, num_points); double *fval = new double[num_points]; // Invert the Vandermonde matrix @@ -27,6 +27,29 @@ pyramidalBasis::pyramidalBasis(int tag) : nodalBasis(tag) bergot->f(points(j,0), points(j,1), points(j, 2), fval); for (int i = 0; i < num_points; i++) VDM(i,j) = fval[i]; } + VDM.invert(bergotCoefficients); + + coefficients.resize(num_points,num_points); + monomials.resize(num_points,3); + + int idx = 0; + for (int i=0;i<=order;i++) { + for (int j=0;j<=order;j++) { + for (int k=0;k<=order-std::max(i,j);k++,idx++) { + monomials(idx,0) = i; + monomials(idx,1) = j; + monomials(idx,2) = k; + + for (int l=0;l<num_points;l++) { + double oneMinW = std::max(1e-14,1-points(l,2)); + VDM(idx,l) = std::pow(points(l,0),i); + VDM(idx,l) *= std::pow(points(l,1),j); + VDM(idx,l) *= std::pow(points(l,2),k); + VDM(idx,l) *= std::pow(oneMinW,std::max(i,j)-i-j); + } + } + } + } VDM.invert(coefficients); delete[] fval; @@ -55,7 +78,7 @@ void pyramidalBasis::f(double u, double v, double w, double *val) const for (int i = 0; i < N; i++) { val[i] = 0.; - for (int j = 0; j < N; j++) val[i] += coefficients(i,j)*fval[j]; + for (int j = 0; j < N; j++) val[i] += bergotCoefficients(i,j)*fval[j]; } delete[] fval; @@ -76,7 +99,7 @@ void pyramidalBasis::f(const fullMatrix<double> &coord, fullMatrix<double> &sf) bergot->f(coord(iPt,0), coord(iPt,1), coord(iPt,2), fval); for (int i = 0; i < N; i++) { sf(iPt,i) = 0.; - for (int j = 0; j < N; j++) sf(iPt,i) += coefficients(i,j)*fval[j]; + for (int j = 0; j < N; j++) sf(iPt,i) += bergotCoefficients(i,j)*fval[j]; } } @@ -97,9 +120,9 @@ void pyramidalBasis::df(double u, double v, double w, double grads[][3]) const for (int i = 0; i < N; i++) { grads[i][0] = 0.; grads[i][1] = 0.; grads[i][2] = 0.; for (int j = 0; j < N; j++) { - grads[i][0] += coefficients(i,j)*dfval[j][0]; - grads[i][1] += coefficients(i,j)*dfval[j][1]; - grads[i][2] += coefficients(i,j)*dfval[j][2]; + grads[i][0] += bergotCoefficients(i,j)*dfval[j][0]; + grads[i][1] += bergotCoefficients(i,j)*dfval[j][1]; + grads[i][2] += bergotCoefficients(i,j)*dfval[j][2]; } } diff --git a/Numeric/pyramidalBasis.h b/Numeric/pyramidalBasis.h index 610f48005d..98157b1135 100644 --- a/Numeric/pyramidalBasis.h +++ b/Numeric/pyramidalBasis.h @@ -18,7 +18,12 @@ class pyramidalBasis: public nodalBasis private: // Orthogonal basis for the pyramid BergotBasis *bergot; + fullMatrix<double> bergotCoefficients; + + public: + fullMatrix<double> coefficients; + fullMatrix<double> monomials; public: pyramidalBasis(int tag); diff --git a/Plugin/Levelset.cpp b/Plugin/Levelset.cpp index 8036dace51..56c1e17e06 100644 --- a/Plugin/Levelset.cpp +++ b/Plugin/Levelset.cpp @@ -702,6 +702,50 @@ static bool recur_sign_change(adaptivePrism *t, } } +static bool recur_sign_change(adaptivePyramid *t, + const GMSH_LevelsetPlugin *plug) +{ + if (!t->e[0] || t->visible){ + double v1 = plug->levelset(t->p[0]->X, t->p[0]->Y, t->p[0]->Z, t->p[0]->val); + double v2 = plug->levelset(t->p[1]->X, t->p[1]->Y, t->p[1]->Z, t->p[1]->val); + double v3 = plug->levelset(t->p[2]->X, t->p[2]->Y, t->p[2]->Z, t->p[2]->val); + double v4 = plug->levelset(t->p[3]->X, t->p[3]->Y, t->p[3]->Z, t->p[3]->val); + double v5 = plug->levelset(t->p[4]->X, t->p[4]->Y, t->p[4]->Z, t->p[4]->val); + if(v1 * v2 > 0 && v1 * v3 > 0 && v1 * v4 > 0 && v1 * v5 > 0) + t->visible = false; + else + t->visible = true; + return t->visible; + } + else{ + bool sc1 = recur_sign_change(t->e[0], plug); + bool sc2 = recur_sign_change(t->e[1], plug); + bool sc3 = recur_sign_change(t->e[2], plug); + bool sc4 = recur_sign_change(t->e[3], plug); + bool sc5 = recur_sign_change(t->e[4], plug); + bool sc6 = recur_sign_change(t->e[5], plug); + bool sc7 = recur_sign_change(t->e[6], plug); + bool sc8 = recur_sign_change(t->e[7], plug); + bool sc9 = recur_sign_change(t->e[8], plug); + bool sc10 = recur_sign_change(t->e[9], plug); + if(sc1 || sc2 || sc3 || sc4 || sc5 || sc6 || sc7 || sc8 || sc9 || sc10){ + if (!sc1) t->e[0]->visible = true; + if (!sc2) t->e[1]->visible = true; + if (!sc3) t->e[2]->visible = true; + if (!sc4) t->e[3]->visible = true; + if (!sc5) t->e[4]->visible = true; + if (!sc6) t->e[5]->visible = true; + if (!sc7) t->e[6]->visible = true; + if (!sc8) t->e[7]->visible = true; + if (!sc9) t->e[8]->visible = true; + if (!sc10) t->e[9]->visible = true; + return true; + } + t->visible = false; + return false; + } +} + void GMSH_LevelsetPlugin::assignSpecificVisibility() const { if(adaptiveTriangle::all.size()){ @@ -724,4 +768,8 @@ void GMSH_LevelsetPlugin::assignSpecificVisibility() const adaptivePrism *p = *adaptivePrism::all.begin(); if(!p->visible) p->visible = !recur_sign_change(p, this); } + if(adaptivePyramid::all.size()){ + adaptivePyramid *p = *adaptivePyramid::all.begin(); + if(!p->visible) p->visible = !recur_sign_change(p, this); + } } diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp index 42a878e2c2..5eaace718e 100644 --- a/Post/PViewDataGModel.cpp +++ b/Post/PViewDataGModel.cpp @@ -15,6 +15,7 @@ #include "MElementCut.h" #include "Numeric.h" #include "GmshMessage.h" +#include "pyramidalBasis.h" PViewDataGModel::PViewDataGModel(DataType type) : PViewData(), _min(VAL_INF), _max(-VAL_INF), _type(type) @@ -168,38 +169,62 @@ bool PViewDataGModel::finalize(bool computeMinMax, const std::string &interpolat // type, assume isoparametric elements (except for ElementData, // for which we know the interpolation: it's constant) int types[] = {TYPE_PNT, TYPE_LIN, TYPE_TRI, TYPE_QUA, TYPE_TET, TYPE_HEX, - TYPE_PRI, /*TYPE_PYR - Not polynomial!,*/ TYPE_POLYG, TYPE_POLYH}; + TYPE_PRI,TYPE_PYR, TYPE_POLYG, TYPE_POLYH}; for(unsigned int i = 0; i < sizeof(types) / sizeof(types[0]); i++){ if(!haveInterpolationMatrices(types[i])){ MElement *e = _getOneElementOfGivenType(model, types[i]); if(e){ - const polynomialBasis *fs = (polynomialBasis*) e->getFunctionSpace(); + + const polynomialBasis *fs = dynamic_cast<const polynomialBasis*> (e->getFunctionSpace()); if(fs){ if(e->getPolynomialOrder() > 1){ if(_type == ElementData){ // data is constant per element: force the interpolation matrix fullMatrix<double> coef(1, 1); - coef(0, 0) = 1.; - fullMatrix<double> mono(1, 3); - mono(0, 0) = 0.; - mono(0, 1) = 0.; - mono(0, 2) = 0.; - setInterpolationMatrices(types[i], coef, mono, - fs->coefficients, fs->monomials); - } + coef(0, 0) = 1.; + fullMatrix<double> mono(1, 3); + mono(0, 0) = 0.; + mono(0, 1) = 0.; + mono(0, 2) = 0.; + setInterpolationMatrices(types[i], coef, mono, + fs->coefficients, fs->monomials); + } else - setInterpolationMatrices(types[i], fs->coefficients, fs->monomials, + setInterpolationMatrices(types[i], + fs->coefficients, fs->monomials, fs->coefficients, fs->monomials); - } + } else setInterpolationMatrices(types[i], fs->coefficients, fs->monomials); } + else { + const pyramidalBasis *fs = dynamic_cast<const pyramidalBasis*> (e->getFunctionSpace()); + if(fs){ + if(e->getPolynomialOrder() > 1){ + if(_type == ElementData){ + // data is constant per element: force the interpolation matrix + fullMatrix<double> coef(1, 1); + coef(0, 0) = 1.; + fullMatrix<double> mono(1, 3); + mono(0, 0) = 0.; + mono(0, 1) = 0.; + mono(0, 2) = 0.; + setInterpolationMatrices(types[i], coef, mono, + fs->coefficients, fs->monomials); + } + else + setInterpolationMatrices(types[i], + fs->coefficients, fs->monomials, + fs->coefficients, fs->monomials); + } + else + setInterpolationMatrices(types[i], fs->coefficients, fs->monomials); + } + } } } } - } - return PViewData::finalize(); } diff --git a/Post/PViewDataList.cpp b/Post/PViewDataList.cpp index 1886fee2ff..de18c1ca85 100644 --- a/Post/PViewDataList.cpp +++ b/Post/PViewDataList.cpp @@ -905,7 +905,7 @@ void PViewDataList::setOrder2(int type) case TYPE_TET: typeMSH = MSH_TET_10; break; case TYPE_HEX: typeMSH = MSH_HEX_27; break; case TYPE_PRI: typeMSH = MSH_PRI_18; break; - // case TYPE_PYR: typeMSH = MSH_PYR_14; break; + case TYPE_PYR: typeMSH = MSH_PYR_14; break; } const polynomialBasis *fs = (polynomialBasis*)BasisFactory::getNodalBasis(typeMSH); if(!fs){ diff --git a/Post/adaptiveData.cpp b/Post/adaptiveData.cpp index 2d91ede6ed..5871cb6ed4 100644 --- a/Post/adaptiveData.cpp +++ b/Post/adaptiveData.cpp @@ -20,6 +20,7 @@ std::set<adaptiveVertex> adaptiveQuadrangle::allVertices; std::set<adaptiveVertex> adaptiveTetrahedron::allVertices; std::set<adaptiveVertex> adaptiveHexahedron::allVertices; std::set<adaptiveVertex> adaptivePrism::allVertices; +std::set<adaptiveVertex> adaptivePyramid::allVertices; std::list<adaptivePoint*> adaptivePoint::all; std::list<adaptiveLine*> adaptiveLine::all; @@ -28,6 +29,7 @@ std::list<adaptiveQuadrangle*> adaptiveQuadrangle::all; std::list<adaptiveTetrahedron*> adaptiveTetrahedron::all; std::list<adaptiveHexahedron*> adaptiveHexahedron::all; std::list<adaptivePrism*> adaptivePrism::all; +std::list<adaptivePyramid*> adaptivePyramid::all; int adaptivePoint::numNodes = 1; int adaptiveLine::numNodes = 2; @@ -36,6 +38,7 @@ int adaptiveQuadrangle::numNodes = 4; int adaptivePrism::numNodes = 6; int adaptiveTetrahedron::numNodes = 4; int adaptiveHexahedron::numNodes = 8; +int adaptivePyramid::numNodes = 5; int adaptivePoint::numEdges = 0; int adaptiveLine::numEdges = 1; @@ -44,6 +47,7 @@ int adaptiveQuadrangle::numEdges = 4; int adaptivePrism::numEdges = 9; int adaptiveTetrahedron::numEdges = 6; int adaptiveHexahedron::numEdges = 12; +int adaptivePyramid::numEdges = 8; template <class T> static void cleanElement() @@ -66,6 +70,40 @@ static void computeShapeFunctions(fullMatrix<double> *coeffs, fullMatrix<double> coeffs->mult(*tmp, *sf); } +/*! Bergot space is characterised by polynomials + \f$ \mathcal B_{ijk} = + \mathcal P_i \left(\frac{\xi }{1-\zeta}\right) + \mathcal P_j \left(\frac{\eta}{1-\zeta}\right) + \left(1-\zeta\right)^{max(i,j)} + \mathcal P^{2 max(i,j),0}_k \left(2 \zeta -1\right)~|~i,j \leq p, k \leq p - max(i,j) \f$ + and hence by the "monomials" + \f$ \mu_{ijk} = + \left(\frac{\xi }{\1-\zeta}\right)^i + \left(\frac{\eta}{\1-\zeta}\right)^j + \left(1-\zeta\right)^{max(i,j)} \zeta^k~|~i,j \leq p~,~k \leq p-max(i,j) + \f$ +*/ +static void computeShapeFunctionsPyramid(fullMatrix<double> *coeffs, + fullMatrix<double> *eexps, + double u, double v, double w, + fullVector<double> *sf, + fullVector<double> *tmp) +{ + + double oneMinW = (w==1) ? 1e-12:1-w; + for(int l = 0; l < eexps->size1(); l++) { + int i = (*eexps)(l,0); + int j = (*eexps)(l,1); + int k = (*eexps)(l,2); + int m = std::max(i,j); + (*tmp)(l) = pow(u,i); + (*tmp)(l) *= pow(v,j); + (*tmp)(l) *= pow(w,k); + (*tmp)(l) *= pow(oneMinW,m-i-j); + } + coeffs->mult(*tmp, *sf); +} + adaptiveVertex *adaptiveVertex::add(double x, double y, double z, std::set<adaptiveVertex> &allVertices) { @@ -883,6 +921,163 @@ void adaptivePrism::recurError(adaptivePrism *p, double AVG, double tol) } } +void adaptivePyramid::create(int maxlevel) +{ + cleanElement<adaptivePyramid>(); + adaptiveVertex *p1 = adaptiveVertex::add(-1, -1, 0, allVertices); + adaptiveVertex *p2 = adaptiveVertex::add(1, -1, 0, allVertices); + adaptiveVertex *p3 = adaptiveVertex::add(1, 1, 0, allVertices); + adaptiveVertex *p4 = adaptiveVertex::add(-1, 1, 0, allVertices); + adaptiveVertex *p5 = adaptiveVertex::add(0, 0, 1, allVertices); + adaptivePyramid *p = new adaptivePyramid(p1, p2, p3, p4, p5); + recurCreate(p, maxlevel, 0); +} + +void adaptivePyramid::recurCreate(adaptivePyramid *p, int maxlevel, int level) +{ + all.push_back(p); + if(level++ >= maxlevel) return; + + // quad points + adaptiveVertex *p1 = p->p[0]; + adaptiveVertex *p2 = p->p[1]; + adaptiveVertex *p3 = p->p[2]; + adaptiveVertex *p4 = p->p[3]; + + // apex + adaptiveVertex *p5 = p->p[4]; + + // center of the quad + + adaptiveVertex *p1234 = adaptiveVertex::add + ((p1->x + p2->x + p3->x + p4->x)*0.25, + (p1->y + p2->y + p3->y + p4->y)*0.25, + (p1->z + p2->z + p3->z + p4->z)*0.25,allVertices); + + // quad edge points + + adaptiveVertex *p12 = adaptiveVertex::add + ((p1->x + p2->x)*0.5, + (p1->y + p2->y)*0.5, + (p1->z + p2->z)*0.5,allVertices); + + adaptiveVertex *p23 = adaptiveVertex::add + ((p2->x + p3->x)*0.5, + (p2->y + p3->y)*0.5, + (p2->z + p3->z)*0.5,allVertices); + + adaptiveVertex *p34 = adaptiveVertex::add + ((p3->x + p4->x)*0.5, + (p3->y + p4->y)*0.5, + (p3->z + p4->z)*0.5,allVertices); + + adaptiveVertex *p41 = adaptiveVertex::add + ((p4->x + p1->x)*0.5, + (p4->y + p1->y)*0.5, + (p4->z + p1->z)*0.5,allVertices); + + // quad vertex to apex edge points + + adaptiveVertex *p15 = adaptiveVertex::add + ((p1->x + p5->x)*0.5, + (p1->y + p5->y)*0.5, + (p1->z + p5->z)*0.5,allVertices); + + adaptiveVertex *p25 = adaptiveVertex::add + ((p2->x + p5->x)*0.5, + (p2->y + p5->y)*0.5, + (p2->z + p5->z)*0.5,allVertices); + + adaptiveVertex *p35 = adaptiveVertex::add + ((p3->x + p5->x)*0.5, + (p3->y + p5->y)*0.5, + (p3->z + p5->z)*0.5,allVertices); + + adaptiveVertex *p45 = adaptiveVertex::add + ((p4->x + p5->x)*0.5, + (p4->y + p5->y)*0.5, + (p4->z + p5->z)*0.5,allVertices); + + // four base pyramids on the quad base + + p->e[0] = new adaptivePyramid(p1, p12, p1234, p41, p15); + recurCreate(p->e[0], maxlevel, level); + p->e[1] = new adaptivePyramid(p2, p23, p1234, p12, p25); + recurCreate(p->e[1], maxlevel, level); + p->e[2] = new adaptivePyramid(p3, p34, p1234, p23, p35); + recurCreate(p->e[2], maxlevel, level); + p->e[3] = new adaptivePyramid(p4, p41, p1234, p34, p45); + recurCreate(p->e[3], maxlevel, level); + + // top pyramids + + p->e[4] = new adaptivePyramid(p15,p25,p35,p45,p5); + recurCreate(p->e[4], maxlevel, level); + p->e[5] = new adaptivePyramid(p15,p45,p35,p25,p1234); + recurCreate(p->e[5], maxlevel, level); + + // degenerated pyramids to replace the remaining tetrahedral holes + // degenerated quad in the interior of the element, apices on the quad edges + + p->e[6] = new adaptivePyramid(p1234,p25,p15,p1234,p12); + recurCreate(p->e[6], maxlevel, level); + p->e[7] = new adaptivePyramid(p1234,p35,p25,p1234,p23); + recurCreate(p->e[7], maxlevel, level); + p->e[8] = new adaptivePyramid(p1234,p45,p35,p1234,p34); + recurCreate(p->e[8], maxlevel, level); + p->e[9] = new adaptivePyramid(p1234,p15,p45,p1234,p41); + recurCreate(p->e[9], maxlevel, level); +} + +void adaptivePyramid::error(double AVG, double tol) +{ + adaptivePyramid *p = *all.begin(); + recurError(p, AVG, tol); +} + +void adaptivePyramid::recurError(adaptivePyramid *p, double AVG, double tol) +{ + if(!p->e[0]) + p->visible = true; + else { + double vi[10]; + for (int i = 0; i < 10; i++) vi[i] = p->e[i]->V(); + double vr = 0; + for (int i = 0; i < 6 ; i++) vr += vi[i]; // pyramids have volume V/8 + for (int i = 6; i < 10; i++) vr += vi[i]*0.5; // tetrahedra have volume V/16 + vr /= 8.; + const double v = p->V(); + if(!p->e[0]->e[0]) { + if(fabs(v - vr) > AVG * tol){ + p->visible = false; + for (int i = 0; i < 10; i++) recurError(p->e[i],AVG,tol); + } + else + p->visible = true; + } + else { + bool err = false; + for(int i = 0; i < 10; i++){ + double vj[10]; + for (int j = 0; j < 10; j++) vj[j] = p->e[i]->e[j]->V(); + double vri = 0; + for (int j = 0; j < 6 ; j++) vri += vj[j]; + for (int j = 6; j < 10; j++) vri += vj[j]*0.5; + vri /= 8.; + err |= (fabs((vi[i] - vri)) > AVG * tol); + } + err |= (fabs((v - vr)) > AVG * tol); + if(err) { + p->visible = false; + for(int i = 0; i < 10; i++) + recurError(p->e[i], AVG, tol); + } + else + p->visible = true; + } + } +} + template <class T> adaptiveElements<T>::adaptiveElements(std::vector<fullMatrix<double>*> &p) : _coeffsVal(0), _eexpsVal(0), _interpolVal(0), @@ -960,6 +1155,61 @@ void adaptiveElements<T>::init(int level) #endif } +template <> +void adaptiveElements<adaptivePyramid>::init(int level) +{ +#ifdef TIMER + double t1 = GetTimeInSeconds(); +#endif + + adaptivePyramid::create(level); + int numVals = _coeffsVal ? _coeffsVal->size1() : adaptivePyramid::numNodes; + int numNodes = _coeffsGeom ? _coeffsGeom->size1() : adaptivePyramid::numNodes; + + if(_interpolVal) delete _interpolVal; + _interpolVal = new fullMatrix<double>(adaptivePyramid::allVertices.size(), numVals); + + if(_interpolGeom) delete _interpolGeom; + _interpolGeom = new fullMatrix<double>(adaptivePyramid::allVertices.size(), numNodes); + + fullVector<double> sfv(numVals), *tmpv = 0; + fullVector<double> sfg(numNodes), *tmpg = 0; + if(_eexpsVal) tmpv = new fullVector<double>(_eexpsVal->size1()); + if(_eexpsGeom) tmpg = new fullVector<double>(_eexpsGeom->size1()); + + int i = 0; + for(std::set<adaptiveVertex>::iterator it = adaptivePyramid::allVertices.begin(); + it != adaptivePyramid::allVertices.end(); ++it) { + + if(_coeffsVal && _eexpsVal) + computeShapeFunctionsPyramid(_coeffsVal, _eexpsVal, + it->x, it->y, it->z, &sfv, tmpv); + else + adaptivePyramid::GSF(it->x, it->y, it->z, sfv); + + for(int j = 0; j < numVals; j++) + (*_interpolVal)(i, j) = sfv(j); + + if(_coeffsGeom && _eexpsGeom) + computeShapeFunctionsPyramid(_coeffsGeom, _eexpsGeom, + it->x, it->y, it->z, &sfg, tmpg); + else + adaptivePyramid::GSF(it->x, it->y, it->z, sfg); + for(int j = 0; j < numNodes; j++) + (*_interpolGeom)(i, j) = sfg(j); + + i++; + } + + if(tmpv) delete tmpv; + if(tmpg) delete tmpg; + +#ifdef TIMER + adaptiveData::timerInit += GetTimeInSeconds() - t1; + return; +#endif +} + template <class T> void adaptiveElements<T>::adapt(double tol, int numComp, std::vector<PCoords> &coords, @@ -1134,6 +1384,11 @@ void adaptiveElements<T>::addInView(double tol, int step, outNb = (numComp == 1) ? &out->NbSI : &out->NbVI; outList = (numComp == 1) ? &out->SI : &out->VI; break; + case 8: + numEle = in->getNumPyramids(); + outNb = (numComp == 1) ? &out->NbSY : &out->NbVY; + outList = (numComp == 1) ? &out->SY : &out->VY; + break; case 12: numEle = in->getNumHexahedra(); outNb = (numComp == 1) ? &out->NbSH : &out->NbVH; @@ -1227,6 +1482,10 @@ adaptiveData::adaptiveData(PViewData *data) _inData->getInterpolationMatrices(TYPE_HEX, p); _hexahedra = new adaptiveElements<adaptiveHexahedron>(p); } + if(_inData->getNumPyramids()){ + _inData->getInterpolationMatrices(TYPE_PYR, p); + _pyramids = new adaptiveElements<adaptivePyramid>(p); + } } adaptiveData::~adaptiveData() @@ -1238,6 +1497,7 @@ adaptiveData::~adaptiveData() if(_tetrahedra) delete _tetrahedra; if(_prisms) delete _prisms; if(_hexahedra) delete _hexahedra; + if(_pyramids) delete _pyramids; delete _outData; } @@ -1257,6 +1517,7 @@ void adaptiveData::changeResolution(int step, int level, double tol, if(_tetrahedra) _tetrahedra->init(level); if(_prisms) _prisms->init(level); if(_hexahedra) _hexahedra->init(level); + if(_pyramids) _pyramids->init(level); } if(plug || _step != step || _level != level || _tol != tol){ _outData->setDirty(true); @@ -1267,6 +1528,7 @@ void adaptiveData::changeResolution(int step, int level, double tol, if(_tetrahedra) _tetrahedra->addInView(tol, step, _inData, _outData, plug); if(_prisms) _prisms->addInView(tol, step, _inData, _outData, plug); if(_hexahedra) _hexahedra->addInView(tol, step, _inData, _outData, plug); + if(_pyramids) _pyramids->addInView(tol, step, _inData, _outData, plug); _outData->finalize(); } _step = step; diff --git a/Post/adaptiveData.h b/Post/adaptiveData.h index ff8a28e97b..15f5758a0f 100644 --- a/Post/adaptiveData.h +++ b/Post/adaptiveData.h @@ -9,6 +9,7 @@ #include <list> #include <set> #include <vector> +#include <cstdlib> #include "fullMatrix.h" class PViewData; @@ -287,6 +288,55 @@ class adaptiveHexahedron { static void recurError(adaptiveHexahedron *h, double AVG, double tol); }; +// modif koen.hillewaert@cenaero.be, 31/07/2014 + +class adaptivePyramid { + public: + bool visible; + adaptiveVertex *p[5]; + adaptivePyramid *e[10]; + static std::list<adaptivePyramid*> all; + static std::set<adaptiveVertex> allVertices; + static int numNodes, numEdges; + public: + adaptivePyramid(adaptiveVertex *p1, + adaptiveVertex *p2, + adaptiveVertex *p3, + adaptiveVertex *p4, + adaptiveVertex *p5) + : visible(false) + { + p[0] = p1; + p[1] = p2; + p[2] = p3; + p[3] = p4; + p[4] = p5; + for (int i=0;i<10;i++) e[i] = NULL; + } + inline double V() const + { + return (p[0]->val + + p[1]->val + + p[2]->val + + p[3]->val + + p[4]->val) / 5.; + } + // barycentric coordinates ? + inline static void GSF(double u, double v, double w, fullVector<double> &sf) + { + double ww = 0.25 / std::max(1e-14,1.-w); + sf(0) = (1 - u - w) * (1 - v - w) * ww; + sf(1) = (1 + u - w) * (1 - v - w) * ww; + sf(2) = (1 + u - w) * (1 + v - w) * ww; + sf(3) = (1 - u - w) * (1 + v - w) * ww; + sf(4) = w; + } + static void create(int maxlevel); + static void recurCreate(adaptivePyramid *h, int maxlevel, int level); + static void error(double AVG, double tol); + static void recurError(adaptivePyramid *h, double AVG, double tol); +}; + class PCoords { public: double c[3]; @@ -346,6 +396,7 @@ class adaptiveData { adaptiveElements<adaptiveTetrahedron> *_tetrahedra; adaptiveElements<adaptiveHexahedron> *_hexahedra; adaptiveElements<adaptivePrism> *_prisms; + adaptiveElements<adaptivePyramid> *_pyramids; public: static double timerInit, timerAdapt; adaptiveData(PViewData *data); -- GitLab