From a4e1795797a0144745387078a72be497876aa1fe Mon Sep 17 00:00:00 2001 From: Thomas Toulorge <thomas.toulorge@mines-paristech.fr> Date: Tue, 7 Mar 2017 23:50:17 +0000 Subject: [PATCH] Updated fast high-order BL mesh curving algorithm --- contrib/HighOrderMeshOptimizer/CMakeLists.txt | 2 +- contrib/HighOrderMeshOptimizer/MetaEl.cpp | 290 ++++++++++++++++++ .../{SuperEl.h => MetaEl.h} | 38 +-- .../OptHomFastCurving.cpp | 162 +++++----- contrib/HighOrderMeshOptimizer/SuperEl.cpp | 233 -------------- 5 files changed, 388 insertions(+), 337 deletions(-) create mode 100644 contrib/HighOrderMeshOptimizer/MetaEl.cpp rename contrib/HighOrderMeshOptimizer/{SuperEl.h => MetaEl.h} (70%) delete mode 100644 contrib/HighOrderMeshOptimizer/SuperEl.cpp diff --git a/contrib/HighOrderMeshOptimizer/CMakeLists.txt b/contrib/HighOrderMeshOptimizer/CMakeLists.txt index 79c7deb4be..4f4e6d6dd6 100644 --- a/contrib/HighOrderMeshOptimizer/CMakeLists.txt +++ b/contrib/HighOrderMeshOptimizer/CMakeLists.txt @@ -10,7 +10,7 @@ set(SRC OptHomIntegralBoundaryDist.cpp OptHomCADDist.cpp ParamCoord.cpp - SuperEl.cpp + MetaEl.cpp OptHomElastic.cpp OptHomFastCurving.cpp OptHomPeriodicity.cpp diff --git a/contrib/HighOrderMeshOptimizer/MetaEl.cpp b/contrib/HighOrderMeshOptimizer/MetaEl.cpp new file mode 100644 index 0000000000..8a3c3ea7a3 --- /dev/null +++ b/contrib/HighOrderMeshOptimizer/MetaEl.cpp @@ -0,0 +1,290 @@ +// Copyright (C) 2013 ULg-UCL +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished +// to do so, provided that the above copyright notice(s) and this +// permission notice appear in all copies of the Software and that +// both the above copyright notice(s) and this permission notice +// appear in supporting documentation. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR +// ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY +// DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +// OF THIS SOFTWARE. +// +// Please report all bugs and problems to the public mailing list +// <gmsh@onelab.info>. +// +// Contributor: Thomas Toulorge + +#include <iostream> +#include <sstream> +#include "GmshMessage.h" +#include "GEdge.h" +#include "MLine.h" +#include "MQuadrangle.h" +#include "MPrism.h" +#include "MHexahedron.h" +#include "BasisFactory.h" +#include "MetaEl.h" + + +std::map<int, MetaEl::metaInfoType> MetaEl::_metaInfo; + + +//namespace { +// +// +//void getEdgeIndQuad(int order, std::vector<int> edInd) { +// edInd.clear(); +// const int nbEdVert = 4*(order-1); +// edInd.resize(nbEdVert); +// for (int iV = 0; iV < nbEdVert; iV++) edInd[iV] = iV; +//} +// +// +// +//} + + +MetaEl::metaInfoType::metaInfoType(int type, int order) +{ + typedef std::vector<int>::iterator VIntIter; + + int iBaseFace = 0, iTopFace = 0, nbEdVert = 0; + switch (type) { + case TYPE_QUA: + iBaseFace = 0; iTopFace = 2; nbEdVert = 4 + 4*(order-1); + break; + case TYPE_PRI: + iBaseFace = 0; iTopFace = 1; nbEdVert = 6 + 9*(order-1); + break; + case TYPE_HEX: + iBaseFace = 0; iTopFace = 5; nbEdVert = 8 + 12*(order-1); + break; + default: + Msg::Error("MetaEl not implemented for element of type %d", type); + nbVert = 0; + return; + } + + // Get HO nodal basis +// const int tag = ElementType::getTag(type, order, true); // Get tag for incomplete element type + const int tag = ElementType::getTag(type, order); // Get tag for complete element type + if (!tag) return; + const nodalBasis *basis = BasisFactory::getNodalBasis(tag); + nbVert = basis->getNumShapeFunctions(); + points = basis->points; + std::set<int> foundVerts; + + // Vertices on base and top faces + baseInd = basis->getClosure(basis->getClosureId(iBaseFace, 1, 0)); + topInd = basis->getClosure(basis->getClosureId(iTopFace, 0, 0)); + foundVerts.insert(baseInd.begin(), baseInd.end()); + foundVerts.insert(topInd.begin(), topInd.end()); + + // Vertices on edges (excluding base and top faces) + for (int iV = 0; iV < nbEdVert; iV++) + if (foundVerts.find(iV) == foundVerts.end()) { + edgeInd.push_back(iV); + foundVerts.insert(iV); + } + + // Remaining face and interior vertices + for(int iV = 0; iV < nbVert; iV++) + if (foundVerts.find(iV) == foundVerts.end()) { + otherInd.push_back(iV); + foundVerts.insert(iV); + } +} + + +MetaEl::MetaEl(int type, int order, const std::vector<MVertex*> &baseVert, + const std::vector<MVertex*> &topPrimVert) : _metaEl(0), _metaEl0(0) +{ + + // Get useful info on meta-element type if not already there + std::map<int, MetaEl::metaInfoType>::iterator itSInfo = _metaInfo.find(type); + if (itSInfo == _metaInfo.end()) { + const metaInfoType mInfo(type, order); + itSInfo = _metaInfo.insert(std::pair<int,metaInfoType>(type, mInfo)).first; + } + MetaEl::metaInfoType &sInfo = itSInfo->second; + + // Exit if unknown type + if (sInfo.nbVert == 0) return; + + // References for easier writing + const int &nbVert = sInfo.nbVert; + const fullMatrix<double> &points = sInfo.points; + const std::vector<int> &baseInd = sInfo.baseInd; + const std::vector<int> &topInd = sInfo.topInd; + const std::vector<int> &edgeInd = sInfo.edgeInd; + const std::vector<int> &otherInd = sInfo.otherInd; + + // Add copies of vertices in base & top faces (only first-order vertices for top face) + _metaVert.resize(nbVert); + for (int iV = 0; iV < baseInd.size(); iV++) + _metaVert[baseInd[iV]] = new MVertex(*baseVert[iV]); + for (int iV = 0; iV < topPrimVert.size(); iV++) + _metaVert[topInd[iV]] = new MVertex(*topPrimVert[iV]); + + // Create first-order meta-element + switch (type) { + case TYPE_QUA: + _metaEl0 = new MQuadrangle(_metaVert); + break; + case TYPE_PRI: + _metaEl0 = new MPrism(_metaVert); + break; + case TYPE_HEX: + _metaEl0 = new MHexahedron(_metaVert); + break; + default: + Msg::Error("SuperEl not implemented for element of type %d", type); + return; + } + + // Add HO vertices in top face + for (int iV = topPrimVert.size(); iV < topInd.size(); iV++) { + SPoint3 p; + const int ind = topInd[iV]; + _metaEl0->pnt(points(ind, 0), points(ind, 1), points(ind, 2), p); + _metaVert[ind] = new MVertex(p.x(), p.y(), p.z()); + } + + // Add vertices on edges (excluding base and top faces) + for (int iV = 0; iV < edgeInd.size(); iV++) { + SPoint3 p; + const int ind = edgeInd[iV]; + _metaEl0->pnt(points(ind, 0), points(ind, 1), points(ind, 2), p); + _metaVert[ind] = new MVertex(p.x(), p.y(), p.z()); + } + + // Get incomplete high-order meta-element basis + const int tag = ElementType::getTag(type, order, true); // Get tag for incomplete element type + if (!tag) return; + const nodalBasis *incBasis = BasisFactory::getNodalBasis(tag); + + // Add remaining face and interior points + for (int iV = 0; iV < otherInd.size(); iV++) { + const int ind = otherInd[iV]; + double shapeFunc[1256]; + incBasis->f(points(ind, 0), points(ind, 1), points(ind, 2), shapeFunc); + double x = 0., y = 0., z = 0.; + for (int iSF = 0; iSF < incBasis->getNumShapeFunctions(); iSF++) { + x += shapeFunc[iSF] * _metaVert[iSF]->x(); + y += shapeFunc[iSF] * _metaVert[iSF]->y(); + z += shapeFunc[iSF] * _metaVert[iSF]->z(); + } + _metaVert[ind] = new MVertex(x, y, z); + } + + // Create high-order meta-element + switch (type) { + case TYPE_QUA: + _metaEl = new MQuadrangleN(_metaVert, order); + break; + case TYPE_PRI: + _metaEl = new MPrismN(_metaVert, order); + break; + case TYPE_HEX: + _metaEl = new MHexahedronN(_metaVert, order); + break; + } + +// // Scale meta-element if not valid +// // TODO: Scale depending on target Jmin? +// // TODO: Could be improved by using complete meta-element and use optimization +// for (int iter = 0; iter < 10; iter++) { +// if (_metaEl->distoShapeMeasure() > 0) break; +// if (iter == 0) +// Msg::Warning("A meta-element has a negative distortion, trying to scale"); +// for (int i = 0; i < topPrimVert.size(); ++i) { // Move top primary vert. +// MVertex *&vb = _metaVert[baseInd[i]], *&vt = _metaVert[topInd[i]]; +// SPoint3 pb = vb->point(), pt = vt->point(); +// pt += SPoint3(0.25*(pt-pb)); +// vt->setXYZ(pt.x(), pt.y(), pt.z()); +// } +// for (int i=topPrimVert.size(); i<topInd.size(); ++i) { // Recompute HO vert. in top face +// SPoint3 p; +// const int ind = topInd[i]; +// _metaEl0->pnt(points(ind,0), points(ind,1), points(ind,2),p); +// _metaVert[ind]->setXYZ(p.x(), p.y(), p.z()); +// } +// for (int i=0; i<otherInd.size(); ++i) { // Recompute vert. not in base & top faces +// SPoint3 p; +// const int ind = otherInd[i]; +// _metaEl0->pnt(points(ind,0), points(ind,1), points(ind,2),p); +// _metaVert[ind]->setXYZ(p.x(), p.y(), p.z()); +// } +// } + +} + + +MetaEl::~MetaEl() +{ + for (int i = 0; i < _metaVert.size(); i++) delete _metaVert[i]; + _metaVert.clear(); + if (_metaEl) delete _metaEl; + if (_metaEl0) delete _metaEl0; +} + + +bool MetaEl::isPointIn(const SPoint3 p) const +{ + double xyz[3] = {p.x(), p.y(), p.z()}, uvw[3]; + _metaEl0->xyz2uvw(xyz, uvw); + return _metaEl0->isInside(uvw[0], uvw[1], uvw[2]); +} + + +bool MetaEl::straightToCurved(double *xyzS, double *xyzC) const +{ + double uvw[3]; + _metaEl0->xyz2uvw(xyzS, uvw); + if (!_metaEl0->isInside(uvw[0], uvw[1], uvw[2])) return false; + + SPoint3 pC; + _metaEl->pnt(uvw[0], uvw[1], uvw[2], pC); + xyzC[0] = pC[0]; + xyzC[1] = pC[1]; + xyzC[2] = pC[2]; + + return true; +} + + +std::string MetaEl::printPOS() +{ + std::vector<MVertex*> verts; + _metaEl->getVertices(verts); + std::string posStr = _metaEl0->getStringForPOS(); + int n = (posStr[posStr.size()-1] == '2' ? + _metaEl : _metaEl0)->getNumVertices(); + + std::ostringstream oss; + + oss << posStr << "("; + for(int i = 0; i < n; i++){ + if(i) oss << ","; + oss << _metaVert[i]->x() << "," << _metaVert[i]->y() << "," + << _metaVert[i]->z(); + } + oss << "){0."; + for(int i = 1; i < n; i++) oss << ",0."; + oss << "};\n"; + + return oss.str(); +} diff --git a/contrib/HighOrderMeshOptimizer/SuperEl.h b/contrib/HighOrderMeshOptimizer/MetaEl.h similarity index 70% rename from contrib/HighOrderMeshOptimizer/SuperEl.h rename to contrib/HighOrderMeshOptimizer/MetaEl.h index 180c013b12..37ad9bbb12 100644 --- a/contrib/HighOrderMeshOptimizer/SuperEl.h +++ b/contrib/HighOrderMeshOptimizer/MetaEl.h @@ -27,41 +27,43 @@ // // Contributor: Thomas Toulorge -#ifndef _SUPEREL_H_ -#define _SUPEREL_H_ +#ifndef _METAEL_H_ +#define _METAEL_H_ #include <string> #include "MElement.h" -class SuperEl +class MetaEl { public: - SuperEl(int type, int order, const std::vector<MVertex*> &baseVert, + MetaEl(int type, int order, const std::vector<MVertex*> &baseVert, const std::vector<MVertex*> &topPrimVert); - ~SuperEl(); - bool isOK() const { return _superEl; } + ~MetaEl(); + bool isOK() const { return _metaEl; } bool isPointIn(const SPoint3 p) const; bool straightToCurved(double *xyzS, double *xyzC) const; std::string printPOS(); void printCoord() { std::cout << "DBGTT: superEl -> "; - for(int i = 0; i < _superVert.size(); i++){ - std::cout << "v" << i << " = (" << _superVert[i]->x() << "," - << _superVert[i]->y() << "," << _superVert[i]->z() << ")"; - if (i == _superVert.size()-1) std::cout << "\n"; else std::cout << ", "; + for(int i = 0; i < _metaVert.size(); i++){ + std::cout << "v" << i << " = (" << _metaVert[i]->x() << "," + << _metaVert[i]->y() << "," << _metaVert[i]->z() << ")"; + if (i == _metaVert.size()-1) std::cout << "\n"; else std::cout << ", "; } } + MElement *getMElement() { return _metaEl; } + private: - struct superInfoType { - int nV; + struct metaInfoType { + int nbVert; fullMatrix<double> points; - std::vector<int> baseInd, topInd, otherInd; - superInfoType(int type, int order); + std::vector<int> baseInd, topInd, edgeInd, otherInd; + metaInfoType(int type, int order); }; - static std::map<int,superInfoType> _superInfo; - std::vector<MVertex*> _superVert; - MElement *_superEl, *_superEl0; + static std::map<int, metaInfoType> _metaInfo; + std::vector<MVertex*> _metaVert; + MElement *_metaEl, *_metaEl0; }; -#endif +#endif // _METAEL_H_ diff --git a/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp b/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp index f71e14d542..0c3ab4cea3 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp @@ -44,10 +44,10 @@ #include "MLine.h" #include "OS.h" #include <stack> -#include "SuperEl.h" #include "SVector3.h" #include "BasisFactory.h" #include "Field.h" +#include "MetaEl.h" @@ -300,31 +300,23 @@ bool getBaseVertices(const MFace &baseFace, MElement *firstEl, std::vector<MVert template<class bndType> bool getTopPrimVertices(std::map<MVertex*, std::vector<MElement *> > &vertex2elements, const std::map<MVertex*, SVector3> &normVert, - const BoundaryLayerColumns *blc, const bndType &baseBnd, - int maxNumLayers, const std::vector<MVertex*> &baseVert, + const bndType &baseBnd, int maxNumLayers, + const std::vector<MVertex*> &baseVert, std::vector<MVertex*> &topPrimVert) { int nbVert = baseBnd.getNumVertices(); topPrimVert = std::vector<MVertex*>(nbVert); for(int i = 0; i < nbVert; i++) { - if (blc && (blc->size() > 1)) { // Is there BL data? - return false; - // const BoundaryLayerData &c = blc->getColumn(baseVert[i], baseBnd); - // if (c._column.size() == 0) return false; // Give up element if column not found - // topPrimVert[i] = *(c._column.end()-2); - } - else { // No BL data, look for columns of vertices - std::map<MVertex*, SVector3>::const_iterator itNorm = normVert.find(baseVert[i]); - if (itNorm == normVert.end()) { - Msg::Error("Normal to vertex not found in getTopPrimVertices"); - itNorm = normVert.begin(); - } - std::vector<MVertex*> col; - bool colFound = findColumn(vertex2elements, baseVert[i], itNorm->second, - baseBnd, col, maxNumLayers); - if (!colFound) return false; // Give up element if column not found - topPrimVert[i] = *(col.end()-2); + std::map<MVertex*, SVector3>::const_iterator itNorm = normVert.find(baseVert[i]); + if (itNorm == normVert.end()) { + Msg::Error("Normal to vertex not found in getTopPrimVertices"); + itNorm = normVert.begin(); } + std::vector<MVertex*> col; + bool colFound = findColumn(vertex2elements, baseVert[i], itNorm->second, + baseBnd, col, maxNumLayers); + if (!colFound) return false; // Give up element if column not found + topPrimVert[i] = *(col.end()-2); } return true; @@ -335,7 +327,7 @@ bool getTopPrimVertices(std::map<MVertex*, std::vector<MElement *> > &vertex2ele // Get blob of elements encompassed by a given meta-element // FIXME: Implement 3D void get2DBLBlob(const std::map<MVertex*, std::vector<MElement*> > &vertex2elements, - MElement *firstEl, const SuperEl *supEl, std::set<MElement*> &blob) + MElement *firstEl, const MetaEl *supEl, std::set<MElement*> &blob) { static const int maxDepth = 100; typedef std::list<MElement*> elLType; @@ -420,10 +412,52 @@ inline void insertIfCurved(MElement *el, std::list<MElement*> &bndEl) } +class DbgOutput { +public: + void addMetaEl(MetaEl &mEl) { + MElement *elt = mEl.getMElement(); + elType_.push_back(elt->getTypeForMSH()); + nbVertEl_.push_back(elt->getNumVertices()); + for (int iV = 0; iV < elt->getNumVertices(); iV++) + point_.push_back(elt->getVertex(iV)->point()); + } + void write(std::string fNameBase, int tag) { + std::ostringstream oss; + oss << fNameBase << "_" << tag << ".msh"; + std::string fName = oss.str(); + FILE *fp = fopen(fName.c_str(), "w"); + fprintf(fp, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"); + fprintf(fp, "$Nodes\n"); + fprintf(fp, "%d\n", point_.size()); + for (int iV = 0; iV < point_.size(); iV++) + fprintf(fp, "%i %g %g %g\n", iV+1, point_[iV].x(), + point_[iV].y(), point_[iV].z()); + fprintf(fp, "$EndNodes\n"); + fprintf(fp, "$Elements\n"); + fprintf(fp, "%d\n", elType_.size()); + int iV = 0; + for (int iEl = 0; iEl < elType_.size(); iEl++) { + fprintf(fp, "%i %i 2 0 0 ", iEl+1, elType_[iEl]); + for (int iVEl = 1; iVEl <= nbVertEl_[iEl]; iVEl++) + fprintf(fp, " %i", iV+iVEl); + fprintf(fp, "\n"); + iV += nbVertEl_[iEl]; + } + fprintf(fp, "$EndElements\n"); + fclose(fp); + } + +private: + std::vector<int> elType_; + std::vector<int> nbVertEl_; + std::vector<SPoint3> point_; +}; + + // Curve elements adjacent to a boundary model entity void curveMeshFromBnd(std::map<MVertex*, std::vector<MElement *> > &vertex2elements, - const std::map<MVertex*, SVector3> &normVert, BoundaryLayerColumns *blc, + const std::map<MVertex*, SVector3> &normVert, GEntity *bndEnt, FastCurvingParameters &p) { // Build list of bnd. elements to consider @@ -443,28 +477,25 @@ void curveMeshFromBnd(std::map<MVertex*, std::vector<MElement *> > &vertex2eleme else Msg::Error("Cannot treat model entity %i of dim %i", bndEnt->tag(), bndEnt->dim()); - std::ostringstream oss; - oss << "meta-elements_" << bndEnt->tag() << ".pos"; - std::ofstream of(oss.str().c_str()); - of << "View \" \"{\n"; + DbgOutput dbgOut; std::set<MVertex*> movedVert; for(std::list<MElement*>::iterator itBE = bndEl.begin(); itBE != bndEl.end(); itBE++) { // Loop over bnd. elements const int bndType = (*itBE)->getType(); - int seType; + int metaElType; bool foundVert; MElement *firstEl = 0; std::vector<MVertex*> baseVert, topPrimVert; if (bndType == TYPE_LIN) { // 1D boundary? MVertex *vb0 = (*itBE)->getVertex(0); MVertex *vb1 = (*itBE)->getVertex(1); - seType = TYPE_QUA; + metaElType = TYPE_QUA; MEdge baseEd(vb0, vb1); firstEl = getFirstEl(vertex2elements, baseEd); foundVert = getBaseVertices(baseEd, firstEl, baseVert); if (!foundVert) continue; // Skip bnd. el. if base vertices not found - foundVert = getTopPrimVertices(vertex2elements, normVert, blc, baseEd, + foundVert = getTopPrimVertices(vertex2elements, normVert, baseEd, p.maxNumLayers, baseVert, topPrimVert); } else { // 2D boundary @@ -474,11 +505,11 @@ void curveMeshFromBnd(std::map<MVertex*, std::vector<MElement *> > &vertex2eleme MVertex *vb3; if (bndType == TYPE_QUA) { vb3 = (*itBE)->getVertex(3); - seType = TYPE_HEX; + metaElType = TYPE_HEX; } else { vb3 = 0; - seType = TYPE_PRI; + metaElType = TYPE_PRI; } MFace baseFace(vb0, vb1, vb2, vb3); firstEl = getFirstEl(vertex2elements, baseFace); @@ -489,23 +520,23 @@ void curveMeshFromBnd(std::map<MVertex*, std::vector<MElement *> > &vertex2eleme } foundVert = getBaseVertices(baseFace, firstEl, baseVert); if (!foundVert) continue; // Skip bnd. el. if base vertices not found - foundVert = getTopPrimVertices(vertex2elements, normVert, blc, + foundVert = getTopPrimVertices(vertex2elements, normVert, baseFace, p.maxNumLayers, baseVert, topPrimVert); } if (!foundVert) continue; // Skip bnd. el. if top vertices not found int order = firstEl->getPolynomialOrder(); - SuperEl se(seType, order, baseVert, topPrimVert); - of << se.printPOS(); + MetaEl metaEl(metaElType, order, baseVert, topPrimVert); + dbgOut.addMetaEl(metaEl); std::set<MElement*> blob; - get2DBLBlob(vertex2elements, firstEl, &se, blob); // TODO: Implement for 3D + get2DBLBlob(vertex2elements, firstEl, &metaEl, blob); // TODO: Implement for 3D for (std::set<MElement*>::iterator itE = blob.begin(); itE != blob.end(); ++itE) { makeStraight(*itE, movedVert); for (int i = (*itE)->getNumPrimaryVertices(); i < (*itE)->getNumVertices(); ++i) { // Loop over HO vert. of each el. in blob MVertex* vert = (*itE)->getVertex(i); if (movedVert.find(vert) == movedVert.end()) { // Try to move vert. not already moved double xyzS[3] = {vert->x(), vert->y(), vert->z()}, xyzC[3]; - if (se.straightToCurved(xyzS,xyzC)) { + if (metaEl.straightToCurved(xyzS,xyzC)) { vert->setXYZ(xyzC[0], xyzC[1], xyzC[2]); movedVert.insert(vert); } @@ -514,8 +545,7 @@ void curveMeshFromBnd(std::map<MVertex*, std::vector<MElement *> > &vertex2eleme } } - of << "};\n"; - of.close(); + dbgOut.write("meta-elements", bndEnt->tag()); } @@ -539,64 +569,26 @@ void HighOrderMeshFastCurving(GModel *gm, FastCurvingParameters &p) for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) calcVertex2Elements(p.dim, allEntities[iEnt], vertex2elements); - // Get BL field (if any) - BoundaryLayerField *blf = getBLField(gm); - // Build multimap of each geometric entity to its boundaries std::multimap<GEntity*,GEntity*> entities; - if (blf) { // BF field? - for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { - GEntity* &entity = allEntities[iEnt]; - if (entity->dim() == p.dim && (!p.onlyVisible || entity->getVisibility())) // Consider only "domain" entities - if (p.dim == 2) { // "Domain" face? - std::list<GEdge*> edges = entity->edges(); - for (std::list<GEdge*>::iterator itEd = edges.begin(); itEd != edges.end(); itEd++) // Loop over model boundary edges - if (blf->isEdgeBL((*itEd)->tag())) // Already skip model edge if no BL there - entities.insert(std::pair<GEntity*,GEntity*>(entity, *itEd)); - } - // else if (p.dim == 3) { // "Domain" region? - // std::list<GFace*> faces = entity->faces(); - // for (std::list<GFace*>::iterator itF = faces.begin(); itF != faces.end(); itF++) // Loop over model boundary faces - // if (blf->isFaceBL((*itF)->tag())) // Already skip model face if no BL there - // entities.insert(std::pair<GEntity*,GEntity*>(entity, *itF)); - // } - } - } - else { // No BL field - for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { - GEntity *dummy = 0; - GEntity* &entity = allEntities[iEnt]; - if (entity->dim() == p.dim-1 && (!p.onlyVisible || entity->getVisibility())) // Consider boundary entities - entities.insert(std::pair<GEntity*,GEntity*>(dummy, entity)); - } + for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { + GEntity *dummy = 0; + GEntity* &entity = allEntities[iEnt]; + if (entity->dim() == p.dim-1 && (!p.onlyVisible || entity->getVisibility())) // Consider boundary entities + entities.insert(std::pair<GEntity*,GEntity*>(dummy, entity)); } - // Build normals if necessary + // Build normals to base vertices std::map<GEntity*, std::map<MVertex*, SVector3> > normVertEnt; // Normal to each vertex for each geom. entity - if (!blf) { - Msg::Warning("Boundary layer data not found, trying to detect columns"); - buildNormals(vertex2elements, entities, p, normVertEnt); - } + buildNormals(vertex2elements, entities, p, normVertEnt); // Loop over geometric entities for (std::multimap<GEntity*,GEntity*>::iterator itBE = entities.begin(); itBE != entities.end(); itBE++) { GEntity *domEnt = itBE->first, *bndEnt = itBE->second; - BoundaryLayerColumns *blc = 0; - if (blf) { - Msg::Info("Curving elements for entity %d bounding entity %d...", - bndEnt->tag(), domEnt->tag()); - if (p.dim == 2) - blc = domEnt->cast2Face()->getColumns(); - else if (p.dim == 3) - blc = domEnt->cast2Region()->getColumns(); - else - Msg::Error("Fast curving implemented only in dim. 2 and 3"); - } - else - Msg::Info("Curving elements for boundary entity %d...", bndEnt->tag()); + Msg::Info("Curving elements for boundary entity %d...", bndEnt->tag()); std::map<MVertex*, SVector3> &normVert = normVertEnt[bndEnt]; - curveMeshFromBnd(vertex2elements, normVert, blc, bndEnt, p); + curveMeshFromBnd(vertex2elements, normVert, bndEnt, p); } double t2 = Cpu(); diff --git a/contrib/HighOrderMeshOptimizer/SuperEl.cpp b/contrib/HighOrderMeshOptimizer/SuperEl.cpp deleted file mode 100644 index 845c548d93..0000000000 --- a/contrib/HighOrderMeshOptimizer/SuperEl.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (C) 2013 ULg-UCL -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, and/or sell copies of the -// Software, and to permit persons to whom the Software is furnished -// to do so, provided that the above copyright notice(s) and this -// permission notice appear in all copies of the Software and that -// both the above copyright notice(s) and this permission notice -// appear in supporting documentation. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE -// COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR -// ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY -// DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -// OF THIS SOFTWARE. -// -// Please report all bugs and problems to the public mailing list -// <gmsh@onelab.info>. -// -// Contributor: Thomas Toulorge - -#include <iostream> -#include <sstream> -#include "GmshMessage.h" -#include "GEdge.h" -#include "MLine.h" -#include "MQuadrangle.h" -#include "MPrism.h" -#include "MHexahedron.h" -#include "BasisFactory.h" -#include "SuperEl.h" - -std::map<int,SuperEl::superInfoType> SuperEl::_superInfo; - -SuperEl::superInfoType::superInfoType(int type, int order) -{ - int iBaseFace = 0, iTopFace = 0; - switch (type) { - case TYPE_QUA: - iBaseFace = 0; iTopFace = 2; - break; - case TYPE_PRI: - iBaseFace = 0; iTopFace = 1; - break; - case TYPE_HEX: - iBaseFace = 0; iTopFace = 5; - break; - default: - Msg::Error("SuperEl not implemented for element of type %d", type); - nV = 0; - return; - } - - // Get HO nodal basis - const int tag = ElementType::getTag(type, order, true); // Get tag for incomplete element type -// const int tag = ElementType::getTag(type, order); // Get tag for complete element type - if(tag){ - const nodalBasis *basis = BasisFactory::getNodalBasis(tag); - - nV = basis->getNumShapeFunctions(); - // _superInfo[type].nV1 = basis->getNumShapeFunctions(); - points = basis->points; - - baseInd = basis->getClosure(basis->getClosureId(iBaseFace,1,0)); - topInd = basis->getClosure(basis->getClosureId(iTopFace,0,0)); - otherInd.reserve(nV-baseInd.size()-topInd.size()); - for(int i=0; i<nV; ++i) { - const std::vector<int>::iterator inBaseFace = find(baseInd.begin(),baseInd.end(),i); - const std::vector<int>::iterator inTopFace = find(topInd.begin(),topInd.end(),i); - if (inBaseFace == baseInd.end() && inTopFace == topInd.end()) otherInd.push_back(i); - } - } -} - - - -SuperEl::SuperEl(int type, int order, const std::vector<MVertex*> &baseVert, - const std::vector<MVertex*> &topPrimVert) : _superEl(0), _superEl0(0) -{ - - // Get useful info on meta-element type if not already there - std::map<int,SuperEl::superInfoType>::iterator itSInfo = _superInfo.find(type); - if (itSInfo == _superInfo.end()) - itSInfo = _superInfo.insert(std::pair<int,superInfoType>(type,superInfoType(type, order))).first; - SuperEl::superInfoType &sInfo = itSInfo->second; - - // Exit if unknown type - if (sInfo.nV == 0) return; - - // References for easier writing - const int &nV = sInfo.nV; - const fullMatrix<double> &points = sInfo.points; - const std::vector<int> &baseInd = sInfo.baseInd; - const std::vector<int> &topInd = sInfo.topInd; - const std::vector<int> &otherInd = sInfo.otherInd; - - // Add copies of vertices in base & top faces (only first-order vertices for top face) - _superVert.resize(nV); - for (int i=0; i<baseInd.size(); ++i) _superVert[baseInd[i]] = new MVertex(*baseVert[i]); - for (int i=0; i<topPrimVert.size(); ++i) _superVert[topInd[i]] = new MVertex(*topPrimVert[i]); - - // Create first-order meta-element - switch (type) { - case TYPE_QUA: - _superEl0 = new MQuadrangle(_superVert); - break; - case TYPE_PRI: - _superEl0 = new MPrism(_superVert); - break; - case TYPE_HEX: - _superEl0 = new MHexahedron(_superVert); - break; - default: - Msg::Error("SuperEl not implemented for element of type %d", type); - return; - } - - // Add HO vertices in top face - for (int i=topPrimVert.size(); i<topInd.size(); ++i) { - SPoint3 p; - const int ind = topInd[i]; - _superEl0->pnt(points(ind,0),points(ind,1),points(ind,2),p); - _superVert[ind] = new MVertex(p.x(),p.y(),p.z()); - } - - // Add vertices not in base & top faces - for (int i=0; i<otherInd.size(); ++i) { - SPoint3 p; - const int ind = otherInd[i]; - _superEl0->pnt(points(ind,0),points(ind,1),points(ind,2),p); - _superVert[ind] = new MVertex(p.x(),p.y(),p.z()); - } - - // Create high-order meta-element - switch (type) { - case TYPE_QUA: - _superEl = new MQuadrangleN(_superVert, order); - break; - case TYPE_PRI: - _superEl = new MPrismN(_superVert, order); - break; - case TYPE_HEX: - _superEl = new MHexahedronN(_superVert, order); - break; - } - - // Scale meta-element if not valid - // TODO: Scale depending on target Jmin? - // TODO: Could be improved by using complete meta-element and use optimization - for (int iter = 0; iter < 10; iter++) { - if (_superEl->distoShapeMeasure() > 0) break; - if (iter == 0) Msg::Warning("A meta-element has a negative distortion, trying to scale"); - for (int i=0; i<topPrimVert.size(); ++i) { // Move top primary vert. - MVertex *&vb = _superVert[baseInd[i]], *&vt = _superVert[topInd[i]]; - SPoint3 pb = vb->point(), pt = vt->point(); - pt += SPoint3(0.25*(pt-pb)); - vt->setXYZ(pt.x(), pt.y(), pt.z()); - } - for (int i=topPrimVert.size(); i<topInd.size(); ++i) { // Recompute HO vert. in top face - SPoint3 p; - const int ind = topInd[i]; - _superEl0->pnt(points(ind,0),points(ind,1),points(ind,2),p); - _superVert[ind]->setXYZ(p.x(),p.y(),p.z()); - } - for (int i=0; i<otherInd.size(); ++i) { // Recompute vert. not in base & top faces - SPoint3 p; - const int ind = otherInd[i]; - _superEl0->pnt(points(ind,0),points(ind,1),points(ind,2),p); - _superVert[ind]->setXYZ(p.x(),p.y(),p.z()); - } - } - -} - -SuperEl::~SuperEl() -{ - for (int i = 0; i < _superVert.size(); i++) delete _superVert[i]; - _superVert.clear(); - delete _superEl; - if(_superEl0) delete _superEl0; -} - -bool SuperEl::isPointIn(const SPoint3 p) const -{ - double xyz[3] = {p.x(), p.y(), p.z()}, uvw[3]; - _superEl0->xyz2uvw(xyz,uvw); - return _superEl0->isInside(uvw[0],uvw[1],uvw[2]); -} - -bool SuperEl::straightToCurved(double *xyzS, double *xyzC) const -{ - double uvw[3]; - _superEl0->xyz2uvw(xyzS,uvw); - if (!_superEl0->isInside(uvw[0],uvw[1],uvw[2])) return false; - - SPoint3 pC; - _superEl->pnt(uvw[0],uvw[1],uvw[2],pC); - xyzC[0] = pC[0]; - xyzC[1] = pC[1]; - xyzC[2] = pC[2]; - - return true; -} - -std::string SuperEl::printPOS() -{ - std::vector<MVertex*> verts; - _superEl->getVertices(verts); -// std::string posStr = _superEl->getStringForPOS(); - std::string posStr = _superEl0->getStringForPOS(); - int n = (posStr[posStr.size()-1]=='2' ? _superEl : _superEl0)->getNumVertices(); - - std::ostringstream oss; - - oss << posStr << "("; - for(int i = 0; i < n; i++){ - if(i) oss << ","; - oss << _superVert[i]->x() << "," << _superVert[i]->y() << "," << _superVert[i]->z(); - } - oss << "){0."; - for(int i = 1; i < n; i++) oss << ",0."; - oss << "};\n"; - - return oss.str(); -} -- GitLab