From 81da27f3578147fd271c5fc98b59548559d88f68 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Thu, 23 May 2019 13:48:15 -0400 Subject: [PATCH 01/48] First commit for EdgeOptim Operator. This operator takes in an edge and tries to reshape the edge by using LBFGS optimization on a user defined objective functions. --- crv/CMakeLists.txt | 2 + crv/LBFGS.cc | 194 ++++++++++++++++++++++++ crv/LBFGS.h | 53 +++++++ crv/crvEdgeOptim.cc | 349 ++++++++++++++++++++++++++++++++++++++++++++ crv/crvEdgeOptim.h | 78 ++++++++++ crv/crvQuality.cc | 4 +- crv/crvQuality.h | 4 + 7 files changed, 682 insertions(+), 2 deletions(-) create mode 100644 crv/LBFGS.cc create mode 100644 crv/LBFGS.h create mode 100644 crv/crvEdgeOptim.cc create mode 100644 crv/crvEdgeOptim.h diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 992589d23..59d70bae1 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -20,6 +20,8 @@ set(SOURCES crvTables.cc crvQuality.cc crvVtk.cc + LBFGS.cc + crvEdgeOptim.cc ) # Package headers diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc new file mode 100644 index 000000000..b9344cd6e --- /dev/null +++ b/crv/LBFGS.cc @@ -0,0 +1,194 @@ +#include "LBFGS.h" +#include +#include "apfMatrix.h" + +namespace crv{ + +//void LBFGS::setInitialValue(std::vector x) +//{ +// x0 = x; +//} + +std::vector LBFGS::getCurrentX() +{ + return currentX; +} + +static double dotP(const std::vector &v1, const std::vector &v2) +{ + double sum = 0.0; + for (std::size_t i = 0; i < v1.size(); i++) { + sum += v1[i]*v2[i]; + } + return sum; +} + +double LBFGS::getFvalueAfter() +{ + return fValAfter; +} + +double LBFGS::lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax) +{ + double alpha = 1.0e-4, tolOndeltaX = 1.0e-8; + int itrs = 2000; + double a, alam, alam2 = 0.0, alamin, b, disc, f2 = 0.0; + double rhs1, rhs2, slope = 0.0, sum = 0.0, temp, test, tmplam; + int n = xold.size(); + + std::vector xnew(xold.size(), 0.0); + sum = sqrt(dotP(direction,direction)); + if (sum > stpmax) { + for (int i = 0; i < n; i++) { + direction[i] *= stpmax/sum; + } + } +// for (int i = 0; i < n; i++) slope += g[i]*p[i]; + slope = dotP(g,direction); +//if (slope >= 0.0) std::cout<<"slope positive"< test) test = temp; + } + alamin = tolOndeltaX/test; + alam = 1.0; + + double fold = objFunc->getValue(xold); + + for (int k = 0; k < itrs; k++) { + for (int i =0; i < n; i++) xnew[i] = xold[i] + alam*direction[i]; + + double fnew = objFunc->getValue(xnew); + if (alam < alamin || fnew <= fold + alpha*alam*slope) { + std::cout<<"fval "< 0.5*alam) tmplam = 0.5*alam; + } + } + alam2 = alam; + alam = std::max(tmplam, 0.1*alam); + } + return alam; +} + +void LBFGS::moveArrayToLeft(std::vector a[], int r) +{ + for (int i = 0; i < r-1; i++) + a[i] = a[i+1]; +} + +bool LBFGS::run() +{ + std::vector p(x0.size(), 0.0); + std::vector xs[r]; + std::vector gs[r]; + std::vector gdiffs[r]; + double gammas[r]; + + for(int i = 0; i < r; ++i) + { + xs[i] = std::vector(x0.size(), 0.0); + gs[i] = std::vector(x0.size(), 0.0); + gdiffs[i] = std::vector(x0.size(), 0.0); + gammas[i] = 0.0; + } + + xs[0] = x0; + gs[0] = objFunc->getGrad(x0); + + //gdiffs[0] (gs[0]); + + for (std::size_t i = 0; i < xs[0].size(); i++) p[i] = -gs[0][i]; + + for (int k = 0; k < iter; k++) { + int I = 0; + int J = 0; + if (k+1 < r) { + I = k+1; + J = k; + } + else { + I = r-1; + J = I-1; + moveArrayToLeft(xs, r); + moveArrayToLeft(gs, r); + } + double n = objFunc->getSpaceDim(); + double m = sqrt(dotP(p, p)); + //double stpmax = 100.0 * (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); + double stpmax = 100.0 * (std::max(m, n)); + double lambda = lineSearch(xs[J], gs[J], p, stpmax); + + for (std::size_t j = 0; j < xs[I].size(); j++) + xs[I][j] = xs[J][j] + lambda * p[j]; + + gs[I] = objFunc->getGrad(xs[I]); + + if ( I > 0) { + for (std::size_t jj = 0; jj < gs[I].size(); jj++) + gdiffs[I-1][jj] = gs[I][jj] - gs[I-1][jj]; + } + + if ((dotP(gs[I],gs[I]) < tol) || (dotP(gdiffs[I-1], gdiffs[I-1])) < tol) { + currentX = xs[I]; + fValAfter = objFunc->getValue(xs[I]); + std::cout<<"number of LBFGS iterations: "<= 0; --i) { + std::vector s(xs[I].size(), 0.0); + std::vector y(xs[I].size(), 0.0); + for( std::size_t j = 0; j < xs[i+1].size(); j++) { + s[j] = xs[i+1][j] - xs[i][j]; + y[j] = gs[i+1][j] - gs[i][j]; + } + double rho = 1 / dotP(s, y); + gammas[i] = rho * dotP(s, p); + for(std::size_t j = 0; j < p.size(); j++) + p[j] = p[j] - gammas[i]*y[j]; + } + + for (int i = 0; i <= I-1; i++) { + std::vector s(xs[I].size(), 0.0); + std::vector y(xs[I].size(), 0.0); + for( std::size_t j = 0; j < xs[i+1].size(); j++) { + s[j] = xs[i+1][j] - xs[i][j]; + y[j] = gs[i+1][j] - gs[i][j]; + } + double rho = 1 / dotP(s, y); + double phi = rho* dotP(y, p); + for(std::size_t j = 0; j < p.size(); j++) + p[j] = p[j] + s[j]* (gammas[i] - phi); + } + + if (dotP(p, gs[I]) > 0) + for (std::size_t j = 0; j < p.size(); j++) p[j] = -p[j]; + + } + return false; + +} + +} // end of namespace + diff --git a/crv/LBFGS.h b/crv/LBFGS.h new file mode 100644 index 000000000..337a84b97 --- /dev/null +++ b/crv/LBFGS.h @@ -0,0 +1,53 @@ + +#ifndef LBFGS_H +#define LBFGS_H + +#include +#include +#include + +namespace crv{ + +class ObjFunction +{ + public: + ObjFunction(){}; + + public: + virtual double getValue(std::vector &x) = 0; + virtual std::vector getGrad(std::vector &x) = 0; + //virtual int getVectorDim() = 0; + virtual int getSpaceDim() = 0; +}; + +class LBFGS +{ +public: + LBFGS(double inTol, int inIter, const std::vector &x, ObjFunction *inObjFunc): + tol(inTol), iter(inIter), x0(x), objFunc(inObjFunc) {} + + ~LBFGS() {} + +public: + //void setInitialValue(std::vector x); + std::vector getCurrentX(); + double getFvalueAfter(); + double lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax); + void moveArrayToLeft(std::vector a[], int r); + bool run(); + +public: + double tol; + int iter; + std::vector x0; + ObjFunction *objFunc; + std::vector currentX; + double fValAfter; + +private: + int r = 20; +}; + +} + +#endif diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc new file mode 100644 index 000000000..55a59efbf --- /dev/null +++ b/crv/crvEdgeOptim.cc @@ -0,0 +1,349 @@ +#include "crvEdgeOptim.h" +#include "LBFGS.h" +#include "crv.h" +#include "crvQuality.h" +#include "crvBezier.h" +#include "crvMath.h" +#include +#include "apfMatrix.h" + +namespace crv{ + +int CrvEdgeReshapeObjFunc :: getSpaceDim() +{ + return P*d; +} + +void CrvEdgeReshapeObjFunc :: getInitEdgeN() +{ + apf::Vector3 intEdgeX; + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + + for (int i = 0; i < numENodes; i++) { + mesh->getPoint(edge, i, intEdgeX); + ien.push_back(intEdgeX); + } +} + +void CrvEdgeReshapeObjFunc :: getInitFaceN() +{ + apf::Adjacent adjF; + apf::Vector3 intFaceX; + mesh->getAdjacent(edge, 2, adjF); + int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFaceX); + ifn.push_back(intFaceX); + } + } +} + +void CrvEdgeReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(edge, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +std::vector CrvEdgeReshapeObjFunc :: getInitialGuess() +{ + return convertNodeVectorToX(ien); +} + +std::vector CrvEdgeReshapeObjFunc :: convertNodeVectorToX(std::vector eftn) +{ + std::vector x0; + for (int i = 0; i < P-1; i++) + for (int j = 0; j < 3; j++) + x0.push_back(eftn[i][j]); + + return x0; +} + +std::vector CrvEdgeReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) +{ + std::vector a; + apf::Vector3 v; + if (d == 2) { + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < numENodes; i++) { + v = {x[d*i], x[d*i + 1], 0.0}; + a.push_back(v); + } + } + if (d == 3) { + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < numENodes; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + } + return a; +} + +void CrvEdgeReshapeObjFunc :: blendTris(const std::vector &egn, std::vector &faceNodes) +{ + apf::Vector3 xi; + apf::Adjacent adjF; + apf::Adjacent adjE; + std::vector cien (ien.begin(),ien.end()); + + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + mesh->getAdjacent(adjF[i], 1, adjE); + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (std::size_t j = 0; j < adjE.getSize(); j++) { + if (adjE[j] == edge) { + int jj = 1; + + if ( j == 0) + jj = 2; + else if ( j == 1) + jj = 0; + else + jj = 1; + + for (int k = 0; k < numFNodes; k++) { + getBezierNodeXi(mesh->TRIANGLE, P, k, xi); + for (std::size_t ii = 0; ii < egn.size(); ii++) { + double factor = 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) + + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); + faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - cien[ii])*factor; + } + } + } + } + } +} + +void CrvEdgeReshapeObjFunc :: updateNodes(std::vector ed, std::vector fa, std::vector te) +{ + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < numENodes; i++) + mesh->setPoint(edge, i, ed[i]); + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); + } + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } +} + + +void CrvEdgeReshapeObjFunc :: setNodes(std::vector &x) +{ + std::vector en (ien.begin(), ien.end()); + std::vector fn (ifn.begin(), ifn.end()); + std::vector tn (itn.begin(), itn.end()); + en = convertXtoNodeVector(x); + blendTris(en, fn); + + updateNodes(en, fn, tn); +} + +std::vector CrvEdgeReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(v); + } + } + if (d == 2) { + apf::Adjacent adjF; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 2, adjF); + apf::Vector3 point; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjF[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) { + if (k < 2) m[j][k] = point[k]; + else m[j][2] = 1.0; + } + } + double v = getDeterminant(m); + vol.push_back(v); + } + } + return vol; +} + +double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + std::cout< &x) +{ + setNodes(x); + + double sum = 0.0; + if (d == 2) { + apf::Adjacent adjF; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + return sum; +} + +std::vector CrvEdgeReshapeObjFunc :: getGrad(std::vector &x) +{ + double fold = getValue(x); + double eps = 1.0e-4; + double h; + std::vector g; + + for (std::size_t i = 0; i < x.size(); i++) { + if (std::abs(x[i]) > eps) + h = eps * std::abs(x[i]); + else + h = eps; + + x[i] = x[i] + h; + double fnew = getValue(x); + x[i] = x[i] - h; + g.push_back((fnew-fold)/h); + } + return g; +} + +void CrvEdgeOptim :: setMaxIter(int n) +{ + iter = n; +} + +void CrvEdgeOptim :: setTol(double t) +{ + tol = t; +} + +bool CrvEdgeOptim :: run() +{ + CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); + std::vector x0 = objF->getInitialGuess(); + double f0 = objF->getValue(x0); + std::cout<< "fval at x0 " << f0<run()) { + finalX = l->currentX; + fval = l->fValAfter; + objF->setNodes(finalX); + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + if (checkValidity(mesh, adjT[i], 1) > 1) { + objF->restoreInitialNodes(); + return false; + } + } + return true; + } + else + return false; +} + +} diff --git a/crv/crvEdgeOptim.h b/crv/crvEdgeOptim.h new file mode 100644 index 000000000..bcc14c652 --- /dev/null +++ b/crv/crvEdgeOptim.h @@ -0,0 +1,78 @@ +#ifndef CRVEDGEOPTIM_H +#define CRVEDGEOPTIM_H + +#include +#include +#include +#include "apf.h" +#include "apfMesh.h" +#include "apfMesh2.h" +#include "LBFGS.h" +#include "apfShape.h" + +namespace crv{ + +class CrvEdgeReshapeObjFunc : public ObjFunction +{ + public: + CrvEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e) : + mesh(m), edge(e) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitEdgeN(); + getInitFaceN(); + getInitTetN(); + } + public: + int getSpaceDim(); + double getValue(std::vector &x); + std::vector getGrad(std::vector &x); + std::vector getInitialGuess(); + void setNodes(std::vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + + private: + void getInitEdgeN(); + void getInitFaceN(); + void getInitTetN(); + std::vector convertNodeVectorToX(std::vector eftn); + std::vector convertXtoNodeVector(const std::vector &x); + void blendTris(const std::vector &edgeNodes, std::vector &faceNodes); + //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); + void updateNodes(std::vector ed, std::vector fa, std::vector te); + std::vector getVolume(); + double computeFValOfElement(apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + std::vector vol; + std::vector ien; + std::vector ifn; + std::vector itn; +}; + +class CrvEdgeOptim +{ + public: + CrvEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e) : + mesh(m), edge(e) {} + public: + void setMaxIter(int n); + void setTol(double t); + bool run(); + public: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + int iter; + double tol; + std::vector finalX; + double fval; +}; +} + +#endif diff --git a/crv/crvQuality.cc b/crv/crvQuality.cc index 04119933a..ff6a3f124 100644 --- a/crv/crvQuality.cc +++ b/crv/crvQuality.cc @@ -141,7 +141,7 @@ static double getTetPartialJacobianDet(apf::NewArray& nodes, * 2D planar meshes. * */ -static double Nijk(apf::NewArray& nodes, +double Nijk(apf::NewArray& nodes, int d, int I, int J) { double sum = 0.; @@ -157,7 +157,7 @@ static double Nijk(apf::NewArray& nodes, return sum*d*d/CD; } -static double Nijkl(apf::NewArray& nodes, +double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K) { double sum = 0.; diff --git a/crv/crvQuality.h b/crv/crvQuality.h index e06ad2d1a..60c115ba5 100644 --- a/crv/crvQuality.h +++ b/crv/crvQuality.h @@ -38,6 +38,10 @@ extern const SubdivisionFunction subdivideBezierJacobianDet[apf::Mesh::TYPES]; void elevateBezierJacobianDet(int type, int P, int r, apf::NewArray& nodes, apf::NewArray& elevatedNodes); + +double Nijk(apf::NewArray& nodes, int d, int I, int J); +double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K); + } #endif From 0c0fd072a025130b9c68a377d0270f917d34b6cf Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Wed, 29 May 2019 15:33:33 -0400 Subject: [PATCH 02/48] Optimization based edge reshape included for order less than 3. --- crv/crvCurveMesh.cc | 8 +++--- crv/crvShape.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 5cc39bbfb..55d26f0d2 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -193,9 +193,11 @@ bool BezierCurver::run() convertInterpolatingToBezier(); - if( m_mesh->getDimension() >= 2 && m_order == 2){ - ma::Input* shapeFixer = configureShapeCorrection(m_mesh); - crv::adapt(shapeFixer); + if (m_mesh->getDimension() >= 2) { + if (m_order == 2 || m_order == 3) { + ma::Input* shapeFixer = configureShapeCorrection(m_mesh); + crv::adapt(shapeFixer); + } } m_mesh->acceptChanges(); diff --git a/crv/crvShape.cc b/crv/crvShape.cc index d24598abb..2dec39a50 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -19,6 +19,7 @@ #include #include #include +#include "crvEdgeOptim.h" /* This is similar to maShape.cc, conceptually, but different enough * that some duplicate code makes sense */ @@ -315,6 +316,55 @@ class EdgeReshaper : public ma::Operator int nr; }; +class EdgeOptimizer : public ma::Operator +{ +public: + EdgeOptimizer(Adapt* a) { + adapter = a; + mesh = a->mesh; + edge = 0; + ns = 0; + nf = 0; + } + ~EdgeOptimizer() { + } + virtual int getTargetDimension() {return 1;} + virtual bool shouldApply(ma::Entity* e) { + if (ma::getFlag(adapter, e, ma::COLLAPSE) || ma::getFlag(adapter, e, ma::BAD_QUALITY) || isBoundaryEntity(mesh, e)) + return false; + else { + edge = e; + return true; + } + } + + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(&edge,1); + } + + virtual void apply(){ + CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edge); + ceo->setMaxIter(100); + ceo->setTol(1e-8); + + if (ceo->run()) ns++; + else nf++; + + ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + + delete(ceo); + } +private: +protected: + Adapt* adapter; + ma::Mesh* mesh; + ma::Entity* edge; +public: + int ns; + int nf; +}; + static bool isCornerTriAngleLargeMetric(crv::Adapt *a, ma::Entity* tri, int index) { @@ -586,6 +636,16 @@ static void repositionInvalidEdges(Adapt* a) "in %f seconds",es.nr, t1-t0); } +static void optimizeInvalidEdges(Adapt* a) +{ + double t0 = PCU_Time(); + EdgeOptimizer eo(a); + ma::applyOperator(a,&eo); + double t1 = PCU_Time(); + ma::print("Optimized %d bad edges " + "in %f seconds",eo.ns, t1-t0); +} + int fixInvalidEdges(Adapt* a) { int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); @@ -595,6 +655,9 @@ int fixInvalidEdges(Adapt* a) if(a->mesh->getShape()->getOrder() == 2) repositionInvalidEdges(a); + else + optimizeInvalidEdges(a); + collapseInvalidEdges(a); swapInvalidEdges(a); return count; From fe25096204584772bb6c3352e947388f71e14b31 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 8 Jun 2019 23:39:28 -0400 Subject: [PATCH 03/48] edge reshape only. --- crv/LBFGS.cc | 12 ++--- crv/crvCurveMesh.cc | 123 +++++++++++++++++++++++++++++++++++++++++++- crv/crvEdgeOptim.cc | 12 +++-- crv/crvShape.cc | 9 +++- 4 files changed, 139 insertions(+), 17 deletions(-) diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc index b9344cd6e..4c609fa13 100644 --- a/crv/LBFGS.cc +++ b/crv/LBFGS.cc @@ -62,7 +62,6 @@ double LBFGS::lineSearch(std::vector &xold, std::vector &g, std: double fnew = objFunc->getValue(xnew); if (alam < alamin || fnew <= fold + alpha*alam*slope) { - std::cout<<"fval "<getGrad(x0); - //gdiffs[0] (gs[0]); - for (std::size_t i = 0; i < xs[0].size(); i++) p[i] = -gs[0][i]; for (int k = 0; k < iter; k++) { @@ -131,10 +128,7 @@ bool LBFGS::run() moveArrayToLeft(xs, r); moveArrayToLeft(gs, r); } - double n = objFunc->getSpaceDim(); - double m = sqrt(dotP(p, p)); - //double stpmax = 100.0 * (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); - double stpmax = 100.0 * (std::max(m, n)); + double stpmax = 100.0 * (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); double lambda = lineSearch(xs[J], gs[J], p, stpmax); for (std::size_t j = 0; j < xs[I].size(); j++) @@ -147,10 +141,10 @@ bool LBFGS::run() gdiffs[I-1][jj] = gs[I][jj] - gs[I-1][jj]; } - if ((dotP(gs[I],gs[I]) < tol) || (dotP(gdiffs[I-1], gdiffs[I-1])) < tol) { + if ((dotP(gs[I],gs[I]) < tol) || (dotP(gdiffs[I-1], gdiffs[I-1]) < tol)) { currentX = xs[I]; fValAfter = objFunc->getValue(xs[I]); - std::cout<<"number of LBFGS iterations: "< +#include "crvMath.h" #include namespace crv { @@ -192,8 +193,126 @@ bool BezierCurver::run() } convertInterpolatingToBezier(); +/* +//------------------------------------------------------------------- +//----------------------------------------------for testing cubic slab +//------------------------------------------------------------------- + + writeCurvedVtuFiles(m_mesh, apf::Mesh::TRIANGLE, 20, "slab-crv-before"); + writeCurvedWireFrame(m_mesh, 20,"slabcrv-w-before"); + + apf::MeshEntity* e; + apf::MeshIterator* it = m_mesh->begin(1); + + std::vector frtwo; + frtwo.push_back({-0.1666667, -0.5, -0.46156}); + frtwo.push_back({0.166667, -0.5, 0.361564}); + + std::vector twfur; + twfur.push_back({-0.1666667, 0.5, -0.46156}); + twfur.push_back({0.1666667, 0.5, 0.361564}); + + std::vector nitwo; + nitwo.push_back({0.1666667, -0.16666667, 0.361564}); + nitwo.push_back({-0.1666667, 0.16666667, -0.461564}); + + while ((e = m_mesh->iterate(it))){ + + int tagEd = m_mesh->getModelTag(m_mesh->toModel(e)); + apf::Vector3 nodex; + + for (int i = 0; i < 2; i++) { + m_mesh->getPoint(e, i, nodex); + std::cout<<"tag "<< tagEd<< " {"<getDimension() >= 2) { + if (tagEd == 42) { + for (int iia = 0; iia < 2; iia++) { + apf::Vector3 p3; + m_mesh->getPoint(e, iia, p3); + + if (p3[0] > 0) + m_mesh->setPoint(e, iia, frtwo[1]); + else + m_mesh->setPoint(e, iia, frtwo[0]); + } + } + else if (tagEd == 24) { + for (int iia = 0; iia < 2; iia++) { + apf::Vector3 p3; + m_mesh->getPoint(e, iia, p3); + + if (p3[0] > 0) + m_mesh->setPoint(e, iia, twfur[1]); + else + m_mesh->setPoint(e, iia, twfur[0]); + } + } + else { + for (int iia = 0; iia < 2; iia++) { + apf::Vector3 p3; + m_mesh->getPoint(e, iia, p3); + + if (p3[0] > 0) + m_mesh->setPoint(e, iia, nitwo[0]); + else + m_mesh->setPoint(e, iia, nitwo[1]); + } + } + } + } + m_mesh->end(it); + + m_mesh->acceptChanges(); + + apf::MeshEntity* etet; + apf::MeshIterator* itt = m_mesh->begin(3); + + while ((etet = m_mesh->iterate(itt))) { + apf::MeshEntity* es[12]; + int ne = m_mesh->getDownward(etet, 1, es); + + apf::MeshEntity* fs[12]; + int nf = m_mesh->getDownward(etet, 2, fs); + + for (int i = 0; i < nf; i++) { + apf::MeshEntity* fes[3]; + apf::Vector3 ff(0., 0., 0.); + + m_mesh->getDownward(fs[i], 1, fes); + + for (int j = 0; j < 3; j++) { + int whe = apf::findIn(es, ne, fes[j]); + + for (int jj = 0; jj < 2; jj++) { + apf::Vector3 exyz(0.,0.,0); + m_mesh->getPoint(es[whe], jj, exyz); + ff = ff + exyz * 2./3.; + } + } + ff = ff * 1./4.; + m_mesh->setPoint(fs[i], 0, ff); + } + apf::NewArray allNodes; + apf::Element* el = apf::createElement(m_mesh->getCoordinateField(), etet); + apf::getVectorNodes(el, allNodes); + for (int jjj = 0; jjj < 20; jjj++) + std::cout<end(itt); + m_mesh->acceptChanges(); + + writeCurvedVtuFiles(m_mesh, apf::Mesh::TRIANGLE, 20, "slab-crv-initial"); + writeCurvedWireFrame(m_mesh, 20,"slabcrv-w-initial"); +//----------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------- +*/ + if(m_mesh->getDimension() >= 2) { if (m_order == 2 || m_order == 3) { ma::Input* shapeFixer = configureShapeCorrection(m_mesh); crv::adapt(shapeFixer); diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 55a59efbf..7d1443ee4 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -223,7 +223,6 @@ double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray weight = 1; if (I + J + K + L == d*(P-1)) { double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - std::cout< x0 = objF->getInitialGuess(); - double f0 = objF->getValue(x0); - std::cout<< "fval at x0 " << f0<getValue(x0); + //std::cout<< "fval at x0 " << f0<run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); + apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { if (checkValidity(mesh, adjT[i], 1) > 1) { objF->restoreInitialNodes(); + std::cout<<"optimization success but invalid entity+++++"< Date: Wed, 19 Jun 2019 14:01:33 -0400 Subject: [PATCH 04/48] face nodes included in the optimizer. --- crv/LBFGS.cc | 4 +- crv/LBFGS.h | 2 +- crv/crv.h | 9 ++- crv/crvAdapt.cc | 4 +- crv/crvCurveMesh.cc | 130 +++----------------------------------------- crv/crvEdgeOptim.cc | 123 ++++++++++++++++++++++++++++++++--------- crv/crvEdgeOptim.h | 2 +- crv/crvShape.cc | 4 +- 8 files changed, 120 insertions(+), 158 deletions(-) diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc index 4c609fa13..84f13006f 100644 --- a/crv/LBFGS.cc +++ b/crv/LBFGS.cc @@ -40,7 +40,7 @@ double LBFGS::lineSearch(std::vector &xold, std::vector &g, std: sum = sqrt(dotP(direction,direction)); if (sum > stpmax) { for (int i = 0; i < n; i++) { - direction[i] *= stpmax/sum; + direction[i] = direction[i]*stpmax/sum; } } // for (int i = 0; i < n; i++) slope += g[i]*p[i]; @@ -128,7 +128,7 @@ bool LBFGS::run() moveArrayToLeft(xs, r); moveArrayToLeft(gs, r); } - double stpmax = 100.0 * (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); + double stpmax = (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); double lambda = lineSearch(xs[J], gs[J], p, stpmax); for (std::size_t j = 0; j < xs[I].size(); j++) diff --git a/crv/LBFGS.h b/crv/LBFGS.h index 337a84b97..d088131e6 100644 --- a/crv/LBFGS.h +++ b/crv/LBFGS.h @@ -45,7 +45,7 @@ class LBFGS double fValAfter; private: - int r = 20; + int r = 25; }; } diff --git a/crv/crv.h b/crv/crv.h index 60e8c2c1a..c68a11fca 100644 --- a/crv/crv.h +++ b/crv/crv.h @@ -47,13 +47,16 @@ class MeshCurver public: MeshCurver(apf::Mesh2* m, int P) : m_mesh(m), m_order(P) {}; virtual ~MeshCurver() {}; - virtual bool run() = 0; + virtual bool run(bool flag) = 0; /** \brief snaps points to interpolating locations */ void snapToInterpolate(int dim); /** \brief wrapper around synchronizeFieldData */ void synchronize(); + + //public: + // bool flag = 1; protected: apf::Mesh2* m_mesh; @@ -88,9 +91,11 @@ class BezierCurver : public MeshCurver /** \brief curves a mesh using bezier curves of chosen order \details finds interpolating points, then converts to control points see crvBezier.cc */ - virtual bool run(); + virtual bool run(bool flag); /** \brief converts interpolating points to bezier control points */ void convertInterpolatingToBezier(); + //public: + // bool flag = true; }; /** \brief this curves a mesh with 4th order G1 Patches diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 3b6baec15..c8c1bef19 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -163,7 +163,7 @@ ma::Input* configureShapeCorrection( static int fixInvalidElements(crv::Adapt* a) { - a->input->shouldForceAdaptation = true; + a->input->shouldForceAdaptation = false; int count = crv::fixLargeBoundaryAngles(a) + crv::fixInvalidEdges(a); int originalCount = count; @@ -220,7 +220,7 @@ void adapt(ma::Input* in) fixCrvElementShapes(a); } - allowSplitCollapseOutsideLayer(a); + //allowSplitCollapseOutsideLayer(a); if (in->maximumIterations > 0) { fixInvalidElements(a); diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 98f031f49..3e656ecb0 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -171,7 +171,7 @@ void BezierCurver::convertInterpolatingToBezier() synchronize(); } -bool BezierCurver::run() +bool BezierCurver::run(bool flag) { std::string name = m_mesh->getShape()->getName(); if(m_order < 1 || m_order > 6){ @@ -193,129 +193,13 @@ bool BezierCurver::run() } convertInterpolatingToBezier(); -/* -//------------------------------------------------------------------- -//----------------------------------------------for testing cubic slab -//------------------------------------------------------------------- - - writeCurvedVtuFiles(m_mesh, apf::Mesh::TRIANGLE, 20, "slab-crv-before"); - writeCurvedWireFrame(m_mesh, 20,"slabcrv-w-before"); - - apf::MeshEntity* e; - apf::MeshIterator* it = m_mesh->begin(1); - - std::vector frtwo; - frtwo.push_back({-0.1666667, -0.5, -0.46156}); - frtwo.push_back({0.166667, -0.5, 0.361564}); - - std::vector twfur; - twfur.push_back({-0.1666667, 0.5, -0.46156}); - twfur.push_back({0.1666667, 0.5, 0.361564}); - - std::vector nitwo; - nitwo.push_back({0.1666667, -0.16666667, 0.361564}); - nitwo.push_back({-0.1666667, 0.16666667, -0.461564}); - - while ((e = m_mesh->iterate(it))){ - - int tagEd = m_mesh->getModelTag(m_mesh->toModel(e)); - apf::Vector3 nodex; - - for (int i = 0; i < 2; i++) { - m_mesh->getPoint(e, i, nodex); - std::cout<<"tag "<< tagEd<< " {"<getPoint(e, iia, p3); - - if (p3[0] > 0) - m_mesh->setPoint(e, iia, frtwo[1]); - else - m_mesh->setPoint(e, iia, frtwo[0]); - } - } - else if (tagEd == 24) { - for (int iia = 0; iia < 2; iia++) { - apf::Vector3 p3; - m_mesh->getPoint(e, iia, p3); - - if (p3[0] > 0) - m_mesh->setPoint(e, iia, twfur[1]); - else - m_mesh->setPoint(e, iia, twfur[0]); - } - } - else { - for (int iia = 0; iia < 2; iia++) { - apf::Vector3 p3; - m_mesh->getPoint(e, iia, p3); - - if (p3[0] > 0) - m_mesh->setPoint(e, iia, nitwo[0]); - else - m_mesh->setPoint(e, iia, nitwo[1]); - } - } - } - } - m_mesh->end(it); - - m_mesh->acceptChanges(); - - apf::MeshEntity* etet; - apf::MeshIterator* itt = m_mesh->begin(3); - - while ((etet = m_mesh->iterate(itt))) { - apf::MeshEntity* es[12]; - int ne = m_mesh->getDownward(etet, 1, es); - - apf::MeshEntity* fs[12]; - int nf = m_mesh->getDownward(etet, 2, fs); - - for (int i = 0; i < nf; i++) { - apf::MeshEntity* fes[3]; - apf::Vector3 ff(0., 0., 0.); - - m_mesh->getDownward(fs[i], 1, fes); - - for (int j = 0; j < 3; j++) { - int whe = apf::findIn(es, ne, fes[j]); - - for (int jj = 0; jj < 2; jj++) { - apf::Vector3 exyz(0.,0.,0); - m_mesh->getPoint(es[whe], jj, exyz); - ff = ff + exyz * 2./3.; - } + if (flag == 1) { + if(m_mesh->getDimension() >= 2) { + if (m_order == 2 || m_order == 3) { + ma::Input* shapeFixer = configureShapeCorrection(m_mesh); + shapeFixer->maximumIterations = 0; + crv::adapt(shapeFixer); } - ff = ff * 1./4.; - m_mesh->setPoint(fs[i], 0, ff); - } - apf::NewArray allNodes; - apf::Element* el = apf::createElement(m_mesh->getCoordinateField(), etet); - apf::getVectorNodes(el, allNodes); - for (int jjj = 0; jjj < 20; jjj++) - std::cout<end(itt); - m_mesh->acceptChanges(); - - writeCurvedVtuFiles(m_mesh, apf::Mesh::TRIANGLE, 20, "slab-crv-initial"); - writeCurvedWireFrame(m_mesh, 20,"slabcrv-w-initial"); -//----------------------------------------------------------------------------------- -//----------------------------------------------------------------------------------- -//----------------------------------------------------------------------------------- -*/ - if(m_mesh->getDimension() >= 2) { - if (m_order == 2 || m_order == 3) { - ma::Input* shapeFixer = configureShapeCorrection(m_mesh); - crv::adapt(shapeFixer); } } diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 7d1443ee4..a4ca6a91d 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -55,16 +55,25 @@ void CrvEdgeReshapeObjFunc :: getInitTetN() std::vector CrvEdgeReshapeObjFunc :: getInitialGuess() { - return convertNodeVectorToX(ien); + return convertNodeVectorToX(ien, ifn, itn); } -std::vector CrvEdgeReshapeObjFunc :: convertNodeVectorToX(std::vector eftn) +std::vector CrvEdgeReshapeObjFunc :: convertNodeVectorToX(std::vector en, std::vector fn, std::vector tn) { std::vector x0; for (int i = 0; i < P-1; i++) for (int j = 0; j < 3; j++) - x0.push_back(eftn[i][j]); + x0.push_back(en[i][j]); + for (std::size_t i = 0; i < fn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(fn[i][j]); + + if (d > 2 && P > 3) { + for (std::size_t i = 0; i < tn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(tn[i][j]); + } return x0; } @@ -73,15 +82,18 @@ std::vector CrvEdgeReshapeObjFunc :: convertXtoNodeVector(const st std::vector a; apf::Vector3 v; if (d == 2) { - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < numENodes; i++) { + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + //check later for 2D case:: x should not include z coordinate in optim search + for (std::size_t i = 0; i < num; i++) { v = {x[d*i], x[d*i + 1], 0.0}; a.push_back(v); } } if (d == 3) { - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < numENodes; i++) { + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { v = {x[d*i], x[d*i + 1], x[d*i + 2]}; a.push_back(v); } @@ -152,11 +164,29 @@ void CrvEdgeReshapeObjFunc :: updateNodes(std::vector ed, std::vec void CrvEdgeReshapeObjFunc :: setNodes(std::vector &x) { - std::vector en (ien.begin(), ien.end()); - std::vector fn (ifn.begin(), ifn.end()); - std::vector tn (itn.begin(), itn.end()); - en = convertXtoNodeVector(x); - blendTris(en, fn); + std::vector en;// (ien.begin(), ien.end()); + std::vector fn;// (ifn.begin(), ifn.end()); + std::vector tn;// (itn.begin(), itn.end()); + std::vector nod = convertXtoNodeVector(x); + //blendTris(en, fn); + //from all internal node vector to distict vector of nodes + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i getShape()->countNodesOn(mesh->TRIANGLE); + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + + for (std::size_t i = nEN; i < nEN + nFN*adjF.size(); i++) + fn.push_back(nod[i]); + + if (d > 2 && P > 3) { + //int nTN = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = nEN+nFN; i for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) weight = 2; + else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) + weight = 1.5; else - weight = 1; + weight = 0.5; if (I + J + K + L == d*(P-1)) { double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< &x) std::vector CrvEdgeReshapeObjFunc :: getGrad(std::vector &x) { double fold = getValue(x); - double eps = 1.0e-4; - double h; + double eps = 1.0e-5; + double h = eps; std::vector g; + double xmx = x[0]; + double xmn = x[0]; + double ymx = x[1]; + double ymn = x[1]; + double zmx = x[2]; + double zmn = x[2]; + double df = 0.0, dff = 0.0, dbb = 0.0; + + for (std::size_t i = 0; i < x.size(); i+=3) { + if (x[i] >= xmx) xmx = x[i]; + if (x[i] <= xmn) xmn = x[i]; + } + + for (std::size_t i = 1; i < x.size(); i+=3) { + if (x[i] >= ymx) ymx = x[i]; + if (x[i] <= ymn) ymn = x[i]; + } + + for (std::size_t i = 2; i < x.size(); i+=3) { + if (x[i] >= zmx) zmx = x[i]; + if (x[i] <= zmn) zmn = x[i]; + } + + double delx = std::abs(xmx - xmn); + double dely = std::abs(ymx - ymn); + double delz = std::abs(zmx - zmn); + double delta = 1.0; for (std::size_t i = 0; i < x.size(); i++) { - if (std::abs(x[i]) > eps) - h = eps * std::abs(x[i]); - else - h = eps; + if (i % 3 == 0) delta = delx; + if (i % 3 == 1) delta = dely; + if (i % 3 == 2) delta = delz; + + h = eps * delta; + + //if (std::abs(x[i]) > eps) + // h = eps * std::abs(x[i]); + //else + // h = eps; x[i] = x[i] + h; - double fnew = getValue(x); + double ff = getValue(x); + x[i] = x[i] - h; + x[i] = x[i] - h; - g.push_back((fnew-fold)/h); + double fb = getValue(x); + x[i] = x[i] + h; + + dff = (ff - fold)/h; + dbb = (fold - fb)/h; + df = (dff + dbb)/(2.0); + + g.push_back(df); } return g; } @@ -337,11 +410,11 @@ bool CrvEdgeOptim :: run() for (std::size_t i = 0; i < adjT.getSize(); i++) { if (checkValidity(mesh, adjT[i], 1) > 1) { objF->restoreInitialNodes(); - std::cout<<"optimization success but invalid entity+++++"< convertNodeVectorToX(std::vector eftn); + std::vector convertNodeVectorToX(std::vector en, std::vector fn, std::vector tn); std::vector convertXtoNodeVector(const std::vector &x); void blendTris(const std::vector &edgeNodes, std::vector &faceNodes); //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); diff --git a/crv/crvShape.cc b/crv/crvShape.cc index dbf7a7493..ed5bbab5e 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -647,8 +647,8 @@ static void optimizeInvalidEdges(Adapt* a) EdgeOptimizer eo(a); ma::applyOperator(a,&eo); double t1 = PCU_Time(); - ma::print("Optimized %d bad edges " - "in %f seconds",eo.ns, t1-t0); + ma::print("Optimized %d bad edges, failed %d edges " + "in %f seconds",eo.ns, eo.nf, t1-t0); } int fixInvalidEdges(Adapt* a) From 535ac22ddecd745e93e84409dd69dc79d27371a9 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Thu, 20 Jun 2019 18:31:14 -0400 Subject: [PATCH 05/48] included statndalone face repositioning. --- crv/CMakeLists.txt | 3 + crv/LBFGS.h | 5 +- crv/crvEdgeOptim.cc | 15 +-- crv/crvEdgeOptim.h | 4 + crv/crvFaceOptim.cc | 294 ++++++++++++++++++++++++++++++++++++++++++++ crv/crvFaceOptim.h | 78 ++++++++++++ 6 files changed, 391 insertions(+), 8 deletions(-) create mode 100644 crv/crvFaceOptim.cc create mode 100644 crv/crvFaceOptim.h diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 59d70bae1..1a72d97b9 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -22,11 +22,14 @@ set(SOURCES crvVtk.cc LBFGS.cc crvEdgeOptim.cc + crvFaceOptim.cc ) # Package headers set(HEADERS crv.h + /lore/mohara/core/crv/crvEdgeOptim.h + /lore/mohara/core/crv/crvFaceOptim.h ) # Add the crv library diff --git a/crv/LBFGS.h b/crv/LBFGS.h index d088131e6..ee8d70253 100644 --- a/crv/LBFGS.h +++ b/crv/LBFGS.h @@ -24,7 +24,10 @@ class LBFGS { public: LBFGS(double inTol, int inIter, const std::vector &x, ObjFunction *inObjFunc): - tol(inTol), iter(inIter), x0(x), objFunc(inObjFunc) {} + tol(inTol), iter(inIter), x0(x), objFunc(inObjFunc) + { + //setInitialValue(x0); + } ~LBFGS() {} diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index a4ca6a91d..ba028dedf 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -246,11 +246,11 @@ double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 2; + weight = 4; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 1.5; + weight = 2; else - weight = 0.5; + weight = 1; if (I + J + K + L == d*(P-1)) { double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; //std::cout<<"["< &x) std::vector CrvEdgeReshapeObjFunc :: getGrad(std::vector &x) { - double fold = getValue(x); + //double fold = getValue(x); double eps = 1.0e-5; double h = eps; std::vector g; @@ -372,11 +372,12 @@ std::vector CrvEdgeReshapeObjFunc :: getGrad(std::vector &x) x[i] = x[i] - h; double fb = getValue(x); x[i] = x[i] + h; - +/* dff = (ff - fold)/h; dbb = (fold - fb)/h; df = (dff + dbb)/(2.0); - +*/ + df = (ff - fb)/(2.0 * h); g.push_back(df); } return g; @@ -410,7 +411,7 @@ bool CrvEdgeOptim :: run() for (std::size_t i = 0; i < adjT.getSize(); i++) { if (checkValidity(mesh, adjT[i], 1) > 1) { objF->restoreInitialNodes(); - std::cout<<"invalid entity with code "< &x); @@ -61,6 +63,8 @@ class CrvEdgeOptim public: CrvEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e) : mesh(m), edge(e) {} + ~CrvEdgeOptim(){} + public: void setMaxIter(int n); void setTol(double t); diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc new file mode 100644 index 000000000..5fa6f8dde --- /dev/null +++ b/crv/crvFaceOptim.cc @@ -0,0 +1,294 @@ +#include "crvFaceOptim.h" +#include "LBFGS.h" +#include "crv.h" +#include "crvQuality.h" +#include "crvBezier.h" +#include "crvMath.h" +#include +#include "apfMatrix.h" + +namespace crv{ + +int CrvFaceReshapeObjFunc :: getSpaceDim() +{ + return P*d; +} + +void CrvFaceReshapeObjFunc :: getInitFaceN() +{ + apf::Vector3 intFaceX; + int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(face, j, intFaceX); + ifn.push_back(intFaceX); + } +} + +void CrvFaceReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(face, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +std::vector CrvFaceReshapeObjFunc :: getInitialGuess() +{ + return convertNodeVectorToX(ifn); +} + +std::vector CrvFaceReshapeObjFunc :: convertNodeVectorToX(std::vector fn) +{ + std::vector x0; + + for (std::size_t i = 0; i < fn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(fn[i][j]); + + return x0; +} + +std::vector CrvFaceReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) +{ + std::vector a; + apf::Vector3 v; + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + + return a; +} + +void CrvFaceReshapeObjFunc :: updateNodes(std::vector fa, std::vector te) +{ + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(face)); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(face, j, fa[j]); + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(face, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } +} + +void CrvFaceReshapeObjFunc :: setNodes(std::vector &x) +{ + std::vector fn;// (ifn.begin(), ifn.end()); + std::vector tn;// (itn.begin(), itn.end()); + std::vector nod = convertXtoNodeVector(x); + //blendTris(en, fn); + //from all internal node vector to distict vector of nodes + + int nFN = mesh->getShape()->countNodesOn(mesh->getType(face)); + for (int i = 0; i 2 && P > 3) { + //int nTN = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = nFN; i CrvFaceReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(face, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(v); + } + } + return vol; +} + +double CrvFaceReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double fun = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< &x) +{ + setNodes(x); + + double sum = 0.0; + + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(face, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + return sum; +} + +std::vector CrvFaceReshapeObjFunc :: getGrad(std::vector &x) +{ + //double fold = getValue(x); + double eps = 1.0e-4; + double h = eps; + std::vector g; + double xmx = x[0]; + double xmn = x[0]; + double ymx = x[1]; + double ymn = x[1]; + double zmx = x[2]; + double zmn = x[2]; + double df = 0.0, dff = 0.0, dbb = 0.0; + + for (std::size_t i = 0; i < x.size(); i+=3) { + if (x[i] >= xmx) xmx = x[i]; + if (x[i] <= xmn) xmn = x[i]; + } + + for (std::size_t i = 1; i < x.size(); i+=3) { + if (x[i] >= ymx) ymx = x[i]; + if (x[i] <= ymn) ymn = x[i]; + } + + for (std::size_t i = 2; i < x.size(); i+=3) { + if (x[i] >= zmx) zmx = x[i]; + if (x[i] <= zmn) zmn = x[i]; + } + + double delx = std::abs(xmx - xmn); + double dely = std::abs(ymx - ymn); + double delz = std::abs(zmx - zmn); + double delta = 1.0; + + for (std::size_t i = 0; i < x.size(); i++) { + if (i % 3 == 0) delta = delx; + if (i % 3 == 1) delta = dely; + if (i % 3 == 2) delta = delz; + + if (delta < eps) + h = eps * std::abs(x[i]); + else + h = eps * delta; + + //if (std::abs(x[i]) > eps) + // h = eps * std::abs(x[i]); + //else + // h = eps; + + x[i] = x[i] + h; + double ff = getValue(x); + x[i] = x[i] - h; + + x[i] = x[i] - h; + double fb = getValue(x); + x[i] = x[i] + h; + + df = (ff - fb)/(2.0 * h); + g.push_back(df); + } + return g; +} + +void CrvFaceOptim :: setMaxIter(int n) +{ + iter = n; +} + +void CrvFaceOptim :: setTol(double t) +{ + tol = t; +} + +bool CrvFaceOptim :: run() +{ + CrvFaceReshapeObjFunc *objF = new CrvFaceReshapeObjFunc(mesh, face); + std::vector x0 = objF->getInitialGuess(); + //double f0 = objF->getValue(x0); + //std::cout<< "fval at x0 " << f0<run()) { + finalX = l->currentX; + fval = l->fValAfter; + objF->setNodes(finalX); +/* + apf::Adjacent adjT; + mesh->getAdjacent(face, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + if (checkValidity(mesh, adjT[i], 1) > 1) { + objF->restoreInitialNodes(); + std::cout<<"invalid entity after fop with code--- "< +#include +#include +#include "apf.h" +#include "apfMesh.h" +#include "apfMesh2.h" +#include "LBFGS.h" +#include "apfShape.h" + +namespace crv{ + +class CrvFaceReshapeObjFunc : public ObjFunction +{ + public: + CrvFaceReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* f) : + mesh(m), face(f) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitFaceN(); + getInitTetN(); + } + ~CrvFaceReshapeObjFunc() {} + + public: + int getSpaceDim(); + double getValue(std::vector &x); + std::vector getGrad(std::vector &x); + std::vector getInitialGuess(); + void setNodes(std::vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + + private: + void getInitFaceN(); + void getInitTetN(); + std::vector convertNodeVectorToX(std::vector fn); + std::vector convertXtoNodeVector(const std::vector &x); + //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); + void updateNodes(std::vector fa, std::vector te); + std::vector getVolume(); + double computeFValOfElement(apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* face; + std::vector vol; + std::vector ifn; + std::vector itn; +}; + +class CrvFaceOptim +{ + public: + CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f) : + mesh(m), face(f) {} + ~CrvFaceOptim(){} + + public: + void setMaxIter(int n); + void setTol(double t); + bool run(); + public: + apf::Mesh2* mesh; + apf::MeshEntity* face; + int iter; + double tol; + std::vector finalX; + double fval; +}; +} + +#endif From a09a287f819eda59f3757d967f8ac42a8933e7a5 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 27 Jul 2019 02:26:57 -0400 Subject: [PATCH 06/48] optim wo adapt --- crv/CMakeLists.txt | 2 + crv/crvAdapt.cc | 9 +- crv/crvCurveMesh.cc | 33 +- crv/crvEdgeOptim.cc | 127 ++++++- crv/crvFaceOptim.cc | 53 ++- crv/crvModelEdgeOptim.cc | 759 +++++++++++++++++++++++++++++++++++++++ crv/crvModelEdgeOptim.h | 86 +++++ crv/crvShape.cc | 393 +++++++++++++++++++- crv/crvShape.h | 4 + crv/crvVtk.cc | 52 ++- 10 files changed, 1485 insertions(+), 33 deletions(-) create mode 100644 crv/crvModelEdgeOptim.cc create mode 100644 crv/crvModelEdgeOptim.h diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 1a72d97b9..79995f23f 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES crvVtk.cc LBFGS.cc crvEdgeOptim.cc + crvModelEdgeOptim.cc crvFaceOptim.cc ) @@ -29,6 +30,7 @@ set(SOURCES set(HEADERS crv.h /lore/mohara/core/crv/crvEdgeOptim.h + /lore/mohara/core/crv/crvModelEdgeOptim.h /lore/mohara/core/crv/crvFaceOptim.h ) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index c8c1bef19..1e923206d 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -164,8 +164,9 @@ ma::Input* configureShapeCorrection( static int fixInvalidElements(crv::Adapt* a) { a->input->shouldForceAdaptation = false; - int count = crv::fixLargeBoundaryAngles(a) - + crv::fixInvalidEdges(a); + int count = crv::fixLargeBoundaryAngles(a) + + crv::fixInvalidFaces(a) + + crv::fixInvalidEdges(a); int originalCount = count; int prev_count; int i = 0; @@ -173,13 +174,15 @@ static int fixInvalidElements(crv::Adapt* a) if ( ! count) break; prev_count = count; - count = crv::fixLargeBoundaryAngles(a) + count = crv::fixLargeBoundaryAngles(a) + + crv::fixInvalidFaces(a) + crv::fixInvalidEdges(a); ++i; } while(count < prev_count); crv::fixLargeBoundaryAngles(a); ma::clearFlagFromDimension(a,ma::COLLAPSE | ma::BAD_QUALITY,1); + //ma::clearFlagFromDimension(a, ma::SNAP | ma::BAD_QUALITY, 2); a->input->shouldForceAdaptation = false; return originalCount - count; } diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 3e656ecb0..739ca09bf 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -12,6 +12,7 @@ #include #include "crvMath.h" #include +#include "crvFaceOptim.h" namespace crv { @@ -171,6 +172,15 @@ void BezierCurver::convertInterpolatingToBezier() synchronize(); } +static bool faceOp(apf::Mesh2* m, apf::MeshEntity* me) +{ + CrvFaceOptim *opF = new CrvFaceOptim(m, me); + opF->setMaxIter(100); + opF->setTol(1e-8); + if (opF->run()) return true; + else return false; +} + bool BezierCurver::run(bool flag) { std::string name = m_mesh->getShape()->getName(); @@ -193,11 +203,32 @@ bool BezierCurver::run(bool flag) } convertInterpolatingToBezier(); + + //crv::writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 10, "after-inflate"); + //crv::writeCurvedWireFrame(m_mesh, 40, "after-inflate"); + if (flag == 1) { + /* + apf::MeshEntity* f; + apf::MeshIterator* it = m_mesh->begin(2); + apf::Adjacent adjR; + while ((f = m_mesh->iterate(it))){ + int count = 0; + if(m_mesh->getModelType(m_mesh->toModel(f)) == 3) { + m_mesh->getAdjacent(f, 3, adjR); + for (std::size_t i = 0; i < adjR.getSize(); i++) { + if (crv::checkValidity(m_mesh, adjR[i], 2) > 1) + count ++; + } + if (count > 0) + faceOp(m_mesh, f); + } + } + m_mesh->end(it); + */ if(m_mesh->getDimension() >= 2) { if (m_order == 2 || m_order == 3) { ma::Input* shapeFixer = configureShapeCorrection(m_mesh); - shapeFixer->maximumIterations = 0; crv::adapt(shapeFixer); } } diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index ba028dedf..1c4f94d00 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -179,7 +179,7 @@ void CrvEdgeReshapeObjFunc :: setNodes(std::vector &x) apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = nEN; i < nEN + nFN*adjF.size(); i++) + for (std::size_t i = nEN; i < nEN + nFN*adjF.getSize(); i++) fn.push_back(nod[i]); if (d > 2 && P > 3) { @@ -191,6 +191,14 @@ void CrvEdgeReshapeObjFunc :: setNodes(std::vector &x) updateNodes(en, fn, tn); } +static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) +{ + p1 = p1 - p0; + p2 = p2 - p0; + double area = (apf::cross(p1, p2)).getLength(); + return (area/2.0); +} + std::vector CrvEdgeReshapeObjFunc :: getVolume() { if (d == 3) { @@ -246,9 +254,9 @@ double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; + weight = 14; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 2; + weight = 4; else weight = 1; if (I + J + K + L == d*(P-1)) { @@ -301,7 +309,8 @@ double CrvEdgeReshapeObjFunc :: getValue(std::vector &x) sum = sum + computeFValOfElement(allNodes, vol[i]); apf::destroyElement(el); } - restoreInitialNodes(); + +restoreInitialNodes(); } if (d == 3) { @@ -314,6 +323,110 @@ double CrvEdgeReshapeObjFunc :: getValue(std::vector &x) sum = sum + computeFValOfElement(allNodes, vol[i]); apf::destroyElement(el); } +/* + apf::NewArray eCP; + apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); + apf::getVectorNodes(Edl, eCP); + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + + double xr = 1.0; + double xir = 1.0; + //double alpha = 1.0; + double beta = 0.0; + double ad = 0.0; + apf::Vector3 x1, x0; + apf::Vector3 xi2, xi1, xi0; + + for (int i = 0; i < nEN; i++) { + getBezierNodeXi(mesh->getType(edge), P, i, xi1); + if (i > 0 && i < nEN - 1) { + getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); + getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); + x1 = eCP[2+i+1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[2+i-1]; + xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); + } + else if ( i == 0) { + getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); + x1 = eCP[2+i+1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[0]; + xir = (xi2[0] - xi1[0])/(xi1[0] + 1); // parent coordinate[-1,1] + } + else { + getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); + x1 = eCP[1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[2+i-1]; + xir = (1 - xi1[0])/(xi1[0] - xi0[0]); + } + + // if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) + // alpha = 0.5*(xi1[0]+1.0); + // else + // alpha = 1.0 - 0.5*(xi1[0]+1.0); + + xr = (x1.getLength()/x0.getLength()); + ad = (xr/xir - 1);//(alpha*alpha); + beta = beta + ad*ad; + + //sum = sum + ad*ad; + } + + apf::destroyElement(Edl); + */ +/* + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + apf::NewArray fCP; + apf::Vector3 xif; + double a[3] = {1.0, 1.0, 1.0}; + double b[3] = {1.0, 1.0, 1.0}; + double aratio = 0.0; + //double wfactor = 1.0; + double gamma = 0.0; + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(Fal, fCP); + int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; + + double triAphys = getAr(fCP[0], fCP[1], fCP[2]); + apf::Vector3 prt0 = {1, 0, 0}; + apf::Vector3 prt1 = {0, 1, 0}; + apf::Vector3 prt2 = {0, 0, 1}; + double triAparnt = getAr(prt0, prt1, prt2); + + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); + apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; + a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); + b[0] = getAr(xifm, prt0, prt1); + a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); + b[1] = getAr(xifm, prt1, prt2); + a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); + b[2] = getAr(xifm, prt2, prt1); + + //for (int jj = 0; jj < 3; jj++) { + // if (xifm[i] < wfactor) + // wfactor = xifm[i]; + //} + + for (int k = 0; k < 3; k++) { + aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); //(wfactor*wfactor); + gamma = gamma + aratio*aratio; + + //sum = sum + aratio *aratio; + } + } + //sum = sum*(1 + gamma); + //std::cout<<"sum and ratio------ "<< sum <<" "<currentX; fval = l->fValAfter; objF->setNodes(finalX); - + /* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -415,11 +528,11 @@ bool CrvEdgeOptim :: run() return false; } } - +*/ return true; } else { - std::cout<<"*****Optim FAILURE"< CrvFaceReshapeObjFunc :: getVolume() return vol; } +static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) +{ + p1 = p1 - p0; + p2 = p2 - p0; + double area = (apf::cross(p1, p2)).getLength(); + return (area/2.0); +} + double CrvFaceReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) { int weight = 1; @@ -182,6 +190,47 @@ double CrvFaceReshapeObjFunc :: getValue(std::vector &x) sum = sum + computeFValOfElement(allNodes, vol[i]); apf::destroyElement(el); } +/* + apf::NewArray fCP; + apf::Vector3 xif; + double a[3] = {1.0, 1.0, 1.0}; + double b[3] = {1.0, 1.0, 1.0}; + double aratio = 0.0; + //double wfactor = 1.0; + double gamma = 0.0; + + apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), face); + apf::getVectorNodes(Fal, fCP); + int nFN = mesh->getShape()->countNodesOn(mesh->getType(face)); + + int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; + + double triAphys = getAr(fCP[0], fCP[1], fCP[2]); + apf::Vector3 prt0 = {1, 0, 0}; + apf::Vector3 prt1 = {0, 1, 0}; + apf::Vector3 prt2 = {0, 0, 1}; + double triAparnt = getAr(prt0, prt1, prt2); + + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(face), P, j, xif); + apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; + a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); + b[0] = getAr(xifm, prt0, prt1); + a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); + b[1] = getAr(xifm, prt1, prt2); + a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); + b[2] = getAr(xifm, prt2, prt1); + + for (int k = 0; k < 3; k++) { + aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); + gamma = gamma + aratio*aratio; + } + } + + apf::destroyElement(Fal); + + sum = sum*(1 + gamma); + */ restoreInitialNodes(); } return sum; @@ -272,7 +321,7 @@ bool CrvFaceOptim :: run() finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); -/* + /* apf::Adjacent adjT; mesh->getAdjacent(face, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -286,7 +335,7 @@ bool CrvFaceOptim :: run() return true; } else { - std::cout<<"*****Optim FAILURE"< +#include "apfMatrix.h" +#include + +namespace crv{ + +int CrvModelEdgeReshapeObjFunc :: getSpaceDim() +{ + return P*d; +} + +void CrvModelEdgeReshapeObjFunc :: getInitEdgeN() +{ + apf::Vector3 intEdgeX; + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + + for (int i = 0; i < numENodes; i++) { + mesh->getPoint(edge, i, intEdgeX); + ien.push_back(intEdgeX); + } +} + +apf::Vector3 getInterpolatingPointOnFace(apf::Mesh* mesh, apf::MeshEntity* face, int odr, int whichNode) +{ + std::vector faceIp; + apf::Vector3 xi; + apf::NewArray allCntrlP; + apf::Element* Fa = apf::createElement(mesh->getCoordinateField(), face); + apf::getVectorNodes(Fa, allCntrlP); + + int nFn = mesh->getShape()->countNodesOn(mesh->getType(face)); + apf::Vector3 blTri; + //apf::NewArray rhs(n); + int j = 0; + + getBezierNodeXi(apf::Mesh::TRIANGLE, odr, whichNode, xi); + blTri.zero(); + + for (int ii = 0; ii < odr+1; ii++) { + for (int jj = 0; jj < odr+1-ii; jj++) { + double bFactor = trinomial(odr, ii, jj) * Bijk(ii, jj, odr-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); + blTri = blTri + allCntrlP[getTriNodeIndex(odr, ii, jj)] * bFactor; + } + } + + apf::destroyElement(Fa); + return blTri; +} + +void CrvModelEdgeReshapeObjFunc :: getInitFaceN() +{ + apf::Adjacent adjF; + apf::Vector3 intFaceX; + apf::Vector3 ipFN; + mesh->getAdjacent(edge, 2, adjF); + int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFaceX); + ifn.push_back(intFaceX); + //ipFN = getInterpolatingPointOnFace(mesh, adjF[i], P, j); + //itpfn.push_back(ipFN); + } + } +} + +void CrvModelEdgeReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(edge, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +std::vector CrvModelEdgeReshapeObjFunc :: getParamCoords() +{ + apf::Vector3 xi; + apf::Vector3 param; + std::vector xp; + + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + + for (int i = 0; i < numENodes; i++) { + getBezierNodeXi(mesh->getType(edge), P, i, xi); + transferParametricOnEdgeSplit(mesh, edge, 0.5*(xi[0]+1.0), param); + for (int j = 0; j < 3; j++) + xp.push_back(param[j]); + } + + apf::Vector3 xif; + apf::Vector3 paramf; + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + for (int j = 0; j < numFNodes; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); + transferParametricOnTriSplit(mesh, adjF[i], xif, paramf); + for (int k = 0; k < 3; k++) + xp.push_back(paramf[k]); + } + } + else { + apf::Vector3 intFN; + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFN); + for (int k = 0; k < 3; k++) + xp.push_back(intFN[k]); + } + } + } + + return xp; +} + +std::vector CrvModelEdgeReshapeObjFunc :: convertParamCoordsToNodeVector(const std::vector &x) +{ + apf::ModelEntity* me = mesh->toModel(edge); + std::vector edn; + std::vector vn = convertXtoNodeVector(x); + int nENodes = mesh->getShape()->countNodesOn(mesh->EDGE); + + for (int i = 0; i < nENodes; i++) { + apf::Vector3 coorde; + mesh->snapToModel(me, vn[i], coorde); + edn.push_back(coorde); + } + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + int numFNTotal = 0; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int nFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + apf::ModelEntity* mef = mesh->toModel(adjF[i]); + for (int j = 0; j < nFNodes; j++) { + apf::Vector3 coordf; + mesh->snapToModel(mef, vn[nENodes+numFNTotal], coordf); + edn.push_back(coordf); + numFNTotal++; + } + } + else { + for (int j = 0; j < nFNodes; j++) { + edn.push_back(vn[nENodes+numFNTotal]); + numFNTotal++; + } + } + + } + + return edn; +} + +std::vector CrvModelEdgeReshapeObjFunc :: getInitialGuess() +{ + return getParamCoords(); +} + +std::vector CrvModelEdgeReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) +{ + std::vector a; + apf::Vector3 v; + + if (d == 3) { + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + } + return a; +} + +void CrvModelEdgeReshapeObjFunc :: blendTris(const std::vector &egn, std::vector &faceNodes) +{ + apf::Vector3 xi; + apf::Adjacent adjF; + apf::Adjacent adjE; + + mesh->getAdjacent(edge, 2, adjF); + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + mesh->getAdjacent(adjF[i], 1, adjE); + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + for (std::size_t j = 0; j < adjE.getSize(); j++) { + if (adjE[j] == edge) { + int jj = 1; + + if ( j == 0) + jj = 2; + else if ( j == 1) + jj = 0; + else + jj = 1; + + for (int k = 0; k < numFNodes; k++) { + getBezierNodeXi(mesh->TRIANGLE, P, k, xi); + for (std::size_t ii = 0; ii < egn.size(); ii++) { + double factor = 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) + + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); + faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - ien[ii])*factor; + } + } + } + } + } + } +} + +std::vector CrvModelEdgeReshapeObjFunc :: getFaceControlPointsFromInterpolatingPoints(apf::MeshEntity* face, const std::vector &faceInterpolatingP) +{ + std::vector faceControlP; + apf::Vector3 xi; + apf::NewArray allCntrlP; + apf::Element* Fa = apf::createElement(mesh->getCoordinateField(), face); + apf::getVectorNodes(Fa, allCntrlP); + + int n = mesh->getShape()->countNodesOn(mesh->getType(face)); + mth::Matrix A(n, n); + mth::Matrix Ainv(n, n); + apf::NewArray rhs(n); + int j = 0; + + for (int i = 0; i < n; i++) { + getBezierNodeXi(apf::Mesh::TRIANGLE, P, i, xi); + rhs[i].zero(); + for (int ii = 0; ii < P+1; ii++) { + for (int jj = 0; jj < P+1-ii; jj++) { + if (ii == 0 || jj == 0 || (ii+jj == P)) { + double bFactor = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); + rhs[i] += allCntrlP[getTriNodeIndex(P, ii, jj)] * bFactor; + } + else { + j = getTriNodeIndex(P, ii, jj) - 3*P; //3P is the total number of nodes on all edges + A(i, j) = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); + } + } + } + rhs[i] = faceInterpolatingP[i] - rhs[i]; + } + apf::destroyElement(Fa); + + if (n > 1) + invertMatrixWithPLU(n, A, Ainv); + else + Ainv(0,0) = 1./A(0,0); + + for (int i = 0; i < n; i++) { + apf::Vector3 fcp(0., 0., 0.); + for (int j = 0; j < n; j++) + fcp += rhs[j]*Ainv(i, j); + faceControlP.push_back(fcp); + } + + return faceControlP; +} + +void CrvModelEdgeReshapeObjFunc :: updateNodes(std::vector ed, std::vector fa, std::vector te, bool isInitialX) +{ + if (!isInitialX) { + apf::NewArray eIntpCords; + apf::Element* Ed = apf::createElement(mesh->getCoordinateField(), edge); + apf::getVectorNodes(Ed, eIntpCords); + apf::NewArray trsCoff; + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + apf::NewArray contP(nEN); + + for (int i = 0; i < nEN; i++) { + for (int j = 0; j < 3; j++) + eIntpCords[2+i][j] = ed[i][j]; + } + + getBezierTransformationCoefficients(P, mesh->getType(edge), trsCoff); + crv::convertInterpolationPoints(nEN+2, nEN, eIntpCords, trsCoff, contP); + + for (int i = 0; i < nEN; i++) + mesh->setPoint(edge, i, contP[i]); + + apf::destroyElement(Ed); + } + else { + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < nEN; i++) + mesh->setPoint(edge, i, ed[i]); + } + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + std::vector fNd; + + if (!isInitialX) { + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + fNd.clear(); + + for (int j = 0; j < numFNodes; j++) + fNd.push_back(fa[numFNodes*i + j]); + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + std::vector fCN = getFaceControlPointsFromInterpolatingPoints(adjF[i], fNd); + + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fCN[j]); + } + else { + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); + } + } + } + else { + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i+j]); + } + } + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } + + apf::synchronize(mesh->getCoordinateField()); +} + +void CrvModelEdgeReshapeObjFunc :: setNodes(std::vector &x) +{ + std::vector en; + std::vector fn; + std::vector tn; + std::vector nod = convertParamCoordsToNodeVector(x); + //std::vector fnewN; + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < nEN; i++) + en.push_back(nod[i]); + + //for (size_t i = 0; i < itpfn.size(); i++) + // fnewN.push_back(itpfn[i]); + + //blendTris(en, fnewN); + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + int kk = 0; + int nFN = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < nFN; j++) + fn.push_back(nod[nEN+i*nFN+j]); + } + + if (d > 2 && P > 3) { + //int nTN = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = nEN+nFN; i CrvModelEdgeReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(std::abs(v)); + } + } + if (d == 2) { + apf::Adjacent adjF; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 2, adjF); + apf::Vector3 point; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjF[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) { + if (k < 2) m[j][k] = point[k]; + else m[j][2] = 1.0; + } + } + double v = getDeterminant(m); + vol.push_back(v); + } + } + return vol; +} + +static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) +{ + p1 = p1 - p0; + p2 = p2 - p0; + double area = (apf::cross(p1, p2)).getLength(); + return (area/2.0); +} + +static double getArea(apf::Mesh* mesh, apf::MeshEntity* e) +{ + apf::MeshEntity* ver[3]; + mesh->getDownward(e, 0, ver); + apf::Vector3 point0, point1, point2; + + mesh->getPoint(ver[0], 0, point0); + mesh->getPoint(ver[1], 0, point1); + mesh->getPoint(ver[2], 0, point2); + + point1 = point1 - point0; + point2 = point2 - point0; + + double area = (apf::cross(point1, point2)).getLength(); + + return (area/2.0); +} + + +double CrvModelEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) + weight = 14; + else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) + weight = 4; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< &x) +{ + setNodes(x); + + double sum = 0.0; + if (d == 2) { + apf::Adjacent adjF; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + + restoreInitialNodes(); + } + + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + + apf::NewArray eCP; + apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); + apf::getVectorNodes(Edl, eCP); + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + double xr = 1.0; + double xir = 1.0; + //double alpha = 1.0; + double ad = 0.0; + apf::Vector3 x1, x0; + apf::Vector3 xi2, xi1, xi0; + double beta = 0.0; + + apf::MeshElement* mEdl = apf::createMeshElement(mesh, edge); + for (int i = 0; i getType(edge), P, i, xi1); + apf::mapLocalToGlobal(mEdl, xi1, scord); + eCP[2+i] = scord; + } + apf::destroyMeshElement(mEdl); + + for (int i = 0; i < nEN; i++) { + getBezierNodeXi(mesh->getType(edge), P, i, xi1); + if (i > 0 && i < nEN - 1) { + getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); + getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); + x1 = eCP[2+i+1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[2+i-1]; + xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); + } + else if ( i == 0) { + getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); + x1 = eCP[2+i+1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[0]; + xir = (xi2[0] - xi1[0])/(xi1[0] + 1); // parent coordinate[-1,1] + } + else { + getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); + x1 = eCP[1] - eCP[2+i]; + x0 = eCP[2+i] - eCP[2+i-1]; + xir = (1 - xi1[0])/(xi1[0] - xi0[0]); + } + + //if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) + // alpha = 0.5*(xi1[0]+1.0); + //else + // alpha = 1.0 - 0.5*(xi1[0]+1.0); + + xr = (x1.getLength()/x0.getLength()); + ad = (xr/xir - 1); //(alpha*alpha); + beta = beta + ad*ad; + //sum = sum + ad*ad; + } + //sum = sum*(1 + beta); + apf::destroyElement(Edl); +/* + //if (mesh->getModelType(mesh->toModel(edge)) == 2) { + // if (mesh->getModelTag(mesh->toModel(edge)) == 26) { +// double arandomnumber = 2; + // } + // } + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + apf::NewArray fCP; + apf::Vector3 xif; + double a[3] = {1.0, 1.0, 1.0}; + double b[3] = {1.0, 1.0, 1.0}; + double aratio = 0.0; + //double wfactor = 1.0; + double gamma = 0.0; + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(Fal, fCP); + int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; + + apf::MeshElement* mfel = apf::createMeshElement(mesh, adjF[i]); + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); + apf::Vector3 sfcord; + apf::mapLocalToGlobal(mfel, xif, sfcord); + fCP[3*P + j] = sfcord; + } + apf::destroyMeshElement(mfel); + + double triAphys = getAr(fCP[0], fCP[1], fCP[2]); + apf::Vector3 prt0 = {0, 0, 0}; + apf::Vector3 prt1 = {0, 1, 0}; + apf::Vector3 prt2 = {0, 0, 1}; + double triAparnt = getAr(prt0, prt1, prt2); + + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); + apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; + a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); + b[0] = getAr(xifm, prt0, prt1); + a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); + b[1] = getAr(xifm, prt1, prt2); + a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); + b[2] = getAr(xifm, prt2, prt1); + + for (int k = 0; k < 3; k++) { + aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); + gamma = gamma + aratio*aratio; + } + } + apf::destroyElement(Fal); + } + } +*/ + sum = sum*(1 + beta );//+ 0.3*gamma); + + restoreInitialNodes(); + } + return sum; +} + +std::vector CrvModelEdgeReshapeObjFunc :: getGrad(std::vector &x) +{ + //double fold = getValue(x); + double eps = 1.0e-5; + double h = eps; + std::vector g; + /* + std::vector par; + + apf::MeshEntity* v[2]; + mesh->getDownward(edge, 0, v); + + for (int i = 0; i<2; i++) + mesh->getParam(v[i], par[i]); + + double delx = std::abs(par[0][0] - par[1][0]); + double dely = std::abs(par[0][1] - par[1][1]); + double delz = std::abs(par[0][2] - par[1][2]); + double delta = 1.0; +*/ + for (std::size_t i = 0; i < x.size(); i++) { + /* + if (i % 3 == 0) delta = delx; + //if (i % 3 == 1) delta = dely; + //if (i % 3 == 2) delta = delz; + + if (delta < eps) + h = eps; + else + h = eps * delta; +*/ + if (std::abs(x[i]) > eps) + h = eps * std::abs(x[i]); + else + h = eps; + + x[i] = x[i] + h; + double ff = getValue(x); + x[i] = x[i] - h; + + x[i] = x[i] - h; + double fb = getValue(x); + x[i] = x[i] + h; +/* + dff = (ff - fold)/h; + dbb = (fold - fb)/h; + df = (dff + dbb)/(2.0); +*/ + double df = (ff - fb)/(2.0 * h); + g.push_back(df); + } + return g; +} + +void CrvModelEdgeOptim :: setMaxIter(int n) +{ + iter = n; +} + +void CrvModelEdgeOptim :: setTol(double t) +{ + tol = t; +} + +bool CrvModelEdgeOptim :: run() +{ + CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge); + std::vector x0 = objF->getInitialGuess(); + //double f0 = objF->getValue(x0); + //std::cout<< "fval at x0 " << f0<run()) { + finalX = l->currentX; + fval = l->fValAfter; + objF->setNodes(finalX); + + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + if (checkValidity(mesh, adjT[i], 2) > 1) { + objF->restoreInitialNodes(); +// std::cout<<"invalid entity after edop with code "< +#include +#include +#include "apf.h" +#include "apfMesh.h" +#include "apfMesh2.h" +#include "LBFGS.h" +#include "apfShape.h" + +namespace crv{ + +class CrvModelEdgeReshapeObjFunc : public ObjFunction +{ + public: + CrvModelEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e) : + mesh(m), edge(e) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitEdgeN(); + getInitFaceN(); + getInitTetN(); + } + ~CrvModelEdgeReshapeObjFunc(){} + + public: + int getSpaceDim(); + double getValue(std::vector &x); + std::vector getGrad(std::vector &x); + std::vector getInitialGuess(); + void setNodes(std::vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + + private: + void getInitEdgeN(); + void getInitFaceN(); + void getInitTetN(); + std::vector getParamCoords(); + std::vector convertParamCoordsToNodeVector(const std::vector &x); + std::vector convertXtoNodeVector(const std::vector &x); + void blendTris(const std::vector &edgeNodes, std::vector &faceNodes); + //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); + std::vector getFaceControlPointsFromInterpolatingPoints(apf::MeshEntity* face, const std::vector &faceInterpolatingP); + void updateNodes(std::vector ed, std::vector fa, std::vector te, bool isInitialX); + std::vector getVolume(); + double computeFValOfElement(apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + std::vector vol; + std::vector ien; + std::vector ifn; + std::vector itpfn; + std::vector itn; + +}; + +class CrvModelEdgeOptim +{ + public: + CrvModelEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e) : + mesh(m), edge(e) {} + ~CrvModelEdgeOptim(){} + + public: + void setMaxIter(int n); + void setTol(double t); + bool run(); + public: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + int iter; + double tol; + std::vector finalX; + double fval; +}; +} + +#endif diff --git a/crv/crvShape.cc b/crv/crvShape.cc index ed5bbab5e..22340d12c 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -20,6 +20,8 @@ #include #include #include "crvEdgeOptim.h" +#include "crvModelEdgeOptim.h" +#include "crvFaceOptim.h" /* This is similar to maShape.cc, conceptually, but different enough * that some duplicate code makes sense */ @@ -53,6 +55,108 @@ static bool hasTwoEntitiesOnBoundary(apf::Mesh* m, apf::MeshEntity* e, int dimen /* Mark Edges based on the invalidity code the element has been * tagged with. */ + +static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) +{ + apf::MeshEntity* edges[6]; + int ne = mesh->getDownward(e, 1, edges); + + apf::MeshEntity* f[4]; + int nf = mesh->getDownward(e, 2, f); + apf::MeshEntity* vf[3]; + apf::MeshEntity* vt[4]; + mesh->getDownward(e, 0, vt); + + std::vector a; + std::vector b; + + for (int i = 0; i < nf; i++) { + mesh->getDownward(f[i], 0, vf); + int j = apf::findIn(vf, 3, vt[index]); + + if (j != -1) { + a.push_back(i); + b.push_back(j); + } + } + + double c[3]; + int cc[3]; + apf::Vector3 xi; + apf::Matrix3x3 Jac; + for(size_t k = 0; k < a.size(); k++) { + if (b[k] == 0) xi = {0, 0, 0}; + else if (b[k] == 1) xi = {1, 0, 0}; + else xi = {0, 1, 0}; + + cc[k] = k; + + apf::MeshElement* me = apf::createMeshElement(mesh, f[a[k]]); + apf::getJacobian(me, xi, Jac); + c[k] = apf::getJacobianDeterminant(Jac, 2); + + apf::destroyMeshElement(me); + } + + // sort min to max jacobian determinant + for (int i = 0; i < 3; i++) { + for (int j = i-1; j >= 0; --j) { + double k = c[j+1]; + int kk = cc[j+1]; + if ( k < c[j]) { + c[j+1] = c[j]; + c[j] = k; + cc[j+1] = cc[j]; + cc[j] = kk; + } + } + } + + apf::MeshEntity* ef[3]; + apf::MeshEntity* ve[2]; + std::vector aa; + std::vector bb; + + for (int i = 0; i < 2; i++) { + int nef = mesh->getDownward(f[a[cc[i]]], 1, ef); + for (int j = 0; j < nef; j++) { + mesh->getDownward(ef[j], 0, ve); + if (apf::findIn(ve, 2, vt[index]) != -1) { + int k = apf::findIn(edges, 6, ef[j]); + if (k != -1) { + if (aa.size() > 2) { + for (int ii = 0; ii < 2; ii++) { + if ( k != aa[ii] ) { + aa.push_back(k); + bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); + } + } + } + else { + aa.push_back(k); + bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); + } + } + } + } + } + + if (bb[0] < bb[1] ) { + int k = aa[0]; + int kk = bb[0]; + aa[0] = aa[1]; + aa[1] = k; + bb[0] = bb[1]; + bb[1] = kk; + } + + // aa has the index of the edges ordered + // min to max of adj face jacobian + + return aa; + +} + static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* edges[6]) { @@ -70,17 +174,23 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, ma::Downward ed; m->getDownward(e,1,ed); n = md; + + std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); if(md == 2){ edges[0] = ed[index]; edges[1] = ed[(index+2) % 3]; } else { PCU_ALWAYS_ASSERT(index < 4); - edges[0] = ed[vertEdges[index][0]]; - edges[1] = ed[vertEdges[index][1]]; - edges[2] = ed[vertEdges[index][2]]; + edges[0] = ed[aa[0]]; + edges[1] = ed[aa[1]]; + edges[2] = ed[aa[2]]; + //edges[0] = ed[vertEdges[index][0]]; + //edges[1] = ed[vertEdges[index][1]]; + //edges[2] = ed[vertEdges[index][2]]; } + break; } - break; + //break; case 1: { // if we have a single invalid edge, operate on it @@ -88,8 +198,9 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, m->getDownward(e,1,ed); edges[0] = ed[index]; n = 1; + break; } - break; + //break; case 2: { // if we have an invalid face, operate on its edges @@ -100,12 +211,15 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, edges[0] = ed[0]; edges[1] = ed[1]; edges[2] = ed[2]; + break; } - break; + //break; case 3: + { m->getDownward(e,1,edges); n = 6; break; + } default: fail("invalid quality tag in markEdges\n"); break; @@ -114,6 +228,124 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, return n; } +static std::vector faceIndexAdjInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) +{ + apf::MeshEntity* f[4]; + int nf = mesh->getDownward(e, 2, f); + apf::MeshEntity* vf[3]; + apf::MeshEntity* vt[4]; + mesh->getDownward(e, 0, vt); + + std::vector a; + + for (int i = 0; i < nf; i++) { + if (mesh->getModelType(mesh->toModel(f[i])) == 3) { + mesh->getDownward(f[i], 0, vf); + int j = apf::findIn(vf, 3, vt[index]); + + if (j != -1) + a.push_back(i); + } + } + return a; +} + +static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, int index) +{ + apf::MeshEntity* f[4]; + int nf = mesh->getDownward(e, 2, f); + apf::MeshEntity* ef[3]; + apf::MeshEntity* et[6]; + mesh->getDownward(e, 1, et); + + std::vector a; + + for (int i = 0; i < nf; i++) { + if (mesh->getModelType(mesh->toModel(f[i])) == 3) { + mesh->getDownward(f[i], 1, ef); + int j = apf::findIn(ef, 3, et[index]); + + if (j != -1) + a.push_back(i); + } + } + return a; +} + +static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, + ma::Entity* faces[4]) +{ + if ( tag <= 1 ) // if its valid, or not checked, don't worry about it + return 0; + int dim = (tag-2)/6; + int index = (tag-2) % 6; + int n = 0; + int md = m->getDimension(); + + switch (dim) { + case 0: + { + // if we have an invalid vertex, operate on adj faces + ma::Downward fc; + m->getDownward(e, 2, fc); + + std::vector a = faceIndexAdjInvalidVertex(m, e, index); + n = a.size(); + + if(md == 3){ + PCU_ALWAYS_ASSERT(index < 4); + for (int i = 0; i < n; i++) + faces[i] = fc[a[i]]; + } + break; + } + //break; + case 1: + { + ma::Downward fc; + m->getDownward(e,2,fc); + + std::vector a = faceIndexAdjInvalidEdge(m, e, index); + n = a.size(); + for (int i = 0; i < n; i++) + faces[i] = fc[a[i]]; + + break; + } + //break; + case 2: + { + // if we have an invalid face, operate on it + ma::Downward fc; + m->getDownward(e,2,fc); + if (m->getModelType(m->toModel(fc[index])) == 3) { + faces[0] = fc[index]; + n++; + } + break; + } + //break; + case 3: + { + ma::Downward fc; + m->getDownward(e,2,fc); + for (int i = 0; i < 4; i++) { + if (m->getModelType(m->toModel(fc[i])) == 3) { + faces[i] = fc[i]; + n++; + } + } + break; + } + //break; + default: + fail("invalid quality tag in markFaces\n"); + break; + } + + return n; +} + class EdgeSwapper : public ma::Operator { public: @@ -316,6 +548,65 @@ class EdgeReshaper : public ma::Operator int nr; }; +class FaceOptimizer : public ma::Operator +{ +public: + FaceOptimizer(Adapt* a) { + adapter = a; + mesh = a->mesh; + face = 0; + ns = 0; + nf = 0; + } + ~FaceOptimizer() { + } + virtual int getTargetDimension() {return 2;} + virtual bool shouldApply(ma::Entity* e) { + + if (!ma::getFlag(adapter, e, ma::SNAP | ma::BAD_QUALITY)) { + return false; + } + + if (isBoundaryEntity(mesh, e)) { + return false; + } + + if (mesh->getModelType(mesh->toModel(e)) == 2) { + return false; + } + else { + face = e; + return true; + } + } + + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(&face, 1); + } + + virtual void apply(){ + if (mesh->getModelType(mesh->toModel(face)) == 3) { + CrvFaceOptim *cfo = new CrvFaceOptim(mesh, face); + cfo->setMaxIter(100); + cfo->setTol(1e-8); + + if (cfo->run()) ns++; + else nf++; + + ma::clearFlag(adapter, face, ma::SNAP | ma::BAD_QUALITY); + } + } +private: +protected: + Adapt* adapter; + ma::Mesh* mesh; + ma::Entity* face; +public: + int ns; + int nf; +}; + class EdgeOptimizer : public ma::Operator { public: @@ -335,9 +626,12 @@ class EdgeOptimizer : public ma::Operator return false; } - if (isBoundaryEntity(mesh, e)) { + //if (isBoundaryEntity(mesh, e)) { + // return false; + //} + if (mesh->getModelType(mesh->toModel(e)) == 1) { return false; - } + } else { edge = e; return true; @@ -346,19 +640,30 @@ class EdgeOptimizer : public ma::Operator virtual bool requestLocality(apf::CavityOp* o) { - return o->requestLocality(&edge,1); + return o->requestLocality(&edge, 1); } virtual void apply(){ - CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edge); - ceo->setMaxIter(100); - ceo->setTol(1e-8); + if (mesh->getModelType(mesh->toModel(edge)) == 3) { + CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edge); + ceo->setMaxIter(100); + ceo->setTol(1e-8); - if (ceo->run()) ns++; - else nf++; + if (ceo->run()) ns++; + else nf++; + + ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + } + else if (mesh->getModelType(mesh->toModel(edge)) == 2) { + CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edge); + cmeo->setMaxIter(100); + cmeo->setTol(1e-8); - ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + if (cmeo->run()) ns++; + else nf++; + ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + } } private: protected: @@ -575,7 +880,8 @@ static int markEdgesToFix(Adapt* a, int flag) PCU_ALWAYS_ASSERT(edge); if (edge && !ma::getFlag(a,edge,flag)) { - ma::setFlag(a,edge,flag); + if (m->getModelType(m->toModel(edge)) != 1) + ma::setFlag(a,edge,flag); if (a->mesh->isOwned(edge)) ++count; } @@ -586,6 +892,38 @@ static int markEdgesToFix(Adapt* a, int flag) return PCU_Add_Long(count); } +static int markFacesToFix(Adapt* a, int flag) +{ + int invalid = markInvalidEntities(a); + if (!invalid) + return 0; + int count = 0; + + ma::Mesh* m = a->mesh; + ma::Entity* e; + + ma::Entity* faces[4]; + ma::Iterator* it = m->begin(m->getDimension()); + while ((e = m->iterate(it))) + { + int tag = crv::getTag(a, e); + int n = markFaces(m, e, tag, faces); + for (int i = 0; i < n; i++) { + ma::Entity* face = faces[i]; + PCU_ALWAYS_ASSERT(face); + if (face && !ma::getFlag(a, face, flag)) { + if (m->getModelType(m->toModel(face)) != 2) + ma::setFlag(a, face, flag); + if (a->mesh->isOwned(face)) + count++; + } + } + } + m->end(it); + + return PCU_Add_Long(count); +} + int fixLargeBoundaryAngles(Adapt* a) { double t0 = PCU_Time(); @@ -651,6 +989,28 @@ static void optimizeInvalidEdges(Adapt* a) "in %f seconds",eo.ns, eo.nf, t1-t0); } +static void optimizeInvalidFaces(Adapt* a) +{ + double t0 = PCU_Time(); + FaceOptimizer fo(a); + ma::applyOperator(a, &fo); + double t1 = PCU_Time(); + ma::print("Optimized %d bad faces, failed %d faces " + "in %f seconds", fo.ns, fo.nf, t1-t0); +} + +int fixInvalidFaces(Adapt* a) +{ + int count = markFacesToFix(a, ma::SNAP | ma::BAD_QUALITY); + if (! count) { + return 0; + } + + optimizeInvalidFaces(a); + + return count; +} + int fixInvalidEdges(Adapt* a) { int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); @@ -742,6 +1102,7 @@ void fixCrvElementShapes(Adapt* a) /* PCU_Add_Ints(&numEdgeRemoved,1); */ /* if (PCU_Comm_Self() == 0) */ /* lion_oprint(1,"==> %d edges removal operations succeeded.\n", numEdgeRemoved); */ + //fixInvalidFaces(a); count = markCrvBadQuality(a); ++i; } while(count < prev_count && i < 6); // the second conditions is to make sure this does not take long diff --git a/crv/crvShape.h b/crv/crvShape.h index fcd3ed09f..2536a13a5 100644 --- a/crv/crvShape.h +++ b/crv/crvShape.h @@ -59,6 +59,10 @@ int fixLargeBoundaryAngles(Adapt* a); try and collapse or swap it away */ int fixInvalidEdges(Adapt* a); +/** \brief If a face is flagged as invalid + optimize the face nodes */ +int fixInvalidFaces(Adapt* a); + /** \brief attempts to fix the shape of the elements in a same manner as ma::fixElementShape */ void fixCrvElementShapes(Adapt* a); diff --git a/crv/crvVtk.cc b/crv/crvVtk.cc index 489e1f3ae..c2ca9b8fb 100644 --- a/crv/crvVtk.cc +++ b/crv/crvVtk.cc @@ -311,6 +311,47 @@ static void writeEdgeJacobianDet(std::ostream& file, apf::Mesh* m, int n) file << "\n"; } +static double getVolume(apf::Mesh* mesh, apf::MeshEntity* e) +{ + apf::MeshEntity* adjV[4]; + mesh->getDownward(e, 0, adjV); + apf::Matrix3x3 m; + apf::Vector3 point0, point; + + for (std::size_t j = 0; j < 4; j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = apf::getDeterminant(m)/6.0; + + return v; + +} + +static double getArea(apf::Mesh* mesh, apf::MeshEntity* e) +{ + apf::MeshEntity* ver[3]; + mesh->getDownward(e, 0, ver); + apf::Vector3 point0, point1, point2; + + mesh->getPoint(ver[0], 0, point0); + mesh->getPoint(ver[1], 0, point1); + mesh->getPoint(ver[2], 0, point2); + + point1 = point1 - point0; + point2 = point2 - point0; + + double area = (apf::cross(point1, point2)).getLength(); + + return (area/2.0); + +} + static void writeTriJacobianDet(std::ostream& file, apf::Mesh* m, int n) { file << " 0) detJ[i] /= maxJ; - file << detJ[i] << '\n'; + //if(detJ[i] > 0) detJ[i] /= maxJ; + file << detJ[i]/area << '\n'; } apf::destroyMeshElement(me); } @@ -436,10 +479,11 @@ static void writeTetJacobianDet(std::ostream& file, apf::Mesh* m, int n) } } } + double vol = getVolume(m, e); if(maxJ < 1e-10) maxJ = 1e-10; for (int i = 0; i < 4*(n+1)*(n+1)*(n+1); ++i){ - if(detJ[i] > 0) detJ[i] /= maxJ; - file << detJ[i] << '\n'; + //if(detJ[i] > 0) detJ[i] /= maxJ; + file << detJ[i]/vol << '\n'; } apf::destroyMeshElement(me); From 08e8c1309a60d93cb2758d6366dfc70ff599e372 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Thu, 1 Aug 2019 21:50:55 -0400 Subject: [PATCH 07/48] edge optimization based on all invaliidities. --- crv/crvAdapt.cc | 10 +- crv/crvCurveMesh.cc | 14 ++- crv/crvModelEdgeOptim.cc | 26 ++---- crv/crvQuality.cc | 58 ++++++++++++ crv/crvQuality.h | 1 + crv/crvShape.cc | 194 +++++++++++++++++++++++++++++++++------ 6 files changed, 252 insertions(+), 51 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 1e923206d..3960c10db 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -165,8 +165,9 @@ static int fixInvalidElements(crv::Adapt* a) { a->input->shouldForceAdaptation = false; int count = crv::fixLargeBoundaryAngles(a) - + crv::fixInvalidFaces(a) + crv::fixInvalidEdges(a); + //+ crv::fixInvalidFaces(a); + //+ crv::fixInvalidEdges(a); int originalCount = count; int prev_count; int i = 0; @@ -175,14 +176,15 @@ static int fixInvalidElements(crv::Adapt* a) break; prev_count = count; count = crv::fixLargeBoundaryAngles(a) - + crv::fixInvalidFaces(a) - + crv::fixInvalidEdges(a); + + crv::fixInvalidEdges(a); + //+ crv::fixInvalidFaces(a); + //+ crv::fixInvalidEdges(a); ++i; } while(count < prev_count); crv::fixLargeBoundaryAngles(a); ma::clearFlagFromDimension(a,ma::COLLAPSE | ma::BAD_QUALITY,1); - //ma::clearFlagFromDimension(a, ma::SNAP | ma::BAD_QUALITY, 2); + //ma::clearFlagFromDimension(a, ma::SNAP, 2); a->input->shouldForceAdaptation = false; return originalCount - count; } diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 739ca09bf..94ea09cb9 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -177,8 +177,14 @@ static bool faceOp(apf::Mesh2* m, apf::MeshEntity* me) CrvFaceOptim *opF = new CrvFaceOptim(m, me); opF->setMaxIter(100); opF->setTol(1e-8); - if (opF->run()) return true; - else return false; + if (opF->run()) { + //delete opF; + return true; + } + else { + //delete opF; + return false; + } } bool BezierCurver::run(bool flag) @@ -208,7 +214,7 @@ bool BezierCurver::run(bool flag) //crv::writeCurvedWireFrame(m_mesh, 40, "after-inflate"); if (flag == 1) { - /* + apf::MeshEntity* f; apf::MeshIterator* it = m_mesh->begin(2); apf::Adjacent adjR; @@ -225,7 +231,7 @@ bool BezierCurver::run(bool flag) } } m_mesh->end(it); - */ + if(m_mesh->getDimension() >= 2) { if (m_order == 2 || m_order == 3) { ma::Input* shapeFixer = configureShapeCorrection(m_mesh); diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 0e3346e4f..ad629c941 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -469,9 +469,9 @@ double CrvModelEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &x) getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); x1 = eCP[2+i+1] - eCP[2+i]; x0 = eCP[2+i] - eCP[0]; - xir = (xi2[0] - xi1[0])/(xi1[0] + 1); // parent coordinate[-1,1] + xir = (xi2[0] - xi1[0])/(xi1[0] + 1.0); // parent coordinate[-1,1] } else { getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); x1 = eCP[1] - eCP[2+i]; x0 = eCP[2+i] - eCP[2+i-1]; - xir = (1 - xi1[0])/(xi1[0] - xi0[0]); + xir = (1.0 - xi1[0])/(xi1[0] - xi0[0]); } //if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) @@ -588,19 +588,13 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) // alpha = 1.0 - 0.5*(xi1[0]+1.0); xr = (x1.getLength()/x0.getLength()); - ad = (xr/xir - 1); //(alpha*alpha); + ad = (1.0*xr/xir - 1.0); //(alpha*alpha); beta = beta + ad*ad; //sum = sum + ad*ad; } //sum = sum*(1 + beta); apf::destroyElement(Edl); -/* - //if (mesh->getModelType(mesh->toModel(edge)) == 2) { - // if (mesh->getModelTag(mesh->toModel(edge)) == 26) { -// double arandomnumber = 2; - // } - // } - + apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); apf::NewArray fCP; @@ -652,8 +646,8 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) apf::destroyElement(Fal); } } -*/ - sum = sum*(1 + beta );//+ 0.3*gamma); + + sum = sum*(1 + beta + 0.3*gamma); restoreInitialNodes(); } @@ -736,7 +730,7 @@ bool CrvModelEdgeOptim :: run() finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - + /* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -746,7 +740,7 @@ bool CrvModelEdgeOptim :: run() return false; } } - + */ //std::cout<<"---------------------------------------------"< getAllInvalidities(apf::MeshEntity* e); int blendingOrder; int n; apf::NewArray blendingCoeffs; @@ -71,6 +72,7 @@ class Quality3D : public Quality virtual ~Quality3D() {}; double getQuality(apf::MeshEntity* e); int checkValidity(apf::MeshEntity* e); + std::vector getAllInvalidities(apf::MeshEntity* e); // 3D uses an alternate method of computing these // returns a validity tag so both quality and validity can // quit early if this function thinks they should @@ -374,6 +376,9 @@ static void getJacDetBySubdivisionMatrices(int type, int P, } } +std::vector Quality2D::getAllInvalidities(apf::MeshEntity* e) +{} + int Quality2D::checkValidity(apf::MeshEntity* e) { @@ -614,6 +619,59 @@ double computeTetJacobianDetFromBezierFormulation(apf::Mesh* m, return detJ; } +std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) +{ + int order = mesh->getShape()->getOrder(); + int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); + + apf::NewArray xi; + xi.allocate(n); + + std::vector ai; + apf::NewArray interNodes(n); + apf::MeshElement* me = apf::createMeshElement(mesh,e); + + for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ + int index = 18*order*order-36*order+20+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(20); + } + } + + for (int face = 0; face < 4; ++face){ + for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ + int index = 18*order-20+face*(3*order-4)*(3*order-5)/2+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(face+14); + break; + } + } + } + + for (int edge = 0; edge < 6; ++edge){ + for (int i = 0; i < 3*(order-1)-1; ++i){ + int index = 4+edge*(3*(order-1)-1)+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(edge+8); + break; + } + } + } + + for (int i = 0; i < 4; ++i){ + interNodes[i] = apf::getDV(me,xi[i]); + if(interNodes[i] < 1e-10){ + ai.push_back(i+2); + } + } + apf::destroyMeshElement(me); + + return ai; +} + int Quality3D::computeJacDetNodes(apf::MeshEntity* e, apf::NewArray& nodes, bool validity) { diff --git a/crv/crvQuality.h b/crv/crvQuality.h index 60c115ba5..9e5ffe4c5 100644 --- a/crv/crvQuality.h +++ b/crv/crvQuality.h @@ -42,6 +42,7 @@ void elevateBezierJacobianDet(int type, int P, int r, double Nijk(apf::NewArray& nodes, int d, int I, int J); double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K); +std::vector getAllInvalidities(apf::Mesh* mesh, apf::MeshEntity* e); } #endif diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 22340d12c..98f1be05c 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -22,6 +22,7 @@ #include "crvEdgeOptim.h" #include "crvModelEdgeOptim.h" #include "crvFaceOptim.h" +#include "crvQuality.h" /* This is similar to maShape.cc, conceptually, but different enough * that some duplicate code makes sense */ @@ -115,9 +116,11 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent apf::MeshEntity* ef[3]; apf::MeshEntity* ve[2]; std::vector aa; - std::vector bb; + //std::vector bb; - for (int i = 0; i < 2; i++) { + // need to flag all adjacent edges + // hence only 2 faces would do + for (int i = 0; i < 2; i++) { int nef = mesh->getDownward(f[a[cc[i]]], 1, ef); for (int j = 0; j < nef; j++) { mesh->getDownward(ef[j], 0, ve); @@ -128,19 +131,19 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent for (int ii = 0; ii < 2; ii++) { if ( k != aa[ii] ) { aa.push_back(k); - bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); + //bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); } } } else { aa.push_back(k); - bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); + //bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); } } } } } - +/* if (bb[0] < bb[1] ) { int k = aa[0]; int kk = bb[0]; @@ -149,13 +152,135 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent bb[0] = bb[1]; bb[1] = kk; } - + */ // aa has the index of the edges ordered // min to max of adj face jacobian return aa; } +static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std::vector all) +{ + apf::MeshEntity* ed[6]; + mesh->getDownward(e, 1, ed); + //int n = all.size(); + + // sort all edges + // aim is to erase duplicate edges + for (size_t i = 0; i < all.size(); i++) { + for (int j = i-1; j >= 0; --j) { + int ko = all[j+1]; + if ( ko < all[j]) { + all[j+1] = all[j]; + all[j] = ko; + } + } + } + + std::vector b; + b.push_back(all[0]); + for (size_t i = 1; i < all.size(); i++) { + if (all[i] != all[i-1]) + b.push_back(all[i]); + } + + std::vector bb; + //int nn = b.size(); + //get type of each edge + for (size_t j = 0; j < b.size(); j++) { + bb.push_back(mesh->getModelType(mesh->toModel(ed[b[j]]))); + } + + //sort type from 3-1 + for (size_t i = 0; i < bb.size(); i++) { + for (int j = i-1; j >= 0; --j) { + int k = bb[j+1]; + int kk = b[j+1]; + if ( k > bb[j]) { + bb[j+1] = bb[j]; + bb[j] = k; + b[j+1] = b[j]; + b[j] = kk; + } + } + } + + return b; +} + +static int markAllEdges(ma::Mesh* m, ma::Entity* e, + std::vector ai, ma::Entity* edges[6]) +{ + std::vector bb; + apf::MeshEntity* edf[3]; + apf::MeshEntity* faces[4]; + ma::Downward ed; + m->getDownward(e,1,ed); + + for (size_t ii = 0; ii < ai.size(); ii++) { + int dim = (ai[ii]-2)/6; + int index = (ai[ii]-2) % 6; + + switch (dim) { + case 0: + { + //ma::Downward ed; + //m->getDownward(e,1,ed); + + std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); + PCU_ALWAYS_ASSERT(index < 4); + for (size_t i = 0; i < aa.size(); i++) + bb.push_back(aa[i]); + + break; + } + + case 1: + { + //ma::Downward ed; + //m->getDownward(e,1,ed); + bb.push_back(index); + break; + } + //break; + case 2: + { + // if we have an invalid face, operate on its edges + //ma::Downward edf, faces; + m->getDownward(e,2,faces); + m->getDownward(faces[index],1,edf); + + for (int i = 0; i < 3; i++) { + int j = apf::findIn(ed, 6, edf[i]); + if (j != -1) + bb.push_back(j); + } + break; + } + //break; + case 3: + { + m->getDownward(e,1,edges); + return 6; + } + default: + fail("invalid quality tag in markEdges\n"); + break; + } + } + + int n = 0; + std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); + + for (size_t i = 0; i < allinvEdges.size(); i++) { + if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { + n++; + edges[n-1] = ed[allinvEdges[i]]; + } + } + + return n; +} static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* edges[6]) @@ -175,18 +300,18 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, m->getDownward(e,1,ed); n = md; - std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); + //std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); if(md == 2){ edges[0] = ed[index]; edges[1] = ed[(index+2) % 3]; } else { PCU_ALWAYS_ASSERT(index < 4); - edges[0] = ed[aa[0]]; - edges[1] = ed[aa[1]]; - edges[2] = ed[aa[2]]; - //edges[0] = ed[vertEdges[index][0]]; - //edges[1] = ed[vertEdges[index][1]]; - //edges[2] = ed[vertEdges[index][2]]; + //edges[0] = ed[aa[0]]; + //edges[1] = ed[aa[1]]; + //edges[2] = ed[aa[2]]; + edges[0] = ed[vertEdges[index][0]]; + edges[1] = ed[vertEdges[index][1]]; + edges[2] = ed[vertEdges[index][2]]; } break; } @@ -563,7 +688,7 @@ class FaceOptimizer : public ma::Operator virtual int getTargetDimension() {return 2;} virtual bool shouldApply(ma::Entity* e) { - if (!ma::getFlag(adapter, e, ma::SNAP | ma::BAD_QUALITY)) { + if (!ma::getFlag(adapter, e, ma::SNAP)) { return false; } @@ -594,7 +719,8 @@ class FaceOptimizer : public ma::Operator if (cfo->run()) ns++; else nf++; - ma::clearFlag(adapter, face, ma::SNAP | ma::BAD_QUALITY); + ma::clearFlag(adapter, face, ma::SNAP); + delete cfo; } } private: @@ -630,6 +756,7 @@ class EdgeOptimizer : public ma::Operator // return false; //} if (mesh->getModelType(mesh->toModel(e)) == 1) { + ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); return false; } else { @@ -653,6 +780,7 @@ class EdgeOptimizer : public ma::Operator else nf++; ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + delete ceo; } else if (mesh->getModelType(mesh->toModel(edge)) == 2) { CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edge); @@ -663,6 +791,7 @@ class EdgeOptimizer : public ma::Operator else nf++; ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + delete cmeo; } } private: @@ -871,22 +1000,33 @@ static int markEdgesToFix(Adapt* a, int flag) // markEdges could have upto 6 edges marked!!! ma::Entity* edges[6]; ma::Iterator* it = m->begin(m->getDimension()); + //std::vector ai; + //Quality* qual = makeQuality(m, 2); while ((e = m->iterate(it))) { - int tag = crv::getTag(a,e); - int n = markEdges(m,e,tag,edges); - for (int i = 0; i < n; ++i){ - ma::Entity* edge = edges[i]; - PCU_ALWAYS_ASSERT(edge); - if (edge && !ma::getFlag(a,edge,flag)) - { - if (m->getModelType(m->toModel(edge)) != 1) - ma::setFlag(a,edge,flag); - if (a->mesh->isOwned(edge)) - ++count; + //int tag = crv::getTag(a,e); + //int n = markEdges(m,e,tag,edges); + + std::vector ai = crv::getAllInvalidities(m, e); + //int niv = qual->checkValidity(e); + int niv = ai.size(); + if (niv != 0) { + int n = markAllEdges(m, e, ai, edges); + for (int i = 0; i < n; ++i){ + ma::Entity* edge = edges[i]; + PCU_ALWAYS_ASSERT(edge); + + if (edge && !ma::getFlag(a,edge,flag)) { + if (m->getModelType(m->toModel(edge)) != 1) { + ma::setFlag(a,edge,flag); + if (a->mesh->isOwned(edge)) + ++count; + } + } } } } + //delete qual; m->end(it); return PCU_Add_Long(count); @@ -1001,7 +1141,7 @@ static void optimizeInvalidFaces(Adapt* a) int fixInvalidFaces(Adapt* a) { - int count = markFacesToFix(a, ma::SNAP | ma::BAD_QUALITY); + int count = markFacesToFix(a, ma::SNAP); if (! count) { return 0; } From 98eeaf3071063421049702621b1f991b41d5f68e Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Wed, 6 Nov 2019 18:02:30 -0500 Subject: [PATCH 08/48] Debugging on Avinash's code --- crv/CMakeLists.txt | 10 +- crv/crvAdapt.cc | 9 ++ crv/crvCurveMesh.cc | 39 ++++---- crv/crvQuality.cc | 219 ++++++++++++++++++++++++++++++++++++++++++++ crv/crvQuality.h | 2 + 5 files changed, 258 insertions(+), 21 deletions(-) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 79995f23f..b18d8eb15 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -29,9 +29,13 @@ set(SOURCES # Package headers set(HEADERS crv.h - /lore/mohara/core/crv/crvEdgeOptim.h - /lore/mohara/core/crv/crvModelEdgeOptim.h - /lore/mohara/core/crv/crvFaceOptim.h + crvEdgeOptim.h + crvModelEdgeOptim.h + crvFaceOptim.h + LBFGS.h + crvBezier.h + crvTables.h + crvQuality.h ) # Add the crv library diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 3960c10db..2c971d3af 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -163,6 +163,13 @@ ma::Input* configureShapeCorrection( static int fixInvalidElements(crv::Adapt* a) { + + crv::fixLargeBoundaryAngles(a); + crv::fixInvalidEdges(a); + + return 0; + + a->input->shouldForceAdaptation = false; int count = crv::fixLargeBoundaryAngles(a) + crv::fixInvalidEdges(a); @@ -214,6 +221,8 @@ void adapt(ma::Input* in) fixInvalidElements(a); + return; + for (int i=0; i < in->maximumIterations; ++i) { ma::print("iteration %d",i); diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 94ea09cb9..0eb1fa85b 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -202,6 +202,9 @@ bool BezierCurver::run(bool flag) apf::changeMeshShape(m_mesh, getBezier(m_order),true); } + writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_shape_change"); + writeCurvedWireFrame(m_mesh, 16, "mesh_after_shape_change"); + if (m_mesh->canSnap()){ for(int d = 1; d <= 2; ++d) snapToInterpolate(d); @@ -210,27 +213,27 @@ bool BezierCurver::run(bool flag) convertInterpolatingToBezier(); - //crv::writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 10, "after-inflate"); - //crv::writeCurvedWireFrame(m_mesh, 40, "after-inflate"); + writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_inflate"); + writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); if (flag == 1) { - apf::MeshEntity* f; - apf::MeshIterator* it = m_mesh->begin(2); - apf::Adjacent adjR; - while ((f = m_mesh->iterate(it))){ - int count = 0; - if(m_mesh->getModelType(m_mesh->toModel(f)) == 3) { - m_mesh->getAdjacent(f, 3, adjR); - for (std::size_t i = 0; i < adjR.getSize(); i++) { - if (crv::checkValidity(m_mesh, adjR[i], 2) > 1) - count ++; - } - if (count > 0) - faceOp(m_mesh, f); - } - } - m_mesh->end(it); + /* apf::MeshEntity* f; */ + /* apf::MeshIterator* it = m_mesh->begin(2); */ + /* apf::Adjacent adjR; */ + /* while ((f = m_mesh->iterate(it))){ */ + /* int count = 0; */ + /* if(m_mesh->getModelType(m_mesh->toModel(f)) == 3) { */ + /* m_mesh->getAdjacent(f, 3, adjR); */ + /* for (std::size_t i = 0; i < adjR.getSize(); i++) { */ + /* if (crv::checkValidity(m_mesh, adjR[i], 2) > 1) */ + /* count ++; */ + /* } */ + /* if (count > 0) */ + /* faceOp(m_mesh, f); */ + /* } */ + /* } */ + /* m_mesh->end(it); */ if(m_mesh->getDimension() >= 2) { if (m_order == 2 || m_order == 3) { diff --git a/crv/crvQuality.cc b/crv/crvQuality.cc index 9372a5090..12e9e8170 100644 --- a/crv/crvQuality.cc +++ b/crv/crvQuality.cc @@ -10,6 +10,7 @@ #include "crvMath.h" #include "crvTables.h" #include "crvQuality.h" +#include namespace crv { @@ -479,6 +480,7 @@ int Quality3D::checkValidity(apf::MeshEntity* e) int validityTag = computeJacDetNodes(e,nodes,true); if (validityTag > 1) return validityTag; + else return 1; // check verts apf::Downward verts; mesh->getDownward(e,0,verts); @@ -487,6 +489,7 @@ int Quality3D::checkValidity(apf::MeshEntity* e) return 2+i; } } + // std::cout<<"reached here"<getDownward(e,1,edges); @@ -619,6 +622,220 @@ double computeTetJacobianDetFromBezierFormulation(apf::Mesh* m, return detJ; } +std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorithm) +{ + + int order = mesh->getShape()->getOrder(); + int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); + apf::NewArray subdivisionCoeffs[4]; + // apf::NewArray xi; + // xi.allocate(n); + if (algorithm == 0 || algorithm == 2){ + for (int d = 1; d <= 3; ++d) + getBezierJacobianDetSubdivisionCoefficients( + 3*(order-1),apf::Mesh::simplexTypes[d],subdivisionCoeffs[d]); + } + + apf::NewArray nodes(n); + + std::vector ai = getAllInvaliditiesWNodes(mesh, e, nodes); + + std::vector ainvA; + + if (ai.size()==0) { + ainvA.push_back(-1); + return ainvA; + } + + int flag = 3; + if (ai[0] == 20) flag = 0; + else if (ai[0] > 13 && ai[0] < 18) flag = 1; + else if (ai[0] > 7 && ai[0] < 14) flag = 2; + + apf::Downward verts; + mesh->getDownward(e,0,verts); + for (int i = 0; i < 4; ++i){ + if(nodes[i] < minAcceptable){ + ainvA.push_back(2+i); + } + } + + double minJ = 0, maxJ = 0; + if (flag == 0 || flag == 1 || flag == 2) { + apf::MeshEntity* edges[6]; + mesh->getDownward(e,1,edges); + // Vertices will already be flagged in the first check + + for (int edge = 0; edge < 6; ++edge){ + for (int i = 0; i < 3*(order-1)-1; ++i){ + if (nodes[4+edge*(3*(order-1)-1)+i] < minAcceptable){ + minJ = -1e10; + apf::NewArray edgeNodes(3*(order-1)+1); + + if(algorithm < 2){ + edgeNodes[0] = nodes[apf::tet_edge_verts[edge][0]]; + edgeNodes[3*(order-1)] = nodes[apf::tet_edge_verts[edge][1]]; + for (int j = 0; j < 3*(order-1)-1; ++j) + edgeNodes[j+1] = nodes[4+edge*(3*(order-1)-1)+j]; + // allows recursion stop on first "conclusive" invalidity + if(algorithm == 1) + getJacDetByElevation(apf::Mesh::EDGE,3*(order-1), + edgeNodes,minJ,maxJ); + else { + bool done = false; + getJacDetBySubdivision(apf::Mesh::EDGE,3*(order-1), + 0,edgeNodes,minJ,maxJ,done); + } + } else { + edgeNodes[0] = nodes[apf::tet_edge_verts[edge][0]]; + edgeNodes[1] = nodes[apf::tet_edge_verts[edge][1]]; + for (int j = 0; j < 3*(order-1)-1; ++j) + edgeNodes[j+2] = nodes[4+edge*(3*(order-1)-1)+j]; + + bool done = false; + bool quality = false; + getJacDetBySubdivisionMatrices(apf::Mesh::EDGE,3*(order-1), + 0,subdivisionCoeffs[1],edgeNodes,minJ,maxJ,done,quality); + } + if(minJ < minAcceptable){ + ainvA.push_back(8+edge); + break; + } + } + } + } + } + + if (flag == 0 || flag == 1) { + apf::MeshEntity* faces[4]; + mesh->getDownward(e,2,faces); + for (int face = 0; face < 4; ++face){ + double minJ = -1e10; + for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ + if (nodes[18*order-20+face*(3*order-4)*(3*order-5)/2+i] < minAcceptable){ + minJ = -1e10; + apf::NewArray triNodes((3*order-2)*(3*order-1)/2); + getTriDetJacNodesFromTetDetJacNodes(face,3*(order-1),nodes,triNodes); + if(algorithm == 2){ + bool done = false; + bool quality = false; + getJacDetBySubdivisionMatrices(apf::Mesh::TRIANGLE,3*(order-1), + 0,subdivisionCoeffs[2],triNodes,minJ,maxJ,done,quality); + } else if(algorithm == 1) + getJacDetByElevation(apf::Mesh::TRIANGLE,3*(order-1), + triNodes,minJ,maxJ); + else { + bool done = false; + getJacDetBySubdivision(apf::Mesh::TRIANGLE,3*(order-1), + 0,triNodes,minJ,maxJ,done); + } + if(minJ < minAcceptable){ + ainvA.push_back(14+face); + break; + } + } + } + } + } + + if (flag == 0) { + for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ + if (nodes[18*order*order-36*order+20+i] < minAcceptable){ + minJ = -1e10; + if(algorithm == 1){ + getJacDetByElevation(apf::Mesh::TET,3*(order-1),nodes,minJ,maxJ); + } else { + bool done = false; + bool quality = false; + getJacDetBySubdivisionMatrices(apf::Mesh::TET,3*(order-1), + 0,subdivisionCoeffs[3],nodes,minJ,maxJ,done,quality); + } + if(minJ < minAcceptable){ + ainvA.push_back(20); + break; + } + } + } + } + return ainvA; +} + +std::vector getAllInvaliditiesWNodes(apf::Mesh* mesh,apf::MeshEntity* e, apf::NewArray& nodes) +{ + int order = mesh->getShape()->getOrder(); + int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); + + apf::NewArray xi; + xi.allocate(n); + + collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), + elem_vert_xi[apf::Mesh::TET], xi); + std::vector ai; + apf::NewArray interNodes(n); + apf::MeshElement* me = apf::createMeshElement(mesh,e); + + for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ + int index = 18*order*order-36*order+20+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(20); + } + } + + for (int face = 0; face < 4; ++face){ + for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ + int index = 18*order-20+face*(3*order-4)*(3*order-5)/2+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(face+14); + break; + } + } + } + + for (int edge = 0; edge < 6; ++edge){ + for (int i = 0; i < 3*(order-1)-1; ++i){ + int index = 4+edge*(3*(order-1)-1)+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(edge+8); + break; + } + } + } + + for (int i = 0; i < 4; ++i){ + interNodes[i] = apf::getDV(me,xi[i]); + if(interNodes[i] < 1e-10){ + ai.push_back(i+2); + } + } + apf::destroyMeshElement(me); + + //collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), + // elem_vert_xi[apf::Mesh::TET], xi); + //for (int i = 0; i < n; i++) { + // std::cout<<"Determinant value at "<< xi[i] <<" "<< interNodes[i]< transformationMatrix; + mth::Matrix A(n,n); + transformationMatrix.resize(n,n); + //collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), + // elem_vert_xi[apf::Mesh::TET], xi); + getBezierTransformationMatrix(apf::Mesh::TET, 3*(order-1), A, + elem_vert_xi[apf::Mesh::TET]); + invertMatrixWithPLU(n, A, transformationMatrix); + + for (int i = 0; i < n; i++) { + nodes[i] = 0; + for (int j = 0; j < n; j++) + nodes[i] += interNodes[j]*transformationMatrix(i,j); + } + + return ai; +} + std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) { int order = mesh->getShape()->getOrder(); @@ -627,6 +844,8 @@ std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) apf::NewArray xi; xi.allocate(n); + collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), + elem_vert_xi[apf::Mesh::TET], xi); std::vector ai; apf::NewArray interNodes(n); apf::MeshElement* me = apf::createMeshElement(mesh,e); diff --git a/crv/crvQuality.h b/crv/crvQuality.h index 9e5ffe4c5..fcc54e07b 100644 --- a/crv/crvQuality.h +++ b/crv/crvQuality.h @@ -43,6 +43,8 @@ double Nijk(apf::NewArray& nodes, int d, int I, int J); double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K); std::vector getAllInvalidities(apf::Mesh* mesh, apf::MeshEntity* e); +std::vector getAllInvaliditiesWNodes(apf::Mesh* mesh, apf::MeshEntity* e, apf::NewArray& nodes); +std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorithm); } #endif From a171c428c89bb24ff9dd210ee82f5eef1b9a2e5d Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Thu, 7 Nov 2019 17:24:44 -0500 Subject: [PATCH 09/48] Debugging on Avinash's code day 2 --- crv/crvAdapt.cc | 1 + crv/crvEdgeOptim.cc | 148 +++++++++++++++++++++++++++++++++++++++ crv/crvModelEdgeOptim.cc | 2 - crv/crvShape.cc | 129 ++++++++++++++++++++++++++++++++-- 4 files changed, 271 insertions(+), 9 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 2c971d3af..2004204b5 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -165,6 +165,7 @@ static int fixInvalidElements(crv::Adapt* a) { crv::fixLargeBoundaryAngles(a); + /* crv::fixInvalidFaces(a); */ crv::fixInvalidEdges(a); return 0; diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 1c4f94d00..e628641d0 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -1,12 +1,147 @@ #include "crvEdgeOptim.h" #include "LBFGS.h" #include "crv.h" +#include "gmi.h" +#include "apfMDS.h" #include "crvQuality.h" #include "crvBezier.h" #include "crvMath.h" #include #include "apfMatrix.h" +static int global_counter = 0; + +static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], int count, int nat) +{ + printf("at edge %d\n", count); + for (int i = 0; i < nat; i++) { + std::vector ai = crv::getAllInvalidities(m, e[i]); + for (std::size_t j = 0; j < ai.size(); j++) { + printf("%d ", ai[j]); + } + printf("\n"); + } +} + + +static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], int count, const char* prefix, int nat) +{ + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); + //printf("HERE 02\n")liver tetrahedral element + outMesh->acceptChanges(); + } + + // std::stringstream ss2; + // ss2 << "straight_sided_" << count; + // apf::writeVtkFiles(ss2.str().c_str(), outMesh); + + apf::changeMeshShape(outMesh, crv::getBezier(3), true); + outMesh->acceptChanges(); + + for (int ii = 0; ii < nat; ii++) { + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh->getDownward(newEnt[ii], d, new_eds); + int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh->setPoint(new_eds[n], i, p); + } + } + } + outMesh->acceptChanges(); + } + /* + apf::MeshEntity* es1[6]; + apf::MeshEntity* es2[6]; + + outMesh->getDownward(newEnt, 1, es1); + m->getDownward(e, 1, es2); +*/ + std::stringstream ss; + ss << prefix<< count; + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 20, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 20, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh, 50, ss.str().c_str()); + + outMesh->destroyNative(); + apf::destroyMesh(outMesh); +} + namespace crv{ int CrvEdgeReshapeObjFunc :: getSpaceDim() @@ -508,6 +643,16 @@ void CrvEdgeOptim :: setTol(double t) bool CrvEdgeOptim :: run() { + global_counter++; + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(edge, 3, adj); + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + } + + makeMultipleEntityMesh(mesh, adj_array, global_counter, "before_cavity_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, global_counter, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); @@ -529,6 +674,9 @@ bool CrvEdgeOptim :: run() } } */ + + makeMultipleEntityMesh(mesh, adj_array, global_counter, "after_cavity_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, global_counter, adj.getSize()); return true; } else { diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index ad629c941..31cc820de 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -730,7 +730,6 @@ bool CrvModelEdgeOptim :: run() finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - /* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -740,7 +739,6 @@ bool CrvModelEdgeOptim :: run() return false; } } - */ //std::cout<<"---------------------------------------------"< getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent std::vector a; std::vector b; + // get the vertex local number for face from the invalid vertex for (int i = 0; i < nf; i++) { mesh->getDownward(f[i], 0, vf); int j = apf::findIn(vf, 3, vt[index]); @@ -81,8 +82,9 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent } } - double c[3]; - int cc[3]; + //getJacobianDeterminant on each face at + double c[3]; //contains jacobian value + int cc[3]; //face index apf::Vector3 xi; apf::Matrix3x3 Jac; for(size_t k = 0; k < a.size(); k++) { @@ -208,6 +210,84 @@ static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std:: return b; } +static int getCommonEdgeIndexToFaces(int a, int b) +{ + int tb[4][4] = {{-1, 0, 1, 2}, + {0, -1, 4, 3}, + {1, 4, -1, 5}, + {2, 3, 5, -1}}; + return tb[a][b] + 2; +} + +// doess not account for TET(20) invalidity +static int numOfUniqueFaces(std::vector &ai) +{ + int num = 0; + std::vector aiEdgeNVtx; + std::vector aiOnlyFace; + std::vector aiUniqueFace; + + for (size_t i = 0; i < ai.size(); i++) { + if (ai[i] > 13 && ai[i] < 20) + aiOnlyFace.push_back(ai[i]); + else + aiEdgeNVtx.push_back(ai[i]); + } + + int tbOfFaceToEdgeIndex[4][4] = {{-1, 0, 1, 2}, + {0, -1, 4, 3}, + {1, 4, -1, 5}, + {2, 3, 5, -1}}; + + for (size_t j = 0; j < aiOnlyFace.size(); j++) { + bool isUnique = false; + for (int i = 0; i < 4; i++) { + for (size_t k = 0; k < aiEdgeNVtx.size(); k++) { + isUnique = isUnique || (tbOfFaceToEdgeIndex[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]); + //if (tbOfFaceToEdgeIndex[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]) // only for TET + } + } + if (isUnique == false) + aiUniqueFace.push_back(aiOnlyFace[j]); + } + + ai.clear(); + + if (aiUniqueFace.size() > 0) { + for (std::size_t i = 0; i < aiUniqueFace.size(); i++) + ai.push_back(aiUniqueFace[i]); + for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) + ai.push_back(aiEdgeNVtx[i]); + + num = aiUniqueFace.size(); + return num; + } + else { + for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) + ai.push_back(aiEdgeNVtx[i]); + return 0; + } +} + +static std::vector inspectInvalidies(std::vector ai) +{ + std::vector aimod; + std::vector a; + + for (size_t i = 0; i < ai.size(); i++) { + if (ai[i] > 13) + a.push_back(ai[i]); + else + aimod.push_back(ai[i]); + } + if (a.size() == 2) { + //aimod.push_back(getCommonEdgeIndexToFaces(a[0]-14,a[1]-14)); + return aimod; + } + else + return ai; +} + static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* edges[6]) { @@ -217,7 +297,12 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, ma::Downward ed; m->getDownward(e,1,ed); - for (size_t ii = 0; ii < ai.size(); ii++) { + //std::vector ai = inspectInvalidies(aiall); + int num = numOfUniqueFaces(ai); + + if (ai.size() <= num) return 0; + + for (size_t ii = num; ii < ai.size(); ii++) { int dim = (ai[ii]-2)/6; int index = (ai[ii]-2) % 6; @@ -397,6 +482,31 @@ static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, i return a; } +static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, + ma::Entity* faces[4]) +{ + int num = numOfUniqueFaces(ai); + int n = 0; + + if (num > 0) { + for (std::size_t i = 0; i < num; i++) { + int index = (ai[i] -2) % 6; + int md = m->getDimension(); + + ma::Downward fc; + m->getDownward(e, 2, fc); + + if (m->getModelType(m->toModel(fc[index])) == 3) { + faces[n] = fc[index]; + n++; + } + } + return n; + } + else + return 0; +} + static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* faces[4]) { @@ -444,7 +554,7 @@ static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, ma::Downward fc; m->getDownward(e,2,fc); if (m->getModelType(m->toModel(fc[index])) == 3) { - faces[0] = fc[index]; + faces[n] = fc[index]; n++; } break; @@ -544,7 +654,10 @@ class EdgeReshaper : public ma::Operator virtual bool shouldApply(ma::Entity* e) { int tag = crv::getTag(adapter,e); - ne = markEdges(mesh,e,tag,edges); + + std::vector ai = crv::getAllInvalidities(mesh, e); + //ne = markEdges(mesh,e,tag,edges); + ne = markAllEdges(mesh, e, ai, edges); simplex = e; return (ne > 0); } @@ -1046,8 +1159,10 @@ static int markFacesToFix(Adapt* a, int flag) ma::Iterator* it = m->begin(m->getDimension()); while ((e = m->iterate(it))) { - int tag = crv::getTag(a, e); - int n = markFaces(m, e, tag, faces); + std::vector ai = crv::getAllInvalidities(m, e); +// int tag = crv::getTag(a, e); +// int n = markFaces(m, e, tag, faces); + int n = markUniqueFaces(m, e, ai, faces); for (int i = 0; i < n; i++) { ma::Entity* face = faces[i]; PCU_ALWAYS_ASSERT(face); From 7acc845d3a6925e65f5886addf44db1fedd16c0d Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 9 Nov 2019 13:11:27 -0500 Subject: [PATCH 10/48] Debugging Day-3 --- crv/crvAdapt.cc | 2 +- crv/crvEdgeOptim.cc | 253 +++++++++++++++++++++++++++++++++++++++++--- crv/crvQuality.cc | 36 ++++--- crv/crvShape.cc | 208 +++++++++++++++++++++++++++++------- 4 files changed, 427 insertions(+), 72 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 2004204b5..b7ad25f67 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -165,7 +165,7 @@ static int fixInvalidElements(crv::Adapt* a) { crv::fixLargeBoundaryAngles(a); - /* crv::fixInvalidFaces(a); */ + //crv::fixInvalidFaces(a); crv::fixInvalidEdges(a); return 0; diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index e628641d0..a127faba3 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -10,6 +10,8 @@ #include "apfMatrix.h" static int global_counter = 0; +static apf::MeshEntity* tetra[100]; +static int number = 0; static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], int count, int nat) { @@ -23,6 +25,17 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], int count, } } +static void printTetNumber(apf::MeshEntity* e) +{ + int n = apf::findIn(tetra, number, e); + if (n == -1) { + tetra[number] = e; + number++; + std::cout<<"; TET:: "<< number-1<acceptChanges(); } - /* - apf::MeshEntity* es1[6]; - apf::MeshEntity* es2[6]; - - outMesh->getDownward(newEnt, 1, es1); - m->getDownward(e, 1, es2); -*/ + std::stringstream ss; ss << prefix<< count; - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 20, ss.str().c_str()); - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 20, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh, 50, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); outMesh->destroyNative(); apf::destroyMesh(outMesh); } +static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) +{ + int dim = 0; + if (m->getType(e) == apf::Mesh::TRIANGLE) { + std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[4]; + for (int i = 0; i < 4; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); + } + + apf::MeshEntity* face[4]; + apf::MeshEntity* newface[4]; + int nf = m->getDownward(e, 2, face); + + for (int i = 0; i < nf; i++) { + + //Verts + apf::MeshEntity* vs[3]; + apf::MeshEntity* newVs[3]; + int nv = m->getDownward(face[i], 0, vs); + for (int j = 0; j < nv; j++) { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[j], 0, p); + newVs[j] = outMesh[i]->createVertex(0, p, param); + } + outMesh[i]->acceptChanges(); + + //Edges + apf::MeshEntity* es[3]; + apf::MeshEntity* newEs[3]; + int ne = m->getDownward(face[i], 1, es); + for (int j = 0; j < ne; j++) { + apf::MeshEntity* evs[2]; + apf::MeshEntity* newEvs[2]; + m->getDownward(es[j], 0, evs); + for (int k = 0; k < 2; k++) { + int kk = apf::findIn(vs,nv, evs[k]); + newEvs[k] = newVs[kk]; + } + + newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); + } + + //Faces + apf::MeshEntity* fes[3]; + apf::MeshEntity* newFes[3]; + m->getDownward(face[i], 1, fes); + for (int j = 0; j < 3; j++) + newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; + + newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); + + PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); + outMesh[i]->acceptChanges(); + + apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); + outMesh[i]->acceptChanges(); + + for (int d = 1; d < dim; d++) { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* ent[10]; + int counter = m->getDownward(face[i], d, ent); + apf::MeshEntity* newent[10]; + outMesh[i]->getDownward(newface[i], d, newent); + int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for (int n = 0; n < counter; n++) { + for (int j = 0; j < non; j++) { + apf::Vector3 p; + m->getPoint(ent[n], j, p); + outMesh[i]->setPoint(newent[n], j, p); + } + } + } + + outMesh[i]->acceptChanges(); + + std::stringstream ss; + ss << prefix << "_Face_"<< i; + crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); + } +} + +static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], int count, const char* prefix, int nat) +{ + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[nat]; + for (int i = 0; i < nat; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); + } + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh[ii]->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); + outMesh[ii]->acceptChanges(); + + apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); + outMesh[ii]->acceptChanges(); + + + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh[ii]->getDownward(newEnt[ii], d, new_eds); + int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh[ii]->setPoint(new_eds[n], i, p); + } + } + } + outMesh[ii]->acceptChanges(); + + std::stringstream ss; + ss << prefix<< count << "_TET_"<destroyNative(); + //apf::destroyMesh(outMesh[ii]); + + visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); + } +} + + namespace crv{ int CrvEdgeReshapeObjFunc :: getSpaceDim() @@ -651,7 +863,8 @@ bool CrvEdgeOptim :: run() adj_array[i] = adj[i]; } - makeMultipleEntityMesh(mesh, adj_array, global_counter, "before_cavity_of_edge_", adj.getSize()); + //makeMultipleEntityMesh(mesh, adj_array, global_counter, "before_cavity_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, global_counter, "before_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, global_counter, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); std::vector x0 = objF->getInitialGuess(); @@ -659,11 +872,22 @@ bool CrvEdgeOptim :: run() //std::cout<< "fval at x0 " << f0<getAdjacent(edge, 3, adjT); + apf::MeshEntity* ed[6]; + + for (std::size_t i = 0; i < adjT.getSize(); i++) { + mesh->getDownward(adjT[i], 1, ed); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d edge", edgeIndex); + printTetNumber(adjT[i]); + } + if (l->run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - /* +/* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -675,12 +899,15 @@ bool CrvEdgeOptim :: run() } */ - makeMultipleEntityMesh(mesh, adj_array, global_counter, "after_cavity_of_edge_", adj.getSize()); + //makeMultipleEntityMesh(mesh, adj_array, global_counter, "after_cavity_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, global_counter, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, global_counter, adj.getSize()); + std::cout<<"--------------------------------------"< getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) apf::NewArray interNodes(n); apf::MeshElement* me = apf::createMeshElement(mesh,e); - for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ - int index = 18*order*order-36*order+20+i; - interNodes[index] = apf::getDV(me,xi[index]); - if(interNodes[index] < 1e-10){ - ai.push_back(20); + for (int i = 0; i < 4; ++i){ + interNodes[i] = apf::getDV(me,xi[i]); + if(interNodes[i] < 1e-10){ + ai.push_back(i+2); } } - for (int face = 0; face < 4; ++face){ - for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ - int index = 18*order-20+face*(3*order-4)*(3*order-5)/2+i; + for (int edge = 0; edge < 6; ++edge){ + for (int i = 0; i < 3*(order-1)-1; ++i){ + int index = 4+edge*(3*(order-1)-1)+i; interNodes[index] = apf::getDV(me,xi[index]); if(interNodes[index] < 1e-10){ - ai.push_back(face+14); + ai.push_back(edge+8); break; } } } - for (int edge = 0; edge < 6; ++edge){ - for (int i = 0; i < 3*(order-1)-1; ++i){ - int index = 4+edge*(3*(order-1)-1)+i; + for (int face = 0; face < 4; ++face){ + for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ + int index = 18*order-20+face*(3*order-4)*(3*order-5)/2+i; interNodes[index] = apf::getDV(me,xi[index]); if(interNodes[index] < 1e-10){ - ai.push_back(edge+8); + ai.push_back(face+14); break; } } } - for (int i = 0; i < 4; ++i){ - interNodes[i] = apf::getDV(me,xi[i]); - if(interNodes[i] < 1e-10){ - ai.push_back(i+2); + for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ + int index = 18*order*order-36*order+20+i; + interNodes[index] = apf::getDV(me,xi[index]); + if(interNodes[index] < 1e-10){ + ai.push_back(20); + break; } } + apf::destroyMeshElement(me); return ai; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index bd162a200..9762afdcd 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -129,13 +129,12 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent if (apf::findIn(ve, 2, vt[index]) != -1) { int k = apf::findIn(edges, 6, ef[j]); if (k != -1) { - if (aa.size() > 2) { - for (int ii = 0; ii < 2; ii++) { - if ( k != aa[ii] ) { - aa.push_back(k); - //bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); - } - } + if (aa.size() >= 2) { + bool contains = false; + for (std::size_t ii = 0; ii < aa.size(); ii++) + contains = contains || (k == aa[ii]); + if (contains == false) + aa.push_back(k); } else { aa.push_back(k); @@ -161,6 +160,60 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent return aa; } + +static void sortDes(std::vector &a) +{ + for (std::size_t i = 0; i < a.size(); i++) { + for (int j = i-1; j >= 0; j--) { + int ko = a[j+1]; + if (ko > a[j]) { + a[j+1] = a[j]; + a[j] = ko; + } + } + } +} + +static void sortDesWrtFreqVector(std::vector &f, std::vector &a) +{ + for (std::size_t i = 0; i < f.size(); i++) { + for (int j = i-1; j >= 0; j--) { + int ko = f[j+1]; + int ke = a[j+1]; + if (ko > f[j]) { + f[j+1] = f[j]; + a[j+1] = a[j]; + f[j] = ko; + a[j] = ke; + } + } + } +} + +static std::vector sortEdgeIndexByFrequency(std::vector &all) +{ + sortDes(all); + std::vector freq, unqEntries; + freq.push_back(1); + int ind = 0; + unqEntries.push_back(all[0]); + + for (std::size_t i = 1; i < all.size(); i++) { + if (all[i] == all[i-1]) { + freq[ind] = freq[ind] + 1; + } + else { + unqEntries.push_back(all[i]); + ind++; + freq.push_back(1); + } + } + + sortDesWrtFreqVector(freq, unqEntries); + + return unqEntries; +} + static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std::vector all) { apf::MeshEntity* ed[6]; @@ -186,6 +239,8 @@ static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std:: b.push_back(all[i]); } + return b; + std::vector bb; //int nn = b.size(); //get type of each edge @@ -220,12 +275,12 @@ static int getCommonEdgeIndexToFaces(int a, int b) } // doess not account for TET(20) invalidity -static int numOfUniqueFaces(std::vector &ai) +static std::vector numOfUniqueFaces(std::vector &ai) { - int num = 0; std::vector aiEdgeNVtx; std::vector aiOnlyFace; std::vector aiUniqueFace; + std::vector FFE; for (size_t i = 0; i < ai.size(); i++) { if (ai[i] > 13 && ai[i] < 20) @@ -234,39 +289,71 @@ static int numOfUniqueFaces(std::vector &ai) aiEdgeNVtx.push_back(ai[i]); } - int tbOfFaceToEdgeIndex[4][4] = {{-1, 0, 1, 2}, - {0, -1, 4, 3}, - {1, 4, -1, 5}, - {2, 3, 5, -1}}; - + int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, + {0, -1, 4, 3}, + {1, 4, -1, 5}, + {2, 3, 5, -1}}; + + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) { + for (std::size_t j = 0; j < aiOnlyFace.size(); j++) { + if ((i != j) && (j > i)) { + for (std::size_t k = 0; k < aiEdgeNVtx.size(); k++) { + if (faceToEdgeInd[aiOnlyFace[i]-14][aiOnlyFace[j]-14] + 8 == aiEdgeNVtx[k]) { + FFE.push_back(aiEdgeNVtx[k]); + FFE.push_back(aiOnlyFace[j]); + FFE.push_back(aiOnlyFace[i]); + break; + } + } + break; + } + } + } + for (size_t j = 0; j < aiOnlyFace.size(); j++) { bool isUnique = false; for (int i = 0; i < 4; i++) { for (size_t k = 0; k < aiEdgeNVtx.size(); k++) { - isUnique = isUnique || (tbOfFaceToEdgeIndex[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]); - //if (tbOfFaceToEdgeIndex[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]) // only for TET + isUnique = isUnique || (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]); } } - if (isUnique == false) + if (isUnique == false) { aiUniqueFace.push_back(aiOnlyFace[j]); + aiOnlyFace.erase(aiOnlyFace.begin()+j); + } } ai.clear(); - if (aiUniqueFace.size() > 0) { - for (std::size_t i = 0; i < aiUniqueFace.size(); i++) - ai.push_back(aiUniqueFace[i]); + std::vector forFaceMarking; + //// + //[number of unique faces, {unique face index}, {pairs of face face coomon edge invalids}] + + if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { + forFaceMarking.push_back(aiUniqueFace.size()); for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) ai.push_back(aiEdgeNVtx[i]); + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + ai.push_back(aiOnlyFace[i]); + for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { + forFaceMarking.push_back(aiUniqueFace[i]); + } + for (std::size_t i = 0; i < FFE.size(); i++) + forFaceMarking.push_back(FFE[i]); - num = aiUniqueFace.size(); - return num; } - else { + else if (aiUniqueFace.size() == 0) { + forFaceMarking.push_back(0); + if (FFE.size() > 0) { + for (std::size_t i = 0; i < FFE.size(); i++) + forFaceMarking.push_back(FFE[i]); + } for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) ai.push_back(aiEdgeNVtx[i]); - return 0; + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + ai.push_back(aiOnlyFace[i]); } + return forFaceMarking; } static std::vector inspectInvalidies(std::vector ai) @@ -298,11 +385,12 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, m->getDownward(e,1,ed); //std::vector ai = inspectInvalidies(aiall); - int num = numOfUniqueFaces(ai); + std::vector faceInvalid = numOfUniqueFaces(ai); - if (ai.size() <= num) return 0; + if (ai.size() == 0) return 0; + if (ai.size() == faceInvalid[0]) return 0; - for (size_t ii = num; ii < ai.size(); ii++) { + for (size_t ii = faceInvalid[0]; ii < ai.size(); ii++) { int dim = (ai[ii]-2)/6; int index = (ai[ii]-2) % 6; @@ -337,8 +425,8 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, for (int i = 0; i < 3; i++) { int j = apf::findIn(ed, 6, edf[i]); - if (j != -1) - bb.push_back(j); + //if (j != -1) + //bb.push_back(j); } break; } @@ -355,8 +443,8 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, } int n = 0; - std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); - + //std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); + std::vector allinvEdges = sortEdgeIndexByFrequency(bb); for (size_t i = 0; i < allinvEdges.size(); i++) { if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { n++; @@ -485,26 +573,64 @@ static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, i static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* faces[4]) { - int num = numOfUniqueFaces(ai); + for (int i = 0; i < ai.size(); i++) { + if (ai[i] == 20) + int j = 0; + } + + std::vector faceInvalid = numOfUniqueFaces(ai); int n = 0; - if (num > 0) { - for (std::size_t i = 0; i < num; i++) { - int index = (ai[i] -2) % 6; - int md = m->getDimension(); + ma::Downward fc; + m->getDownward(e, 2, fc); + ma::Downward ed; + m->getDownward(e, 1, ed); - ma::Downward fc; - m->getDownward(e, 2, fc); + if (faceInvalid[0] > 0) { + for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { + int index = (faceInvalid[i] -2) % 6; + int md = m->getDimension(); if (m->getModelType(m->toModel(fc[index])) == 3) { faces[n] = fc[index]; n++; } } - return n; } - else - return 0; + + if (faceInvalid.size() > 1+faceInvalid[0]) { + int kkk = faceInvalid.size()-faceInvalid[0]-1; + int kk = kkk/3; + for (int k = 1; k <= kk; k++) { + int EdgeInd = (faceInvalid[faceInvalid[0] + 3*(k-1) + 1] - 2) % 6; + int FaceInd1 = (faceInvalid[faceInvalid[0] + 3*(k-1) + 2] - 2) % 6; + int FaceInd2 = (faceInvalid[faceInvalid[0] + 3*(k-1) + 3] - 2) % 6; + int edgeType = m->getModelType(m->toModel(ed[EdgeInd])); + + if (edgeType == 1 || edgeType == 2) { + int jf1 = m->getModelType(m->toModel(fc[FaceInd1])); + int jf2 = m->getModelType(m->toModel(fc[FaceInd2])); + + if (jf1 == 2 && jf2 != 2) { + faces[n] = fc[FaceInd2]; + n++; + } + else if (jf2 == 2 && jf1 != 2) { + faces[n] = fc[FaceInd1]; + n++; + } + else if (jf1 == 3 && jf2 == 3) { + faces[n] = fc[FaceInd1]; + n++; + faces[n] = fc[FaceInd2]; + n++; + } + } + } + } + + return n; + } static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, From 23bc9d51b3bfedb62885ea57db714084b8ef4d4a Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Sat, 9 Nov 2019 15:17:46 -0500 Subject: [PATCH 11/48] Debug edge optim day 4 --- crv/LBFGS.cc | 1 + crv/crvEdgeOptim.cc | 71 ++++++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc index 84f13006f..70a47071d 100644 --- a/crv/LBFGS.cc +++ b/crv/LBFGS.cc @@ -148,6 +148,7 @@ bool LBFGS::run() return true; } + currentX = xs[I]; for (std::size_t j = 0; j < xs[I].size(); j++) p[j] = -gs[I][j]; for (int i = I-1; i >= 0; --i) { diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index a127faba3..5f2968182 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -3,19 +3,23 @@ #include "crv.h" #include "gmi.h" #include "apfMDS.h" +#include "apfNumbering.h" #include "crvQuality.h" #include "crvBezier.h" #include "crvMath.h" #include #include "apfMatrix.h" -static int global_counter = 0; -static apf::MeshEntity* tetra[100]; -static int number = 0; +/* static int global_counter = 0; */ +/* static apf::MeshEntity* tetra[100]; */ +/* static int number = 0; */ -static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], int count, int nat) +static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { - printf("at edge %d\n", count); + apf::Numbering* n = m->findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + printf("at edge %d\n", num); for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -25,20 +29,27 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], int count, } } -static void printTetNumber(apf::MeshEntity* e) +static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { - int n = apf::findIn(tetra, number, e); - if (n == -1) { - tetra[number] = e; - number++; - std::cout<<"; TET:: "<< number-1<findNumbering("debug_num_tet"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, e, 0, 0); + std::cout<<"; TET:: "<< num <findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); int dim = 0; if (m->getType(e[0]) == apf::Mesh::TRIANGLE) dim = 2; @@ -140,7 +151,7 @@ static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], int co } std::stringstream ss; - ss << prefix<< count; + ss << prefix<< num; crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); @@ -242,8 +253,12 @@ static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, } } -static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], int count, const char* prefix, int nat) +static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) { + apf::Numbering* n = m->findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + return; int dim = 0; if (m->getType(e[0]) == apf::Mesh::TRIANGLE) dim = 2; @@ -341,7 +356,7 @@ static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e outMesh[ii]->acceptChanges(); std::stringstream ss; - ss << prefix<< count << "_TET_"<getAdjacent(edge, 3, adj); @@ -863,9 +877,9 @@ bool CrvEdgeOptim :: run() adj_array[i] = adj[i]; } - //makeMultipleEntityMesh(mesh, adj_array, global_counter, "before_cavity_of_edge_", adj.getSize()); - makeIndividualTetsFromFacesOrEdges(mesh, adj_array, global_counter, "before_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, global_counter, adj.getSize()); + makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); @@ -880,7 +894,7 @@ bool CrvEdgeOptim :: run() mesh->getDownward(adjT[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); printf("reshape tried on %d edge", edgeIndex); - printTetNumber(adjT[i]); + printTetNumber(mesh, adjT[i]); } if (l->run()) { @@ -899,14 +913,17 @@ bool CrvEdgeOptim :: run() } */ - //makeMultipleEntityMesh(mesh, adj_array, global_counter, "after_cavity_of_edge_", adj.getSize()); - makeIndividualTetsFromFacesOrEdges(mesh, adj_array, global_counter, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, global_counter, adj.getSize()); + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<currentX; */ + /* objF->setNodes(finalX); */ + makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + std::cout<<"*****Edge Optim FAILURE" < Date: Sun, 10 Nov 2019 13:07:07 -0500 Subject: [PATCH 12/48] Debugging Day 5 --- crv/crvCurveMesh.cc | 2 +- crv/crvEdgeOptim.cc | 18 +- crv/crvModelEdgeOptim.cc | 382 ++++++++++++++++++++++++++++++++++++++- crv/crvShape.cc | 38 ++-- 4 files changed, 408 insertions(+), 32 deletions(-) diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 0eb1fa85b..981952d60 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -213,7 +213,7 @@ bool BezierCurver::run(bool flag) convertInterpolatingToBezier(); - writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_inflate"); + writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "mesh_after_inflate"); writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); if (flag == 1) { diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 5f2968182..81ce73334 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -35,14 +35,6 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); std::cout<<"; TET:: "<< num <getType(e) == apf::Mesh::TRIANGLE) { std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) dim = 3; @@ -258,7 +249,6 @@ static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); - return; int dim = 0; if (m->getType(e[0]) == apf::Mesh::TRIANGLE) dim = 2; @@ -877,7 +867,7 @@ bool CrvEdgeOptim :: run() adj_array[i] = adj[i]; } - makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); + //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); @@ -920,9 +910,9 @@ bool CrvEdgeOptim :: run() return true; } else { - /* finalX = l->currentX; */ - /* objF->setNodes(finalX); */ - makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //finalX = l->currentX; + //objF->setNodes(finalX); + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); std::cout<<"*****Edge Optim FAILURE" < +static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) +{ + apf::Numbering* n = m->findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + printf("at edge %d\n", num); + for (int i = 0; i < nat; i++) { + std::vector ai = crv::getAllInvalidities(m, e[i]); + for (std::size_t j = 0; j < ai.size(); j++) { + printf("%d ", ai[j]); + } + printf("\n"); + } +} + +static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::Numbering* n = m->findNumbering("debug_num_tet"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, e, 0, 0); + std::cout<<"; TET:: "<< num <findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); + //printf("HERE 02\n")liver tetrahedral element + outMesh->acceptChanges(); + } + + // std::stringstream ss2; + // ss2 << "straight_sided_" << count; + // apf::writeVtkFiles(ss2.str().c_str(), outMesh); + + apf::changeMeshShape(outMesh, crv::getBezier(3), true); + outMesh->acceptChanges(); + + for (int ii = 0; ii < nat; ii++) { + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh->getDownward(newEnt[ii], d, new_eds); + int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh->setPoint(new_eds[n], i, p); + } + } + } + outMesh->acceptChanges(); + } + + std::stringstream ss; + ss << prefix<< num; + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); + + outMesh->destroyNative(); + apf::destroyMesh(outMesh); +} + +static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) +{ + int dim = 0; + if (m->getType(e) == apf::Mesh::TRIANGLE) { + std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[4]; + for (int i = 0; i < 4; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); + } + + apf::MeshEntity* face[4]; + apf::MeshEntity* newface[4]; + int nf = m->getDownward(e, 2, face); + for (int i = 0; i < nf; i++) { + + //Verts + apf::MeshEntity* vs[3]; + apf::MeshEntity* newVs[3]; + int nv = m->getDownward(face[i], 0, vs); + for (int j = 0; j < nv; j++) { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[j], 0, p); + newVs[j] = outMesh[i]->createVertex(0, p, param); + } + outMesh[i]->acceptChanges(); + + //Edges + apf::MeshEntity* es[3]; + apf::MeshEntity* newEs[3]; + int ne = m->getDownward(face[i], 1, es); + for (int j = 0; j < ne; j++) { + apf::MeshEntity* evs[2]; + apf::MeshEntity* newEvs[2]; + m->getDownward(es[j], 0, evs); + for (int k = 0; k < 2; k++) { + int kk = apf::findIn(vs,nv, evs[k]); + newEvs[k] = newVs[kk]; + } + + newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); + } + + //Faces + apf::MeshEntity* fes[3]; + apf::MeshEntity* newFes[3]; + m->getDownward(face[i], 1, fes); + for (int j = 0; j < 3; j++) + newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; + + newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); + + PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); + outMesh[i]->acceptChanges(); + + apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); + outMesh[i]->acceptChanges(); + + for (int d = 1; d < dim; d++) { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* ent[10]; + int counter = m->getDownward(face[i], d, ent); + apf::MeshEntity* newent[10]; + outMesh[i]->getDownward(newface[i], d, newent); + int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for (int n = 0; n < counter; n++) { + for (int j = 0; j < non; j++) { + apf::Vector3 p; + m->getPoint(ent[n], j, p); + outMesh[i]->setPoint(newent[n], j, p); + } + } + } + + outMesh[i]->acceptChanges(); + + std::stringstream ss; + ss << prefix << "_Face_"<< i; + crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); + } +} + +static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) +{ + apf::Numbering* n = m->findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[nat]; + for (int i = 0; i < nat; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); + } + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh[ii]->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); + outMesh[ii]->acceptChanges(); + + apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); + outMesh[ii]->acceptChanges(); + + + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh[ii]->getDownward(newEnt[ii], d, new_eds); + int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh[ii]->setPoint(new_eds[n], i, p); + } + } + } + outMesh[ii]->acceptChanges(); + + std::stringstream ss; + ss << prefix<< num << "_TET_"<destroyNative(); + //apf::destroyMesh(outMesh[ii]); + + visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); + } +} + namespace crv{ int CrvModelEdgeReshapeObjFunc :: getSpaceDim() @@ -720,16 +1066,42 @@ void CrvModelEdgeOptim :: setTol(double t) bool CrvModelEdgeOptim :: run() { + + + + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(edge, 3, adj); + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + } + + //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0<getAdjacent(edge, 3, adjT); + apf::MeshEntity* ed[6]; + + for (std::size_t i = 0; i < adjT.getSize(); i++) { + mesh->getDownward(adjT[i], 1, ed); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d edge", edgeIndex); + printTetNumber(mesh, adjT[i]); + } if (l->run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); + + /* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { @@ -739,10 +1111,18 @@ bool CrvModelEdgeOptim :: run() return false; } } - //std::cout<<"---------------------------------------------"<currentX; + //objF->setNodes(finalX); + std::cout<<"*****Optim FAILURE"< &f, std::vector &a) static std::vector sortEdgeIndexByFrequency(std::vector &all) { - sortDes(all); std::vector freq, unqEntries; freq.push_back(1); - int ind = 0; unqEntries.push_back(all[0]); for (std::size_t i = 1; i < all.size(); i++) { - if (all[i] == all[i-1]) { - freq[ind] = freq[ind] + 1; + bool milila = false; + + for (std::size_t j = 0; j < unqEntries.size(); j++) { + milila = milila || (all[i] == unqEntries[j]); + + if (all[i] == unqEntries[j]) { + freq[j] = freq[j] + 1; + } } - else { + if (milila == false) { unqEntries.push_back(all[i]); - ind++; freq.push_back(1); } } @@ -445,6 +448,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, int n = 0; //std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); std::vector allinvEdges = sortEdgeIndexByFrequency(bb); + for (size_t i = 0; i < allinvEdges.size(); i++) { if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { n++; @@ -454,7 +458,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, return n; } - +/* static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* edges[6]) { @@ -525,7 +529,8 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, return n; } - +*/ +/* static std::vector faceIndexAdjInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) { apf::MeshEntity* f[4]; @@ -569,7 +574,7 @@ static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, i } return a; } - +*/ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* faces[4]) { @@ -632,7 +637,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, return n; } - +/* static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* faces[4]) { @@ -706,7 +711,8 @@ static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, return n; } - +*/ +/* class EdgeSwapper : public ma::Operator { public: @@ -758,7 +764,7 @@ class EdgeSwapper : public ma::Operator public: int ns; }; - +*/ class EdgeReshaper : public ma::Operator { public: @@ -1339,7 +1345,7 @@ static void collapseInvalidEdges(Adapt* a) ma::print("Collapsed %d bad edges " "in %f seconds",successCount, t1-t0); } - +/* static void swapInvalidEdges(Adapt* a) { double t0 = PCU_Time(); @@ -1349,7 +1355,7 @@ static void swapInvalidEdges(Adapt* a) ma::print("Swapped %d bad edges " "in %f seconds",es.ns, t1-t0); } - +*/ static void repositionInvalidEdges(Adapt* a) { double t0 = PCU_Time(); @@ -1404,8 +1410,8 @@ int fixInvalidEdges(Adapt* a) else optimizeInvalidEdges(a); - collapseInvalidEdges(a); - swapInvalidEdges(a); + //collapseInvalidEdges(a); + //swapInvalidEdges(a); return count; } From 5a2f5646562f2e49016479532cc48d72d7189194 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 11 Nov 2019 11:41:39 -0500 Subject: [PATCH 13/48] Debugging Day 5a --- crv/crvEdgeOptim.cc | 4 ++-- crv/crvShape.cc | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 81ce73334..e809ebdab 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -868,7 +868,7 @@ bool CrvEdgeOptim :: run() } //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); std::vector x0 = objF->getInitialGuess(); @@ -904,7 +904,7 @@ bool CrvEdgeOptim :: run() */ //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"< allinvEdges = sortEdgeIndexByType(m, e, bb); std::vector allinvEdges = sortEdgeIndexByFrequency(bb); + int k = 0; for (size_t i = 0; i < allinvEdges.size(); i++) { if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { From 394fd59034f24b1f2d7b428549efe4f833edecbe Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 11 Nov 2019 13:06:21 -0500 Subject: [PATCH 14/48] Debugging Day 5a --- crv/crvShape.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crv/crvShape.cc b/crv/crvShape.cc index ab1ed8ac3..73c711555 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -393,7 +393,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, if (ai.size() == 0) return 0; if (ai.size() == faceInvalid[0]) return 0; - for (size_t ii = faceInvalid[0]; ii < ai.size(); ii++) { + for (size_t ii = 0; ii < ai.size(); ii++) { int dim = (ai[ii]-2)/6; int index = (ai[ii]-2) % 6; From d2ca50773baf889dc8526281cdfab3cf0bf5d281 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 11 Nov 2019 17:24:30 -0500 Subject: [PATCH 15/48] Debugging Day 6 - change in markedEdgestoFix --- crv/crvEdgeOptim.cc | 26 +++++++++--- crv/crvEdgeOptim.h | 12 +++--- crv/crvModelEdgeOptim.cc | 30 +++++++------ crv/crvModelEdgeOptim.h | 12 +++--- crv/crvShape.cc | 91 ++++++++++++++++++++++------------------ 5 files changed, 102 insertions(+), 69 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index e809ebdab..2f20a55db 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -853,9 +853,9 @@ void CrvEdgeOptim :: setMaxIter(int n) iter = n; } -void CrvEdgeOptim :: setTol(double t) +void CrvEdgeOptim :: setTol(double tolerance) { - tol = t; + tol = tolerance; } bool CrvEdgeOptim :: run() @@ -867,10 +867,11 @@ bool CrvEdgeOptim :: run() adj_array[i] = adj[i]; } + std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); - CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge); + CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0<currentX; fval = l->fValAfter; objF->setNodes(finalX); + + std::vector aiNew = crv::getAllInvalidities(mesh, tet); + if (aiNew.size() < ai.size()) { + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"--------------------------------------"<restoreInitialNodes(); + return false; + } /* apf::Adjacent adjT; mesh->getAdjacent(edge, 3, adjT); @@ -905,9 +919,9 @@ bool CrvEdgeOptim :: run() //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - std::cout<<"--------------------------------------"<currentX; diff --git a/crv/crvEdgeOptim.h b/crv/crvEdgeOptim.h index ec7bd7358..c4d21d036 100644 --- a/crv/crvEdgeOptim.h +++ b/crv/crvEdgeOptim.h @@ -15,8 +15,8 @@ namespace crv{ class CrvEdgeReshapeObjFunc : public ObjFunction { public: - CrvEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e) : - mesh(m), edge(e) + CrvEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) { P = mesh->getShape()->getOrder(); d = mesh->getDimension(); @@ -52,6 +52,7 @@ class CrvEdgeReshapeObjFunc : public ObjFunction protected: apf::Mesh2* mesh; apf::MeshEntity* edge; + apf::MeshEntity* tet; std::vector vol; std::vector ien; std::vector ifn; @@ -61,17 +62,18 @@ class CrvEdgeReshapeObjFunc : public ObjFunction class CrvEdgeOptim { public: - CrvEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e) : - mesh(m), edge(e) {} + CrvEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) {} ~CrvEdgeOptim(){} public: void setMaxIter(int n); - void setTol(double t); + void setTol(double tolerance); bool run(); public: apf::Mesh2* mesh; apf::MeshEntity* edge; + apf::MeshEntity* tet; int iter; double tol; std::vector finalX; diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 4b42a099b..bda41c5bc 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -1059,28 +1059,28 @@ void CrvModelEdgeOptim :: setMaxIter(int n) iter = n; } -void CrvModelEdgeOptim :: setTol(double t) +void CrvModelEdgeOptim :: setTol(double tolerance) { - tol = t; + tol = tolerance; } bool CrvModelEdgeOptim :: run() { - - - apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(edge, 3, adj); + int cInvT = 0; + for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; } + std::vector ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); - CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge); + CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< aiNew = crv::getAllInvalidities(mesh,tet); + if (aiNew.size() < ai.size()) { + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"--------------------------------------"<restoreInitialNodes(); + return false; + } } else { //finalX = l->currentX; diff --git a/crv/crvModelEdgeOptim.h b/crv/crvModelEdgeOptim.h index ff2f1710e..4489a48aa 100644 --- a/crv/crvModelEdgeOptim.h +++ b/crv/crvModelEdgeOptim.h @@ -15,8 +15,8 @@ namespace crv{ class CrvModelEdgeReshapeObjFunc : public ObjFunction { public: - CrvModelEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e) : - mesh(m), edge(e) + CrvModelEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) { P = mesh->getShape()->getOrder(); d = mesh->getDimension(); @@ -54,6 +54,7 @@ class CrvModelEdgeReshapeObjFunc : public ObjFunction protected: apf::Mesh2* mesh; apf::MeshEntity* edge; + apf::MeshEntity* tet; std::vector vol; std::vector ien; std::vector ifn; @@ -65,17 +66,18 @@ class CrvModelEdgeReshapeObjFunc : public ObjFunction class CrvModelEdgeOptim { public: - CrvModelEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e) : - mesh(m), edge(e) {} + CrvModelEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) {} ~CrvModelEdgeOptim(){} public: void setMaxIter(int n); - void setTol(double t); + void setTol(double tolerance); bool run(); public: apf::Mesh2* mesh; apf::MeshEntity* edge; + apf::MeshEntity* tet; int iter; double tol; std::vector finalX; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 73c711555..49546efc4 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -459,7 +459,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, return n; } -/* + static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, ma::Entity* edges[6]) { @@ -530,7 +530,7 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, return n; } -*/ + /* static std::vector faceIndexAdjInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) { @@ -713,7 +713,7 @@ static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, return n; } */ -/* + class EdgeSwapper : public ma::Operator { public: @@ -765,7 +765,7 @@ class EdgeSwapper : public ma::Operator public: int ns; }; -*/ + class EdgeReshaper : public ma::Operator { public: @@ -985,59 +985,64 @@ class EdgeOptimizer : public ma::Operator EdgeOptimizer(Adapt* a) { adapter = a; mesh = a->mesh; - edge = 0; + edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; + simplex = 0; + md = mesh->getDimension(); ns = 0; nf = 0; + ne = 0; } ~EdgeOptimizer() { } - virtual int getTargetDimension() {return 1;} + virtual int getTargetDimension() {return md;} virtual bool shouldApply(ma::Entity* e) { - - if (!ma::getFlag(adapter, e, ma::COLLAPSE | ma::BAD_QUALITY)) { - return false; + + std::vector ai = crv::getAllInvalidities(mesh, e); + int niv = ai.size(); + if (niv != 0) { + ne = markAllEdges(mesh, e, ai, edges); + simplex = e; + return (ne > 0); } - //if (isBoundaryEntity(mesh, e)) { - // return false; - //} - if (mesh->getModelType(mesh->toModel(e)) == 1) { - ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); - return false; - } - else { - edge = e; - return true; - } } virtual bool requestLocality(apf::CavityOp* o) { - return o->requestLocality(&edge, 1); + return o->requestLocality(edges, ne); } - virtual void apply(){ - if (mesh->getModelType(mesh->toModel(edge)) == 3) { - CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edge); - ceo->setMaxIter(100); - ceo->setTol(1e-8); - - if (ceo->run()) ns++; - else nf++; - - ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); - delete ceo; - } - else if (mesh->getModelType(mesh->toModel(edge)) == 2) { - CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edge); - cmeo->setMaxIter(100); - cmeo->setTol(1e-8); + virtual void apply() { + mesh->getDownward(simplex, 1, edges); + for (int i = 0; i < ne; i++ ) { + if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { + CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edges[i], simplex); + ceo->setMaxIter(100); + ceo->setTol(1e-8); + + if (ceo->run()) { + ns++; + break; + } + else nf++; - if (cmeo->run()) ns++; - else nf++; + delete ceo; + //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + } + else if (mesh->getModelType(mesh->toModel(edges[i])) == 2) { + CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edges[i], simplex); + cmeo->setMaxIter(100); + cmeo->setTol(1e-8); + + if (cmeo->run()) { + ns++; + break; + } + else nf++; - ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); - delete cmeo; + //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); + delete cmeo; + } } } private: @@ -1046,6 +1051,10 @@ class EdgeOptimizer : public ma::Operator ma::Mesh* mesh; ma::Entity* edge; public: + int ne; + int md; + ma::Entity* edges[6]; + ma::Entity* simplex; int ns; int nf; }; From a2c2d0a0b37d326eb4427e0e1f8568b10831ebce Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 11 Nov 2019 17:33:49 -0500 Subject: [PATCH 16/48] Debugging Day 6: changes to EdgeOptimizer logic --- crv/crvShape.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 49546efc4..eed10a764 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -1411,9 +1411,9 @@ int fixInvalidFaces(Adapt* a) int fixInvalidEdges(Adapt* a) { int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - if (! count){ - return 0; - } + //if (! count){ + // return 0; + //} if(a->mesh->getShape()->getOrder() == 2) repositionInvalidEdges(a); From d841f067bd99ba06dca22a395e82d2db7be63e0a Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 11 Nov 2019 23:36:47 -0500 Subject: [PATCH 17/48] Debugging Day 6- acceptance based on getting the operating TET valid --- crv/crvAdapt.cc | 2 +- crv/crvCurveMesh.cc | 33 ----------- crv/crvEdgeOptim.cc | 25 ++++---- crv/crvEdgeOptim.h | 2 +- crv/crvModelEdgeOptim.cc | 29 ++++++---- crv/crvModelEdgeOptim.h | 2 +- crv/crvShape.cc | 120 +++++++++++++++++++++++++-------------- 7 files changed, 112 insertions(+), 101 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index b7ad25f67..0aea1482c 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -165,7 +165,7 @@ static int fixInvalidElements(crv::Adapt* a) { crv::fixLargeBoundaryAngles(a); - //crv::fixInvalidFaces(a); + crv::fixInvalidFaces(a); crv::fixInvalidEdges(a); return 0; diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 981952d60..f347897ed 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -172,21 +172,6 @@ void BezierCurver::convertInterpolatingToBezier() synchronize(); } -static bool faceOp(apf::Mesh2* m, apf::MeshEntity* me) -{ - CrvFaceOptim *opF = new CrvFaceOptim(m, me); - opF->setMaxIter(100); - opF->setTol(1e-8); - if (opF->run()) { - //delete opF; - return true; - } - else { - //delete opF; - return false; - } -} - bool BezierCurver::run(bool flag) { std::string name = m_mesh->getShape()->getName(); @@ -217,24 +202,6 @@ bool BezierCurver::run(bool flag) writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); if (flag == 1) { - - /* apf::MeshEntity* f; */ - /* apf::MeshIterator* it = m_mesh->begin(2); */ - /* apf::Adjacent adjR; */ - /* while ((f = m_mesh->iterate(it))){ */ - /* int count = 0; */ - /* if(m_mesh->getModelType(m_mesh->toModel(f)) == 3) { */ - /* m_mesh->getAdjacent(f, 3, adjR); */ - /* for (std::size_t i = 0; i < adjR.getSize(); i++) { */ - /* if (crv::checkValidity(m_mesh, adjR[i], 2) > 1) */ - /* count ++; */ - /* } */ - /* if (count > 0) */ - /* faceOp(m_mesh, f); */ - /* } */ - /* } */ - /* m_mesh->end(it); */ - if(m_mesh->getDimension() >= 2) { if (m_order == 2 || m_order == 3) { ma::Input* shapeFixer = configureShapeCorrection(m_mesh); diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 2f20a55db..023546069 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -14,12 +14,19 @@ /* static apf::MeshEntity* tetra[100]; */ /* static int number = 0; */ +static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::Numbering* n = m->findNumbering("debug_num_tet"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, e, 0, 0); + std::cout<<" TET:: "<< num <findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); - printf("at edge %d\n", num); + std::cout<<"at edge "<< num << std::endl; for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -29,13 +36,6 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn } } -static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ - apf::Numbering* n = m->findNumbering("debug_num_tet"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, e, 0, 0); - std::cout<<"; TET:: "<< num < ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + printTetNumber(mesh, tet); printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); @@ -884,7 +885,7 @@ bool CrvEdgeOptim :: run() for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge", edgeIndex); + printf("reshape tried on %d edge; ", edgeIndex); printTetNumber(mesh, adjT[i]); } @@ -894,6 +895,7 @@ bool CrvEdgeOptim :: run() objF->setNodes(finalX); std::vector aiNew = crv::getAllInvalidities(mesh, tet); + invaliditySize = aiNew.size(); if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); @@ -903,6 +905,9 @@ bool CrvEdgeOptim :: run() } else { objF->restoreInitialNodes(); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"Size DID NOT decrease"< +static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::Numbering* n = m->findNumbering("debug_num_tet"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, e, 0, 0); + std::cout<<" TET:: "<< num <findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - printf("at edge %d\n", num); + int num = apf::getNumber(n, edge, 0, 0); + std::cout<<"at edge "<< num << std::endl; + for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -29,13 +38,6 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn } } -static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ - apf::Numbering* n = m->findNumbering("debug_num_tet"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, e, 0, 0); - std::cout<<"; TET:: "<< num < ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + printTetNumber(mesh, tet); printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); @@ -1092,7 +1095,7 @@ bool CrvModelEdgeOptim :: run() for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge", edgeIndex); + printf("reshape tried on %d edge; ", edgeIndex); printTetNumber(mesh, adjT[i]); } @@ -1113,6 +1116,7 @@ bool CrvModelEdgeOptim :: run() } */ std::vector aiNew = crv::getAllInvalidities(mesh,tet); + invaliditySize = aiNew.size(); if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); @@ -1122,6 +1126,9 @@ bool CrvModelEdgeOptim :: run() } else { objF->restoreInitialNodes(); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"size did not decrease"< numOfUniqueFaces(std::vector &ai) {1, 4, -1, 5}, {2, 3, 5, -1}}; + int edgeToFaceInd[6][2] = {{0, 1}, + {0, 2}, + {0, 3}, + {1, 3}, + {1, 2}, + {2, 3}}; + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) { for (std::size_t j = 0; j < aiOnlyFace.size(); j++) { if ((i != j) && (j > i)) { @@ -312,11 +319,14 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } } - + + /* for (size_t j = 0; j < aiOnlyFace.size(); j++) { - bool isUnique = false; + bool isUnique = false; for (int i = 0; i < 4; i++) { for (size_t k = 0; k < aiEdgeNVtx.size(); k++) { + if (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]) + aiUniqueFace.push_back(i+14); isUnique = isUnique || (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]); } } @@ -325,6 +335,25 @@ static std::vector numOfUniqueFaces(std::vector &ai) aiOnlyFace.erase(aiOnlyFace.begin()+j); } } +*/ + for (size_t j = 0; j < aiEdgeNVtx.size(); j++) { + bool alreadyIn = false; + if (aiEdgeNVtx[j] > 7 && aiEdgeNVtx[j] < 14) { + for (int i = 0; i < 2; i++) { + for (size_t k = 0; k < aiOnlyFace.size(); k++) { + alreadyIn = alreadyIn || (edgeToFaceInd[aiEdgeNVtx[j]-8][i] == aiOnlyFace[k]-14); + } + if (alreadyIn == false) { + aiOnlyFace.push_back(edgeToFaceInd[aiEdgeNVtx[j]-8][i] + 14); + } + } + } + } + + + for (size_t j = 0; j < aiOnlyFace.size(); j++) { + aiUniqueFace.push_back(aiOnlyFace[j]); + } ai.clear(); @@ -788,9 +817,7 @@ class EdgeReshaper : public ma::Operator { int tag = crv::getTag(adapter,e); - std::vector ai = crv::getAllInvalidities(mesh, e); - //ne = markEdges(mesh,e,tag,edges); - ne = markAllEdges(mesh, e, ai, edges); + ne = markEdges(mesh,e,tag,edges); simplex = e; return (ne > 0); } @@ -925,56 +952,57 @@ class FaceOptimizer : public ma::Operator FaceOptimizer(Adapt* a) { adapter = a; mesh = a->mesh; - face = 0; + faces[0] = faces[1] = faces[2] = faces[3] = 0; + simplex = 0; + md = mesh->getDimension(); + numf = 0; ns = 0; nf = 0; } ~FaceOptimizer() { } - virtual int getTargetDimension() {return 2;} + virtual int getTargetDimension() {return md;} virtual bool shouldApply(ma::Entity* e) { - - if (!ma::getFlag(adapter, e, ma::SNAP)) { - return false; - } - - if (isBoundaryEntity(mesh, e)) { - return false; - } - if (mesh->getModelType(mesh->toModel(e)) == 2) { - return false; - } - else { - face = e; - return true; + std::vector ai = crv::getAllInvalidities(mesh, e); + int niv = ai.size(); + mesh->getDownward(e, 2, faces); + if (niv != 0) { + numf = markUniqueFaces(mesh, e, ai, faces); + simplex = e; + return (numf > 0); } } virtual bool requestLocality(apf::CavityOp* o) { - return o->requestLocality(&face, 1); + return o->requestLocality(faces, numf); } virtual void apply(){ - if (mesh->getModelType(mesh->toModel(face)) == 3) { - CrvFaceOptim *cfo = new CrvFaceOptim(mesh, face); - cfo->setMaxIter(100); - cfo->setTol(1e-8); - - if (cfo->run()) ns++; - else nf++; + //mesh->getDownward(simplex, 2, faces); + for (int i = 0; i < numf; i++ ) { + if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { + CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i]); + cfo->setMaxIter(100); + cfo->setTol(1e-4); + + if (cfo->run()) ns++; + else nf++; - ma::clearFlag(adapter, face, ma::SNAP); - delete cfo; + delete cfo; + } } } private: protected: Adapt* adapter; ma::Mesh* mesh; - ma::Entity* face; public: + ma::Entity* faces[4]; + ma::Entity* simplex; + int numf; + int md; int ns; int nf; }; @@ -998,6 +1026,7 @@ class EdgeOptimizer : public ma::Operator virtual bool shouldApply(ma::Entity* e) { std::vector ai = crv::getAllInvalidities(mesh, e); + mesh->getDownward(e, 1, edges); int niv = ai.size(); if (niv != 0) { ne = markAllEdges(mesh, e, ai, edges); @@ -1013,16 +1042,18 @@ class EdgeOptimizer : public ma::Operator } virtual void apply() { - mesh->getDownward(simplex, 1, edges); + //mesh->getDownward(simplex, 1, edges); + int invaliditySize = 0; for (int i = 0; i < ne; i++ ) { if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edges[i], simplex); ceo->setMaxIter(100); ceo->setTol(1e-8); - if (ceo->run()) { + if (ceo->run(invaliditySize)) { ns++; - break; + if (invaliditySize < 1) + break; } else nf++; @@ -1034,9 +1065,10 @@ class EdgeOptimizer : public ma::Operator cmeo->setMaxIter(100); cmeo->setTol(1e-8); - if (cmeo->run()) { + if (cmeo->run(invaliditySize)) { ns++; - break; + if (invaliditySize < 1) + break; } else nf++; @@ -1398,19 +1430,19 @@ static void optimizeInvalidFaces(Adapt* a) int fixInvalidFaces(Adapt* a) { - int count = markFacesToFix(a, ma::SNAP); - if (! count) { - return 0; - } + //int count = markFacesToFix(a, ma::SNAP); + //if (! count) { + // return 0; + //} optimizeInvalidFaces(a); - return count; + return 0; } int fixInvalidEdges(Adapt* a) { - int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); + //int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); //if (! count){ // return 0; //} @@ -1422,7 +1454,7 @@ int fixInvalidEdges(Adapt* a) //collapseInvalidEdges(a); //swapInvalidEdges(a); - return count; + return 0; } From c334ad3df995b93be406658b390acc516d0170cc Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Tue, 12 Nov 2019 01:38:32 -0500 Subject: [PATCH 18/48] Debugging Day 6: New logic, commented out unused lines --- crv/crvCurveMesh.cc | 8 ++++---- crv/crvEdgeOptim.cc | 14 +++++++------- crv/crvModelEdgeOptim.cc | 14 +++++++------- crv/crvShape.cc | 25 ++++++++++++++----------- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index f347897ed..9ed2c98e4 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -187,8 +187,8 @@ bool BezierCurver::run(bool flag) apf::changeMeshShape(m_mesh, getBezier(m_order),true); } - writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_shape_change"); - writeCurvedWireFrame(m_mesh, 16, "mesh_after_shape_change"); + //writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_shape_change"); + //writeCurvedWireFrame(m_mesh, 16, "mesh_after_shape_change"); if (m_mesh->canSnap()){ for(int d = 1; d <= 2; ++d) @@ -198,8 +198,8 @@ bool BezierCurver::run(bool flag) convertInterpolatingToBezier(); - writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "mesh_after_inflate"); - writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); + writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "ant_mesh_after_inflate"); + writeCurvedWireFrame(m_mesh, 16, "ant_mesh_after_inflate"); if (flag == 1) { if(m_mesh->getDimension() >= 2) { diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 023546069..e7b1b22f9 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -870,8 +870,8 @@ bool CrvEdgeOptim :: run(int &invaliditySize) std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - printTetNumber(mesh, tet); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printTetNumber(mesh, tet); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); @@ -884,9 +884,9 @@ bool CrvEdgeOptim :: run(int &invaliditySize) for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); - int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge; ", edgeIndex); - printTetNumber(mesh, adjT[i]); + //int edgeIndex = apf::findIn(ed, 6, edge); + //printf("reshape tried on %d edge; ", edgeIndex); + //printTetNumber(mesh, adjT[i]); } if (l->run()) { @@ -899,13 +899,13 @@ bool CrvEdgeOptim :: run(int &invaliditySize) if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"Size DID NOT decrease"< ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - printTetNumber(mesh, tet); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printTetNumber(mesh, tet); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); @@ -1094,9 +1094,9 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); - int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge; ", edgeIndex); - printTetNumber(mesh, adjT[i]); + //int edgeIndex = apf::findIn(ed, 6, edge); + //printf("reshape tried on %d edge; ", edgeIndex); + //printTetNumber(mesh, adjT[i]); } if (l->run()) { @@ -1120,13 +1120,13 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + //printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"size did not decrease"< getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent return aa; } - +/* static void sortDes(std::vector &a) { for (std::size_t i = 0; i < a.size(); i++) { @@ -173,7 +173,7 @@ static void sortDes(std::vector &a) } } } - +*/ static void sortDesWrtFreqVector(std::vector &f, std::vector &a) { for (std::size_t i = 0; i < f.size(); i++) { @@ -216,7 +216,7 @@ static std::vector sortEdgeIndexByFrequency(std::vector &all) return unqEntries; } - +/* static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std::vector all) { apf::MeshEntity* ed[6]; @@ -267,7 +267,8 @@ static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std:: return b; } - +*/ +/* static int getCommonEdgeIndexToFaces(int a, int b) { int tb[4][4] = {{-1, 0, 1, 2}, @@ -276,7 +277,7 @@ static int getCommonEdgeIndexToFaces(int a, int b) {2, 3, 5, -1}}; return tb[a][b] + 2; } - +*/ // doess not account for TET(20) invalidity static std::vector numOfUniqueFaces(std::vector &ai) { @@ -337,9 +338,9 @@ static std::vector numOfUniqueFaces(std::vector &ai) } */ for (size_t j = 0; j < aiEdgeNVtx.size(); j++) { - bool alreadyIn = false; if (aiEdgeNVtx[j] > 7 && aiEdgeNVtx[j] < 14) { for (int i = 0; i < 2; i++) { + bool alreadyIn = false; for (size_t k = 0; k < aiOnlyFace.size(); k++) { alreadyIn = alreadyIn || (edgeToFaceInd[aiEdgeNVtx[j]-8][i] == aiOnlyFace[k]-14); } @@ -365,8 +366,8 @@ static std::vector numOfUniqueFaces(std::vector &ai) forFaceMarking.push_back(aiUniqueFace.size()); for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) ai.push_back(aiEdgeNVtx[i]); - for (std::size_t i = 0; i < aiOnlyFace.size(); i++) - ai.push_back(aiOnlyFace[i]); + //for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + // ai.push_back(aiOnlyFace[i]); for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { forFaceMarking.push_back(aiUniqueFace[i]); } @@ -388,6 +389,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) return forFaceMarking; } +/* static std::vector inspectInvalidies(std::vector ai) { std::vector aimod; @@ -406,6 +408,7 @@ static std::vector inspectInvalidies(std::vector ai) else return ai; } +*/ static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* edges[6]) @@ -507,7 +510,6 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, m->getDownward(e,1,ed); n = md; - //std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); if(md == 2){ edges[0] = ed[index]; edges[1] = ed[(index+2) % 3]; @@ -632,7 +634,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, } } } - +/* if (faceInvalid.size() > 1+faceInvalid[0]) { int kkk = faceInvalid.size()-faceInvalid[0]-1; int kk = kkk/3; @@ -663,6 +665,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, } } } + */ return n; @@ -985,7 +988,7 @@ class FaceOptimizer : public ma::Operator if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i]); cfo->setMaxIter(100); - cfo->setTol(1e-4); + cfo->setTol(1e-8); if (cfo->run()) ns++; else nf++; From 6a83b761a97fa07b58fc4b303e938b5f09a06fba Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Tue, 12 Nov 2019 15:13:27 -0500 Subject: [PATCH 19/48] Debugging Day 7 --- crv/crvCurveMesh.cc | 4 ++-- crv/crvEdgeOptim.cc | 14 +++++++------- crv/crvModelEdgeOptim.cc | 14 +++++++------- crv/crvShape.cc | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 9ed2c98e4..6be389fa3 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -198,8 +198,8 @@ bool BezierCurver::run(bool flag) convertInterpolatingToBezier(); - writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "ant_mesh_after_inflate"); - writeCurvedWireFrame(m_mesh, 16, "ant_mesh_after_inflate"); + writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "mesh_after_inflate"); + writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); if (flag == 1) { if(m_mesh->getDimension() >= 2) { diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index e7b1b22f9..023546069 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -870,8 +870,8 @@ bool CrvEdgeOptim :: run(int &invaliditySize) std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - //printTetNumber(mesh, tet); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printTetNumber(mesh, tet); + printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); @@ -884,9 +884,9 @@ bool CrvEdgeOptim :: run(int &invaliditySize) for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); - //int edgeIndex = apf::findIn(ed, 6, edge); - //printf("reshape tried on %d edge; ", edgeIndex); - //printTetNumber(mesh, adjT[i]); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d edge; ", edgeIndex); + printTetNumber(mesh, adjT[i]); } if (l->run()) { @@ -899,13 +899,13 @@ bool CrvEdgeOptim :: run(int &invaliditySize) if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<restoreInitialNodes(); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"Size DID NOT decrease"< ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - //printTetNumber(mesh, tet); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printTetNumber(mesh, tet); + printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); @@ -1094,9 +1094,9 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) for (std::size_t i = 0; i < adjT.getSize(); i++) { mesh->getDownward(adjT[i], 1, ed); - //int edgeIndex = apf::findIn(ed, 6, edge); - //printf("reshape tried on %d edge; ", edgeIndex); - //printTetNumber(mesh, adjT[i]); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d edge; ", edgeIndex); + printTetNumber(mesh, adjT[i]); } if (l->run()) { @@ -1120,13 +1120,13 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) if (aiNew.size() < ai.size()) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<restoreInitialNodes(); - //printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"size did not decrease"< numOfUniqueFaces(std::vector &ai) forFaceMarking.push_back(aiUniqueFace.size()); for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) ai.push_back(aiEdgeNVtx[i]); - //for (std::size_t i = 0; i < aiOnlyFace.size(); i++) - // ai.push_back(aiOnlyFace[i]); + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + ai.push_back(aiOnlyFace[i]); for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { forFaceMarking.push_back(aiUniqueFace[i]); } From 52faaa2626c4ea6162db85f046521a3d752beaf0 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Wed, 13 Nov 2019 11:52:13 -0500 Subject: [PATCH 20/48] Debugging Day 8 --- crv/crvEdgeOptim.cc | 43 ++-- crv/crvFaceOptim.cc | 415 +++++++++++++++++++++++++++++++++++++-- crv/crvFaceOptim.h | 14 +- crv/crvModelEdgeOptim.cc | 34 ++-- crv/crvShape.cc | 8 +- 5 files changed, 445 insertions(+), 69 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 023546069..4d72da254 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -860,11 +860,14 @@ void CrvEdgeOptim :: setTol(double tolerance) bool CrvEdgeOptim :: run(int &invaliditySize) { + std::vector sizeHolder; apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(edge, 3, adj); for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + sizeHolder.push_back(ai.size()); } std::vector ai = crv::getAllInvalidities(mesh, tet); @@ -878,25 +881,30 @@ bool CrvEdgeOptim :: run(int &invaliditySize) //std::cout<< "fval at x0 " << f0<getAdjacent(edge, 3, adjT); apf::MeshEntity* ed[6]; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - mesh->getDownward(adjT[i], 1, ed); + for (std::size_t i = 0; i < adj.getSize(); i++) { + mesh->getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); printf("reshape tried on %d edge; ", edgeIndex); - printTetNumber(mesh, adjT[i]); + printTetNumber(mesh, adj[i]); } + bool hasDecreased = false; + if (l->run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - - std::vector aiNew = crv::getAllInvalidities(mesh, tet); - invaliditySize = aiNew.size(); - if (aiNew.size() < ai.size()) { + + + for (int i = 0; i < adj.getSize(); i++) { + std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + } + + if (hasDecreased == false) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); @@ -910,23 +918,6 @@ bool CrvEdgeOptim :: run(int &invaliditySize) std::cout<<"--------------------------------------"<getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - if (checkValidity(mesh, adjT[i], 1) > 1) { - objF->restoreInitialNodes(); - std::cout<<"invalid entity after edop with code "<currentX; diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc index 2580501e5..b311672bb 100644 --- a/crv/crvFaceOptim.cc +++ b/crv/crvFaceOptim.cc @@ -6,6 +6,351 @@ #include "crvMath.h" #include #include "apfMatrix.h" +#include "apfNumbering.h" +#include "gmi.h" +#include "apfMDS.h" + +static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::Numbering* n = m->findNumbering("debug_num_tet"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, e, 0, 0); + std::cout<<" TET:: "<< num <findNumbering("debug_num_face"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, face, 0, 0); + std::cout<<"at face "<< num << std::endl; + for (int i = 0; i < nat; i++) { + std::vector ai = crv::getAllInvalidities(m, e[i]); + for (std::size_t j = 0; j < ai.size(); j++) { + printf("%d ", ai[j]); + } + printf("\n"); + } +} + +static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, const char* prefix, int nat) +{ + apf::Numbering* n = m->findNumbering("debug_num_face"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, face, 0, 0); + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); + + apf::MeshEntity* newEnt[99]; + + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); + //printf("HERE 02\n")liver tetrahedral element + outMesh->acceptChanges(); + } + apf::changeMeshShape(outMesh, crv::getBezier(3), true); + outMesh->acceptChanges(); + + for (int ii = 0; ii < nat; ii++) { + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh->getDownward(newEnt[ii], d, new_eds); + int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh->setPoint(new_eds[n], i, p); + } + } + } + outMesh->acceptChanges(); + } + + std::stringstream ss; + ss << prefix<< num; + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); + + outMesh->destroyNative(); + apf::destroyMesh(outMesh); +} + +static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) +{ + int dim = 0; + if (m->getType(e) == apf::Mesh::TRIANGLE) { + std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[4]; + for (int i = 0; i < 4; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); + } + + apf::MeshEntity* face[4]; + apf::MeshEntity* newface[4]; + int nf = m->getDownward(e, 2, face); + for (int i = 0; i < nf; i++) { + + //Verts + apf::MeshEntity* vs[3]; + apf::MeshEntity* newVs[3]; + int nv = m->getDownward(face[i], 0, vs); + for (int j = 0; j < nv; j++) { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[j], 0, p); + newVs[j] = outMesh[i]->createVertex(0, p, param); + } + outMesh[i]->acceptChanges(); + + //Edges + apf::MeshEntity* es[3]; + apf::MeshEntity* newEs[3]; + int ne = m->getDownward(face[i], 1, es); + for (int j = 0; j < ne; j++) { + apf::MeshEntity* evs[2]; + apf::MeshEntity* newEvs[2]; + m->getDownward(es[j], 0, evs); + for (int k = 0; k < 2; k++) { + int kk = apf::findIn(vs,nv, evs[k]); + newEvs[k] = newVs[kk]; + } + + newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); + } + + //Faces + apf::MeshEntity* fes[3]; + apf::MeshEntity* newFes[3]; + m->getDownward(face[i], 1, fes); + for (int j = 0; j < 3; j++) + newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; + + newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); + + PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); + outMesh[i]->acceptChanges(); + + apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); + outMesh[i]->acceptChanges(); + + for (int d = 1; d < dim; d++) { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* ent[10]; + int counter = m->getDownward(face[i], d, ent); + apf::MeshEntity* newent[10]; + outMesh[i]->getDownward(newface[i], d, newent); + int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for (int n = 0; n < counter; n++) { + for (int j = 0; j < non; j++) { + apf::Vector3 p; + m->getPoint(ent[n], j, p); + outMesh[i]->setPoint(newent[n], j, p); + } + } + } + + outMesh[i]->acceptChanges(); + + std::stringstream ss; + ss << prefix << "_Face_"<< i; + crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); + } +} + +static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, const char* prefix, int nat) +{ + apf::Numbering* n = m->findNumbering("debug_num_face"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, face, 0, 0); + int dim = 0; + if (m->getType(e[0]) == apf::Mesh::TRIANGLE) + dim = 2; + else if (m->getType(e[0]) == apf::Mesh::TET) + dim = 3; + else + PCU_ALWAYS_ASSERT(0); + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[nat]; + for (int i = 0; i < nat; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); + } + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh[ii]->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); + } + + if (dim == 2) + newEnt[ii] = newFs[0]; + else + newEnt[ii] = tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); + outMesh[ii]->acceptChanges(); + + apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); + outMesh[ii]->acceptChanges(); + + + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh[ii]->getDownward(newEnt[ii], d, new_eds); + int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh[ii]->setPoint(new_eds[n], i, p); + } + } + } + outMesh[ii]->acceptChanges(); + + std::stringstream ss; + ss << prefix<< num << "_TET_"<destroyNative(); + //apf::destroyMesh(outMesh[ii]); + + visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); + } +} + + + namespace crv{ @@ -304,38 +649,76 @@ void CrvFaceOptim :: setMaxIter(int n) iter = n; } -void CrvFaceOptim :: setTol(double t) +void CrvFaceOptim :: setTol(double tolerance) { - tol = t; + tol = tolerance; } -bool CrvFaceOptim :: run() +bool CrvFaceOptim :: run(bool &hasDecreased) { - CrvFaceReshapeObjFunc *objF = new CrvFaceReshapeObjFunc(mesh, face); + std::vector sizeHolder; + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(face, 3, adj); + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + sizeHolder.push_back(ai.size()); + } + + //std::vector ai = crv::getAllInvalidities(mesh, tet); + //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); + printTetNumber(mesh, tet); + printInvalidities(mesh, adj_array, face, adj.getSize()); + CrvFaceReshapeObjFunc *objF = new CrvFaceReshapeObjFunc(mesh, face, tet); std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0<getAdjacent(face, 3, adjT); + apf::MeshEntity* fc[4]; + + for (std::size_t i = 0; i < adjT.getSize(); i++) { + mesh->getDownward(adjT[i], 2, fc); + int faceIndex = apf::findIn(fc, 4, face); + printf("reshape tried on %d face; ",faceIndex); + printTetNumber(mesh, adjT[i]); + } + if (l->run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - /* - apf::Adjacent adjT; - mesh->getAdjacent(face, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - if (checkValidity(mesh, adjT[i], 1) > 1) { - objF->restoreInitialNodes(); - std::cout<<"invalid entity after fop with code--- "< aiNew = crv::getAllInvalidities(mesh, adj[i]); + //invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } -*/ - return true; + + if (hasDecreased == false || hasDecreased == true) { + // makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); + // makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); + printInvalidities(mesh, adj_array, face, adj.getSize()); + std::cout<<"----------------------------------------------------"<restoreInitialNodes(); + printInvalidities(mesh, adj_array, face, adj.getSize()); + std::cout<<"Size didNOT decrease"<getShape()->getOrder(); d = mesh->getDimension(); @@ -49,6 +49,7 @@ class CrvFaceReshapeObjFunc : public ObjFunction protected: apf::Mesh2* mesh; apf::MeshEntity* face; + apf::MeshEntity* tet; std::vector vol; std::vector ifn; std::vector itn; @@ -57,17 +58,18 @@ class CrvFaceReshapeObjFunc : public ObjFunction class CrvFaceOptim { public: - CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f) : - mesh(m), face(f) {} + CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : + mesh(m), face(f), tet(t) {} ~CrvFaceOptim(){} public: void setMaxIter(int n); - void setTol(double t); - bool run(); + void setTol(double tolerance); + bool run(bool &hasDecreased); public: apf::Mesh2* mesh; apf::MeshEntity* face; + apf::MeshEntity* tet; int iter; double tol; std::vector finalX; diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 2f60d36b0..bd06babe5 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -1068,6 +1068,7 @@ void CrvModelEdgeOptim :: setTol(double tolerance) bool CrvModelEdgeOptim :: run(int &invaliditySize) { + std::vector sizeHolder; apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(edge, 3, adj); @@ -1075,9 +1076,11 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + sizeHolder.push_back(ai.size()); } - std::vector ai = crv::getAllInvalidities(mesh,tet); + //std::vector ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printTetNumber(mesh, tet); @@ -1088,36 +1091,29 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0<getAdjacent(edge, 3, adjT); apf::MeshEntity* ed[6]; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - mesh->getDownward(adjT[i], 1, ed); + for (std::size_t i = 0; i < adj.getSize(); i++) { + mesh->getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); printf("reshape tried on %d edge; ", edgeIndex); - printTetNumber(mesh, adjT[i]); + printTetNumber(mesh, adj[i]); } + bool hasDecreased = false; + if (l->run()) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - /* - apf::Adjacent adjT; - mesh->getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - if (checkValidity(mesh, adjT[i], 2) > 1) { - objF->restoreInitialNodes(); -// std::cout<<"invalid entity after edop with code "< aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } -*/ - std::vector aiNew = crv::getAllInvalidities(mesh,tet); - invaliditySize = aiNew.size(); - if (aiNew.size() < ai.size()) { + + if (hasDecreased == false) { //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 49d5db843..36d0e5ca0 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -983,14 +983,18 @@ class FaceOptimizer : public ma::Operator } virtual void apply(){ + bool hasDecreased = false; //mesh->getDownward(simplex, 2, faces); for (int i = 0; i < numf; i++ ) { if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { - CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i]); + CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i], simplex); cfo->setMaxIter(100); cfo->setTol(1e-8); - if (cfo->run()) ns++; + if (cfo->run(hasDecreased)) { + if (hasDecreased == false) + ns++; + } else nf++; delete cfo; From 1129dfab183c76720dbb2ea91573fc01280658b2 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Fri, 15 Nov 2019 11:36:59 -0500 Subject: [PATCH 21/48] try face before edge reshape --- crv/LBFGS.cc | 1 - crv/crvEdgeOptim.cc | 28 ++++++++--- crv/crvFaceOptim.cc | 26 +++++----- crv/crvFaceOptim.h | 2 +- crv/crvModelEdgeOptim.cc | 16 ++++-- crv/crvShape.cc | 102 +++++++++++++++++++++++++++++++-------- 6 files changed, 130 insertions(+), 45 deletions(-) diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc index 70a47071d..84f13006f 100644 --- a/crv/LBFGS.cc +++ b/crv/LBFGS.cc @@ -148,7 +148,6 @@ bool LBFGS::run() return true; } - currentX = xs[I]; for (std::size_t j = 0; j < xs[I].size(); j++) p[j] = -gs[I][j]; for (int i = I-1; i >= 0; --i) { diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 4d72da254..75bd30571 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -606,9 +606,9 @@ double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 14; + weight = 6; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 4; + weight = 3; else weight = 1; if (I + J + K + L == d*(P-1)) { @@ -725,8 +725,9 @@ restoreInitialNodes(); } apf::destroyElement(Edl); - */ +*/ /* + apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); apf::NewArray fCP; @@ -776,11 +777,13 @@ restoreInitialNodes(); //std::cout<<"sum and ratio------ "<< sum <<" "<getAdjacent(edge, 3, adj); + int thisTetSize = 0; + for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + if (adj[i] == tet) thisTetSize = ai.size(); sizeHolder.push_back(ai.size()); + } std::vector ai = crv::getAllInvalidities(mesh, tet); @@ -891,8 +898,9 @@ bool CrvEdgeOptim :: run(int &invaliditySize) } bool hasDecreased = false; + invaliditySize = 0; - if (l->run()) { + if (l->run() && thisTetSize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); @@ -904,7 +912,8 @@ bool CrvEdgeOptim :: run(int &invaliditySize) hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } - if (hasDecreased == false) { + if (hasDecreased == false ) { + //invaliditySize = 0; //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); @@ -923,6 +932,11 @@ bool CrvEdgeOptim :: run(int &invaliditySize) //finalX = l->currentX; //objF->setNodes(finalX); //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + if (thisTetSize == 0) { + std::cout<<" No Optimization tried"< for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; + weight = 6; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 2; + weight = 3; else weight = 1; if (I + J + K + L == d*(P-1)) { @@ -654,7 +654,7 @@ void CrvFaceOptim :: setTol(double tolerance) tol = tolerance; } -bool CrvFaceOptim :: run(bool &hasDecreased) +bool CrvFaceOptim :: run(int &invaliditySize) { std::vector sizeHolder; apf::MeshEntity* adj_array[99]; @@ -662,11 +662,12 @@ bool CrvFaceOptim :: run(bool &hasDecreased) mesh->getAdjacent(face, 3, adj); for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; - std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - sizeHolder.push_back(ai.size()); + //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + //sizeHolder.push_back(ai.size()); } - //std::vector ai = crv::getAllInvalidities(mesh, tet); + std::vector ai = crv::getAllInvalidities(mesh, tet); + invaliditySize = ai.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); printTetNumber(mesh, tet); @@ -693,16 +694,20 @@ bool CrvFaceOptim :: run(bool &hasDecreased) fval = l->fValAfter; objF->setNodes(finalX); + std::vector aiNew = crv::getAllInvalidities(mesh, tet); +/* for (int i = 0; i < adjT.getSize(); i++) { std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); //invaliditySize = invaliditySize + aiNew.size(); hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } - - if (hasDecreased == false || hasDecreased == true) { - // makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); - // makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); +*/ + // if (hasDecreased == false || hasDecreased == true) { + if (aiNew.size() <= invaliditySize) { + invaliditySize = aiNew.size(); + //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); printInvalidities(mesh, adj_array, face, adj.getSize()); std::cout<<"----------------------------------------------------"<getAdjacent(edge, 3, adj); int cInvT = 0; + int thisTetSize = 0; for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + if (adj[i] == tet) thisTetSize = ai.size(); sizeHolder.push_back(ai.size()); } @@ -1101,8 +1103,9 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) } bool hasDecreased = false; + invaliditySize = 0; - if (l->run()) { + if (l->run() && thisTetSize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); @@ -1131,8 +1134,13 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) else { //finalX = l->currentX; //objF->setNodes(finalX); - + if (thisTetSize == 0) { + std::cout<<"No Optimization tried"< numOfUniqueFaces(std::vector &ai) { std::vector aiEdgeNVtx; std::vector aiOnlyFace; + std::vector aiOnlyEdge; + std::vector aiOnlyVtx; + std::vector aiOnlyTet; + std::vector aiUniqueFace; std::vector FFE; for (size_t i = 0; i < ai.size(); i++) { + if (ai[i] < 8) aiOnlyVtx.push_back(ai[i]); + else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); + else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); + else aiOnlyTet.push_back(ai[i]); +/* if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); else aiEdgeNVtx.push_back(ai[i]); + */ } int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, @@ -305,12 +315,19 @@ static std::vector numOfUniqueFaces(std::vector &ai) {1, 2}, {2, 3}}; + int edgeToVtx[6][2] = {{0, 1}, + {1, 2}, + {0, 2}, + {0, 3}, + {1, 3}, + {2, 3}}; + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) { for (std::size_t j = 0; j < aiOnlyFace.size(); j++) { if ((i != j) && (j > i)) { - for (std::size_t k = 0; k < aiEdgeNVtx.size(); k++) { - if (faceToEdgeInd[aiOnlyFace[i]-14][aiOnlyFace[j]-14] + 8 == aiEdgeNVtx[k]) { - FFE.push_back(aiEdgeNVtx[k]); + for (std::size_t k = 0; k < aiOnlyEdge.size(); k++) { + if (faceToEdgeInd[aiOnlyFace[i]-14][aiOnlyFace[j]-14] + 8 == aiOnlyEdge[k]) { + FFE.push_back(aiOnlyEdge[k]); FFE.push_back(aiOnlyFace[j]); FFE.push_back(aiOnlyFace[i]); break; @@ -337,21 +354,40 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } */ - for (size_t j = 0; j < aiEdgeNVtx.size(); j++) { - if (aiEdgeNVtx[j] > 7 && aiEdgeNVtx[j] < 14) { + + bool hasDownVtx, alreadyIn; + + for (size_t j = 0; j < aiOnlyEdge.size(); j++) { + hasDownVtx = false; + for (int jj = 0; jj < 2; jj++) { + //hasDownVtx = false; + for (size_t ii = 0; ii < aiOnlyVtx.size(); ii++) { + hasDownVtx = hasDownVtx || (edgeToVtx[aiOnlyEdge[j]-8][jj] == aiOnlyVtx[ii] - 2); + } + } + + if (hasDownVtx == false) { for (int i = 0; i < 2; i++) { - bool alreadyIn = false; + alreadyIn = false; for (size_t k = 0; k < aiOnlyFace.size(); k++) { - alreadyIn = alreadyIn || (edgeToFaceInd[aiEdgeNVtx[j]-8][i] == aiOnlyFace[k]-14); + alreadyIn = alreadyIn || (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14); } if (alreadyIn == false) { - aiOnlyFace.push_back(edgeToFaceInd[aiEdgeNVtx[j]-8][i] + 14); + aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); + } + } + } + else { + for (int i = 0; i < 2; i++) { + for (size_t k = 0; k < aiOnlyFace.size(); k++) { + if (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14) { + aiOnlyFace.erase(aiOnlyFace.begin()+k); + } } } } } - for (size_t j = 0; j < aiOnlyFace.size(); j++) { aiUniqueFace.push_back(aiOnlyFace[j]); } @@ -364,10 +400,14 @@ static std::vector numOfUniqueFaces(std::vector &ai) if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { forFaceMarking.push_back(aiUniqueFace.size()); - for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) - ai.push_back(aiEdgeNVtx[i]); + for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) + ai.push_back(aiOnlyVtx[i]); + for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) + ai.push_back(aiOnlyEdge[i]); for (std::size_t i = 0; i < aiOnlyFace.size(); i++) ai.push_back(aiOnlyFace[i]); + for (std::size_t i = 0; i < aiOnlyTet.size(); i++) + ai.push_back(aiOnlyTet[i]); for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { forFaceMarking.push_back(aiUniqueFace[i]); } @@ -381,8 +421,10 @@ static std::vector numOfUniqueFaces(std::vector &ai) for (std::size_t i = 0; i < FFE.size(); i++) forFaceMarking.push_back(FFE[i]); } - for (std::size_t i = 0; i < aiEdgeNVtx.size(); i++) - ai.push_back(aiEdgeNVtx[i]); + for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) + ai.push_back(aiOnlyVtx[i]); + for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) + ai.push_back(aiOnlyEdge[i]); for (std::size_t i = 0; i < aiOnlyFace.size(); i++) ai.push_back(aiOnlyFace[i]); } @@ -983,7 +1025,7 @@ class FaceOptimizer : public ma::Operator } virtual void apply(){ - bool hasDecreased = false; + int invaliditySize = 0; //mesh->getDownward(simplex, 2, faces); for (int i = 0; i < numf; i++ ) { if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { @@ -991,11 +1033,18 @@ class FaceOptimizer : public ma::Operator cfo->setMaxIter(100); cfo->setTol(1e-8); - if (cfo->run(hasDecreased)) { - if (hasDecreased == false) + if (cfo->run(invaliditySize)) { + if (invaliditySize < 1) { ns++; + break; + } + } + else { + if (invaliditySize < 1) { + break; + } + nf++; } - else nf++; delete cfo; } @@ -1050,8 +1099,8 @@ class EdgeOptimizer : public ma::Operator virtual void apply() { //mesh->getDownward(simplex, 1, edges); - int invaliditySize = 0; for (int i = 0; i < ne; i++ ) { + int invaliditySize = 0; if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edges[i], simplex); ceo->setMaxIter(100); @@ -1062,14 +1111,20 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) break; } - else nf++; + else { + if (invaliditySize < 1) { + break; + } + nf++; + } + delete ceo; //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); } else if (mesh->getModelType(mesh->toModel(edges[i])) == 2) { CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edges[i], simplex); - cmeo->setMaxIter(100); + cmeo->setMaxIter(200); cmeo->setTol(1e-8); if (cmeo->run(invaliditySize)) { @@ -1077,7 +1132,12 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) break; } - else nf++; + else { + if (invaliditySize < 1) { + break; + } + nf++; + } //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); delete cmeo; From e84d91c95cdff225b648c67081bfcecb18a6c010 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 16 Nov 2019 12:13:39 -0500 Subject: [PATCH 22/48] Without constraining face nodes on model surface --- crv/crvEdgeOptim.cc | 4 ++-- crv/crvModelEdgeOptim.cc | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 75bd30571..9b6e7104b 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -606,9 +606,9 @@ double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray for (int K = 0; K <= d*(P-1); K++) { for (int L = 0; L <= d*(P-1); L++) { if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 6; + weight = 4; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 3; + weight = 2; else weight = 1; if (I + J + K + L == d*(P-1)) { diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 24ac919ee..6ba57f047 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -442,12 +442,12 @@ std::vector CrvModelEdgeReshapeObjFunc :: getParamCoords() std::vector xp; int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < numENodes; i++) { getBezierNodeXi(mesh->getType(edge), P, i, xi); transferParametricOnEdgeSplit(mesh, edge, 0.5*(xi[0]+1.0), param); - for (int j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) { xp.push_back(param[j]); + } } apf::Vector3 xif; @@ -460,8 +460,9 @@ std::vector CrvModelEdgeReshapeObjFunc :: getParamCoords() for (int j = 0; j < numFNodes; j++) { getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); transferParametricOnTriSplit(mesh, adjF[i], xif, paramf); - for (int k = 0; k < 3; k++) + for (int k = 0; k < 3; k++) { xp.push_back(paramf[k]); + } } } else { @@ -473,7 +474,7 @@ std::vector CrvModelEdgeReshapeObjFunc :: getParamCoords() } } } - + return xp; } @@ -483,7 +484,6 @@ std::vector CrvModelEdgeReshapeObjFunc :: convertParamCoordsToNode std::vector edn; std::vector vn = convertXtoNodeVector(x); int nENodes = mesh->getShape()->countNodesOn(mesh->EDGE); - for (int i = 0; i < nENodes; i++) { apf::Vector3 coorde; mesh->snapToModel(me, vn[i], coorde); @@ -817,9 +817,9 @@ double CrvModelEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &x) sum = sum + computeFValOfElement(allNodes, vol[i]); apf::destroyElement(el); } - +/* apf::NewArray eCP; apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); apf::getVectorNodes(Edl, eCP); @@ -995,8 +995,8 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) } } - sum = sum*(1 + beta + 0.3*gamma); - + //sum = sum*(1 + beta + 0.3*gamma); +*/ restoreInitialNodes(); } return sum; @@ -1090,6 +1090,8 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); + + //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< Date: Sun, 17 Nov 2019 17:54:06 -0500 Subject: [PATCH 23/48] rewrote edge distribution criterion --- crv/crvModelEdgeOptim.cc | 138 +++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 49 deletions(-) diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 6ba57f047..50b75a00d 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -886,62 +886,101 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) sum = sum + computeFValOfElement(allNodes, vol[i]); apf::destroyElement(el); } -/* - apf::NewArray eCP; - apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); - apf::getVectorNodes(Edl, eCP); - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + + /* apf::NewArray eCP; */ + /* apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); */ + /* apf::getVectorNodes(Edl, eCP); */ + /* int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); */ + /* double xr = 1.0; */ + /* double xir = 1.0; */ + /* //double alpha = 1.0; */ + /* double ad = 0.0; */ + /* apf::Vector3 x1, x0; */ + /* apf::Vector3 xi2, xi1, xi0; */ + /* double beta = 0.0; */ + + /* apf::MeshElement* mEdl = apf::createMeshElement(mesh, edge); */ + /* for (int i = 0; i getType(edge), P, i, xi1); */ + /* apf::mapLocalToGlobal(mEdl, xi1, scord); */ + /* eCP[2+i] = scord; */ + /* } */ + /* apf::destroyMeshElement(mEdl); */ + + double ad = 0.0; double xr = 1.0; double xir = 1.0; - //double alpha = 1.0; - double ad = 0.0; - apf::Vector3 x1, x0; - apf::Vector3 xi2, xi1, xi0; + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); double beta = 0.0; - - apf::MeshElement* mEdl = apf::createMeshElement(mesh, edge); + std::vector xs; + xs.clear(); + std::vector xis; + xis.clear(); + xis.push_back(apf::Vector3(-1.0, 0.0, 0.0)); for (int i = 0; i getType(edge), P, i, xi1); - apf::mapLocalToGlobal(mEdl, xi1, scord); - eCP[2+i] = scord; + apf::Vector3 currentXi; + getBezierNodeXi(mesh->getType(edge), P, i, currentXi); + xis.push_back(currentXi); } - apf::destroyMeshElement(mEdl); - - for (int i = 0; i < nEN; i++) { - getBezierNodeXi(mesh->getType(edge), P, i, xi1); - if (i > 0 && i < nEN - 1) { - getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); - getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); - x1 = eCP[2+i+1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[2+i-1]; - xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); - } - else if ( i == 0) { - getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); - x1 = eCP[2+i+1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[0]; - xir = (xi2[0] - xi1[0])/(xi1[0] + 1.0); // parent coordinate[-1,1] - } - else { - getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); - x1 = eCP[1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[2+i-1]; - xir = (1.0 - xi1[0])/(xi1[0] - xi0[0]); - } - - //if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) - // alpha = 0.5*(xi1[0]+1.0); - //else - // alpha = 1.0 - 0.5*(xi1[0]+1.0); + xis.push_back(apf::Vector3(+1.0, 0.0, 0.0)); - xr = (x1.getLength()/x0.getLength()); + apf::MeshElement* me = apf::createMeshElement(mesh, edge); + for (int i = 0; i < xis.size(); i++) { + apf::Vector3 scord; + apf::mapLocalToGlobal(me, xis[i], scord); + xs.push_back(scord); + } + apf::destroyMeshElement(me); + + + + /* for (int i = 0; i < nEN; i++) { */ + /* getBezierNodeXi(mesh->getType(edge), P, i, xi1); */ + /* if (i > 0 && i < nEN - 1) { */ + /* getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); */ + /* getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); */ + /* x1 = eCP[2+i+1] - eCP[2+i]; */ + /* x0 = eCP[2+i] - eCP[2+i-1]; */ + /* xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); */ + /* } */ + /* else if ( i == 0) { */ + /* getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); */ + /* x1 = eCP[2+i+1] - eCP[2+i]; */ + /* x0 = eCP[2+i] - eCP[0]; */ + /* xir = (xi2[0] - xi1[0])/(xi1[0] + 1.0); // parent coordinate[-1,1] */ + /* } */ + /* else { */ + /* getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); */ + /* x1 = eCP[1] - eCP[2+i]; */ + /* x0 = eCP[2+i] - eCP[2+i-1]; */ + /* xir = (1.0 - xi1[0])/(xi1[0] - xi0[0]); */ + /* } */ + + /* //if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) */ + /* // alpha = 0.5*(xi1[0]+1.0); */ + /* //else */ + /* // alpha = 1.0 - 0.5*(xi1[0]+1.0); */ + + /* xr = (x1.getLength()/x0.getLength()); */ + /* ad = (1.0*xr/xir - 1.0); //(alpha*alpha); */ + /* beta = beta + ad*ad; */ + /* //sum = sum + ad*ad; */ + /* } */ + + for (int i = 1; i < xs.size()-1; i++) { + + xr = (xs[i] - xs[0]).getLength() / + (xs[xs.size()-1] - xs[0]).getLength(); + xir = (xis[i] - xis[0]).getLength() / + (xis[xs.size()-1] - xis[0]).getLength(); ad = (1.0*xr/xir - 1.0); //(alpha*alpha); beta = beta + ad*ad; //sum = sum + ad*ad; } + //sum = sum*(1 + beta); - apf::destroyElement(Edl); + /* apf::destroyElement(Edl); */ apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); @@ -972,8 +1011,8 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) double triAphys = getAr(fCP[0], fCP[1], fCP[2]); apf::Vector3 prt0 = {0, 0, 0}; - apf::Vector3 prt1 = {0, 1, 0}; - apf::Vector3 prt2 = {0, 0, 1}; + apf::Vector3 prt1 = {1, 0, 0}; + apf::Vector3 prt2 = {0, 1, 0}; double triAparnt = getAr(prt0, prt1, prt2); for (int j = 0; j < nFN; j++) { @@ -995,8 +1034,9 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) } } - //sum = sum*(1 + beta + 0.3*gamma); -*/ + /* double gamma = 0.0; */ + sum = sum*(1 + beta + 0.3*gamma); + restoreInitialNodes(); } return sum; From f3825587e589e8d0b9d6c7da5923aaee421d438c Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sun, 17 Nov 2019 20:47:50 -0500 Subject: [PATCH 24/48] Debugging -changed Edge and Face Node Distribution evaluation --- crv/crvModelEdgeOptim.cc | 63 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 50b75a00d..a3b9dafe2 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -984,6 +984,67 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); + + std::vector xfs; + std::vector xifs; + double arPhys[3] = {1.0, 1.0, 1.0}; + double arParnt[3] = {1.0, 1.0, 1.0}; + double adf; + double gamma = 0.0; + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + xfs.clear(); + xifs.clear(); + adf = 0.0; + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + apf::Vector3 faceXi; + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, faceXi); + xifs.push_back(faceXi); + } + xifs.push_back(apf::Vector3(0.0, 0.0, 0.0)); + xifs.push_back(apf::Vector3(1.0, 0.0, 0.0)); + xifs.push_back(apf::Vector3(0.0, 1.0, 0.0)); + + apf::MeshElement* mef = apf::createMeshElement(mesh, adjF[i]); + for (size_t k = 0; k < xifs.size(); k++) { + apf::Vector3 fcord; + apf::mapLocalToGlobal(mef, xifs[k], fcord); + xfs.push_back(fcord); + } + apf::destroyMeshElement(mef); + + double triPhys = getAr(xfs[xifs.size()-1], xfs[xifs.size()-2], xfs[xifs.size()-3]); + double triParnt = getAr(xifs[xifs.size()-1], xifs[xifs.size()-2], xifs[xifs.size()-3]); + + for (int j = 0; j < nFN; j++) { + /* + arPhys[0] = getAr(xfs[j], xfs[xifs.size()-1], xfs[xifs.size()-2]); + arParnt[0] = getAr(xifs[j], xifs[xifs.size()-1], xifs[xifs.size()-2]); + + arPhys[1] = getAr(xfs[j], xfs[xifs.size()-2], xfs[xifs.size()-3]); + arParnt[1] = getAr(xifs[j], xifs[xifs.size()-2], xifs[xifs.size()-3]); + + arPhys[2] = getAr(xfs[j], xfs[xifs.size()-1], xfs[xifs.size()-3]); + arParnt[2] = getAr(xifs[j], xifs[xifs.size()-1], xifs[xifs.size()-3]); + */ + for (int k = 0; k < 2; k++) { + arPhys[k] = getAr(xfs[j], xfs[xifs.size()-(3-k)], xfs[xifs.size()-(2-k)]); + arParnt[k] = getAr(xifs[j], xifs[xifs.size()-(3-k)], xifs[xifs.size()-(2-k)]); + adf = (1.0*arPhys[k]*triParnt/(arParnt[k]*triPhys) - 1); + gamma = gamma + adf*adf; + } + } + } + } + + +/* + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + apf::NewArray fCP; apf::Vector3 xif; double a[3] = {1.0, 1.0, 1.0}; @@ -1033,7 +1094,7 @@ double CrvModelEdgeReshapeObjFunc :: getValue(std::vector &x) apf::destroyElement(Fal); } } - +*/ /* double gamma = 0.0; */ sum = sum*(1 + beta + 0.3*gamma); From 94ce14774a5bd531f4c5ec4d37909b950f885a48 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sun, 17 Nov 2019 21:23:43 -0500 Subject: [PATCH 25/48] Debugging increased invalid Edge index --- crv/crvShape.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 3292451ed..099f0a294 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -490,6 +490,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, //ma::Downward ed; //m->getDownward(e,1,ed); bb.push_back(index); + bb.push_back(index); break; } //break; From dc142d761782835445d7de8a946cbe2091286dbc Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Wed, 20 Nov 2019 13:24:14 -0500 Subject: [PATCH 26/48] Debugging reshape operator, final. without entity numbering. --- crv/crvEdgeOptim.cc | 5 +++++ crv/crvFaceOptim.cc | 24 +++++++++++++----------- crv/crvModelEdgeOptim.cc | 8 ++++++-- crv/crvShape.cc | 8 ++------ 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 9b6e7104b..68ace22e8 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -16,6 +16,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { + return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -23,10 +24,13 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) } static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { + /* + return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); std::cout<<"at edge "<< num << std::endl; + */ for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -39,6 +43,7 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) { + return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc index 810accdaf..6628b5902 100644 --- a/crv/crvFaceOptim.cc +++ b/crv/crvFaceOptim.cc @@ -12,6 +12,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { + return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -20,10 +21,13 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, int nat) { + /* + return; apf::Numbering* n = m->findNumbering("debug_num_face"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, face, 0, 0); std::cout<<"at face "<< num << std::endl; + */ for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -35,6 +39,7 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, const char* prefix, int nat) { + return; apf::Numbering* n = m->findNumbering("debug_num_face"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, face, 0, 0); @@ -689,23 +694,15 @@ bool CrvFaceOptim :: run(int &invaliditySize) printTetNumber(mesh, adjT[i]); } - if (l->run()) { + if (l->run() && invaliditySize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); std::vector aiNew = crv::getAllInvalidities(mesh, tet); -/* - for (int i = 0; i < adjT.getSize(); i++) { - std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); - //invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); - } -*/ - // if (hasDecreased == false || hasDecreased == true) { - if (aiNew.size() <= invaliditySize) { - invaliditySize = aiNew.size(); + if (aiNew.size() <= invaliditySize) { + invaliditySize = aiNew.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); printInvalidities(mesh, adj_array, face, adj.getSize()); @@ -722,6 +719,11 @@ bool CrvFaceOptim :: run(int &invaliditySize) } } else { + if (invaliditySize == 0) { + std::cout<<" No Optimization tried"< static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ +{ + return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -24,11 +25,13 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { + /* + return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); std::cout<<"at edge "<< num << std::endl; - +*/ for (int i = 0; i < nat; i++) { std::vector ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -41,6 +44,7 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) { + return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 099f0a294..fd9c42203 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -1099,7 +1099,6 @@ class EdgeOptimizer : public ma::Operator } virtual void apply() { - //mesh->getDownward(simplex, 1, edges); for (int i = 0; i < ne; i++ ) { int invaliditySize = 0; if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { @@ -1119,9 +1118,7 @@ class EdgeOptimizer : public ma::Operator nf++; } - delete ceo; - //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); } else if (mesh->getModelType(mesh->toModel(edges[i])) == 2) { CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edges[i], simplex); @@ -1140,7 +1137,6 @@ class EdgeOptimizer : public ma::Operator nf++; } - //ma::clearFlag(adapter, edge, ma::COLLAPSE | ma::BAD_QUALITY); delete cmeo; } } @@ -1455,7 +1451,7 @@ static void collapseInvalidEdges(Adapt* a) ma::print("Collapsed %d bad edges " "in %f seconds",successCount, t1-t0); } -/* + static void swapInvalidEdges(Adapt* a) { double t0 = PCU_Time(); @@ -1465,7 +1461,7 @@ static void swapInvalidEdges(Adapt* a) ma::print("Swapped %d bad edges " "in %f seconds",es.ns, t1-t0); } -*/ + static void repositionInvalidEdges(Adapt* a) { double t0 = PCU_Time(); From b8c7c8034400fc09ec17d20836a534fa1d35d39e Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Wed, 20 Nov 2019 14:37:39 -0500 Subject: [PATCH 27/48] new function fixInvalidEdgesCollapseAndSwap --- crv/crvAdapt.cc | 1 + crv/crvShape.cc | 72 ++++++++++++++++++++++++++----------------------- crv/crvShape.h | 1 + 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 0aea1482c..19e6a8b68 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -167,6 +167,7 @@ static int fixInvalidElements(crv::Adapt* a) crv::fixLargeBoundaryAngles(a); crv::fixInvalidFaces(a); crv::fixInvalidEdges(a); + crv::fixInvalidEdgesCollapseAndSwap(a); return 0; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index fd9c42203..df3966c86 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -653,10 +653,14 @@ static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, i static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* faces[4]) { + + if (ai.size() == 0) return 0; +/* for (int i = 0; i < ai.size(); i++) { if (ai[i] == 20) int j = 0; } + */ std::vector faceInvalid = numOfUniqueFaces(ai); int n = 0; @@ -1337,6 +1341,7 @@ static int markEdgesOppLargeAnglesTet(Adapt* a) * and then use the results to mark edges, etc for * fixing */ + static int markEdgesToFix(Adapt* a, int flag) { // do a invalidity check first @@ -1351,38 +1356,29 @@ static int markEdgesToFix(Adapt* a, int flag) // markEdges could have upto 6 edges marked!!! ma::Entity* edges[6]; ma::Iterator* it = m->begin(m->getDimension()); - //std::vector ai; - //Quality* qual = makeQuality(m, 2); + while ((e = m->iterate(it))) { - //int tag = crv::getTag(a,e); - //int n = markEdges(m,e,tag,edges); + int tag = crv::getTag(a,e); + int n = markEdges(m,e,tag,edges); - std::vector ai = crv::getAllInvalidities(m, e); - //int niv = qual->checkValidity(e); - int niv = ai.size(); - if (niv != 0) { - int n = markAllEdges(m, e, ai, edges); - for (int i = 0; i < n; ++i){ - ma::Entity* edge = edges[i]; - PCU_ALWAYS_ASSERT(edge); - - if (edge && !ma::getFlag(a,edge,flag)) { - if (m->getModelType(m->toModel(edge)) != 1) { - ma::setFlag(a,edge,flag); - if (a->mesh->isOwned(edge)) - ++count; - } - } + for (int i = 0; i < n; ++i){ + ma::Entity* edge = edges[i]; + PCU_ALWAYS_ASSERT(edge); + + if (edge && !ma::getFlag(a,edge,flag)) { + ma::setFlag(a,edge,flag); + if (a->mesh->isOwned(edge)) + ++count; } } } - //delete qual; m->end(it); return PCU_Add_Long(count); } +/* static int markFacesToFix(Adapt* a, int flag) { int invalid = markInvalidEntities(a); @@ -1416,7 +1412,7 @@ static int markFacesToFix(Adapt* a, int flag) return PCU_Add_Long(count); } - +*/ int fixLargeBoundaryAngles(Adapt* a) { double t0 = PCU_Time(); @@ -1494,11 +1490,6 @@ static void optimizeInvalidFaces(Adapt* a) int fixInvalidFaces(Adapt* a) { - //int count = markFacesToFix(a, ma::SNAP); - //if (! count) { - // return 0; - //} - optimizeInvalidFaces(a); return 0; @@ -1506,21 +1497,36 @@ int fixInvalidFaces(Adapt* a) int fixInvalidEdges(Adapt* a) { - //int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - //if (! count){ - // return 0; - //} + if(a->mesh->getShape()->getOrder() == 2) repositionInvalidEdges(a); else optimizeInvalidEdges(a); +/* + int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); + if (! count){ + return 0; + } - //collapseInvalidEdges(a); - //swapInvalidEdges(a); + collapseInvalidEdges(a); + swapInvalidEdges(a); +*/ return 0; } +int fixInvalidEdgesCollapseAndSwap(Adapt* a) +{ + int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); + if (! count){ + return 0; + } + + collapseInvalidEdges(a); + swapInvalidEdges(a); + + return count; +} struct IsBadCrvQuality : public ma::Predicate { diff --git a/crv/crvShape.h b/crv/crvShape.h index 2536a13a5..7fe8876ee 100644 --- a/crv/crvShape.h +++ b/crv/crvShape.h @@ -58,6 +58,7 @@ int fixLargeBoundaryAngles(Adapt* a); /** \brief If an edge is flagged as invalid, try and collapse or swap it away */ int fixInvalidEdges(Adapt* a); +int fixInvalidEdgesCollapseAndSwap(Adapt* a); /** \brief If a face is flagged as invalid optimize the face nodes */ From 7301f4fb58799fa35a2dfff80a07a89fad660b74 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Fri, 22 Nov 2019 03:44:40 -0500 Subject: [PATCH 28/48] debugging for antenna --- crv/CMakeLists.txt | 2 + crv/LBFGS.h | 2 +- crv/crvAdapt.cc | 3 + crv/crvEdgeOptim.cc | 12 ++- crv/crvEdgeOptim.h | 2 +- crv/crvFaceOptim.cc | 43 +++++---- crv/crvModelEdgeOptim.cc | 10 +- crv/crvModelEdgeOptim.h | 2 +- crv/crvShape.cc | 192 ++++++++++++++++++++++++++++++++------- 9 files changed, 208 insertions(+), 60 deletions(-) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index b18d8eb15..da4be73a0 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -24,6 +24,7 @@ set(SOURCES crvEdgeOptim.cc crvModelEdgeOptim.cc crvFaceOptim.cc + optim.cc ) # Package headers @@ -33,6 +34,7 @@ set(HEADERS crvModelEdgeOptim.h crvFaceOptim.h LBFGS.h + optim.h crvBezier.h crvTables.h crvQuality.h diff --git a/crv/LBFGS.h b/crv/LBFGS.h index ee8d70253..cf2ebad23 100644 --- a/crv/LBFGS.h +++ b/crv/LBFGS.h @@ -48,7 +48,7 @@ class LBFGS double fValAfter; private: - int r = 25; + int r = 40; }; } diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 19e6a8b68..8923cab39 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -165,8 +165,11 @@ static int fixInvalidElements(crv::Adapt* a) { crv::fixLargeBoundaryAngles(a); + crv::fixInvalidEdgesCollapseAndSwap(a); crv::fixInvalidFaces(a); crv::fixInvalidEdges(a); + //crv::fixInvalidFaces(a); + //crv::fixInvalidEdges(a); crv::fixInvalidEdgesCollapseAndSwap(a); return 0; diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 68ace22e8..48aaed16e 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -16,6 +16,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { + printf("\n"); return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); @@ -866,7 +867,7 @@ void CrvEdgeOptim :: setTol(double tolerance) tol = tolerance; } -bool CrvEdgeOptim :: run(int &invaliditySize) +bool CrvEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) { std::vector sizeHolder; apf::MeshEntity* adj_array[99]; @@ -882,7 +883,7 @@ bool CrvEdgeOptim :: run(int &invaliditySize) } - std::vector ai = crv::getAllInvalidities(mesh, tet); + //std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printTetNumber(mesh, tet); @@ -894,15 +895,18 @@ bool CrvEdgeOptim :: run(int &invaliditySize) LBFGS *l = new LBFGS(tol, iter, x0, objF); apf::MeshEntity* ed[6]; + int thisTETnum = 0; for (std::size_t i = 0; i < adj.getSize(); i++) { + if (adj[i] == tet) thisTETnum = 1; + else thisTETnum = 0; mesh->getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge; ", edgeIndex); + printf("reshape tried on %d edge, TET %d; ", edgeIndex, thisTETnum); printTetNumber(mesh, adj[i]); } - bool hasDecreased = false; + hasDecreased = false; invaliditySize = 0; if (l->run() && thisTetSize > 0) { diff --git a/crv/crvEdgeOptim.h b/crv/crvEdgeOptim.h index c80e0fe91..0f958d904 100644 --- a/crv/crvEdgeOptim.h +++ b/crv/crvEdgeOptim.h @@ -69,7 +69,7 @@ class CrvEdgeOptim public: void setMaxIter(int n); void setTol(double tolerance); - bool run(int &invaliditySize); + bool run(int &invaliditySize, bool &hasDecreased); public: apf::Mesh2* mesh; apf::MeshEntity* edge; diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc index 6628b5902..e90c1ce34 100644 --- a/crv/crvFaceOptim.cc +++ b/crv/crvFaceOptim.cc @@ -12,6 +12,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { + printf("\n"); return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); @@ -618,7 +619,7 @@ std::vector CrvFaceReshapeObjFunc :: getGrad(std::vector &x) double delx = std::abs(xmx - xmn); double dely = std::abs(ymx - ymn); double delz = std::abs(zmx - zmn); - double delta = 1.0; + double delta = 0.0; for (std::size_t i = 0; i < x.size(); i++) { if (i % 3 == 0) delta = delx; @@ -665,14 +666,16 @@ bool CrvFaceOptim :: run(int &invaliditySize) apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(face, 3, adj); + int thisTetSize = 0; for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; - //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - //sizeHolder.push_back(ai.size()); + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + if (adj[i] == tet) thisTetSize = ai.size(); + sizeHolder.push_back(ai.size()); } - std::vector ai = crv::getAllInvalidities(mesh, tet); - invaliditySize = ai.size(); + //std::vector ai = crv::getAllInvalidities(mesh, tet); + //invaliditySize = ai.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); printTetNumber(mesh, tet); @@ -683,26 +686,34 @@ bool CrvFaceOptim :: run(int &invaliditySize) //std::cout<< "fval at x0 " << f0<getAdjacent(face, 3, adjT); apf::MeshEntity* fc[4]; + int thisTETnum = 0; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - mesh->getDownward(adjT[i], 2, fc); + for (std::size_t i = 0; i < adj.getSize(); i++) { + if (adj[i] == tet) thisTETnum = 1; + else thisTETnum = 0; + mesh->getDownward(adj[i], 2, fc); int faceIndex = apf::findIn(fc, 4, face); - printf("reshape tried on %d face; ",faceIndex); - printTetNumber(mesh, adjT[i]); + printf("reshape tried on %d face, TET %d ",faceIndex, thisTETnum); + printTetNumber(mesh, adj[i]); } - if (l->run() && invaliditySize > 0) { + bool hasDecreased = false; + invaliditySize = 0; + + if (l->run() && thisTetSize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); - std::vector aiNew = crv::getAllInvalidities(mesh, tet); + for (int i = 0; i < adj.getSize(); i++) { + std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + } - if (aiNew.size() <= invaliditySize) { - invaliditySize = aiNew.size(); + if (hasDecreased == false ) { + //invaliditySize = aiNew.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); printInvalidities(mesh, adj_array, face, adj.getSize()); @@ -719,7 +730,7 @@ bool CrvFaceOptim :: run(int &invaliditySize) } } else { - if (invaliditySize == 0) { + if (thisTetSize == 0) { std::cout<<" No Optimization tried"<findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); @@ -1171,7 +1172,7 @@ void CrvModelEdgeOptim :: setTol(double tolerance) tol = tolerance; } -bool CrvModelEdgeOptim :: run(int &invaliditySize) +bool CrvModelEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) { std::vector sizeHolder; apf::MeshEntity* adj_array[99]; @@ -1201,15 +1202,18 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize) //std::cout<< "fval at x0 " << f0<getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge; ", edgeIndex); + printf("reshape tried on %d Medge, TET %d ", edgeIndex, thisTETnum); printTetNumber(mesh, adj[i]); } - bool hasDecreased = false; + hasDecreased = false; invaliditySize = 0; if (l->run() && thisTetSize > 0) { diff --git a/crv/crvModelEdgeOptim.h b/crv/crvModelEdgeOptim.h index 37f758a6a..31c29b0f5 100644 --- a/crv/crvModelEdgeOptim.h +++ b/crv/crvModelEdgeOptim.h @@ -73,7 +73,7 @@ class CrvModelEdgeOptim public: void setMaxIter(int n); void setTol(double tolerance); - bool run(int &invaliditySize); + bool run(int &invaliditySize, bool &hasDecreased); public: apf::Mesh2* mesh; apf::MeshEntity* edge; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index df3966c86..3b770d69d 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -279,6 +279,83 @@ static int getCommonEdgeIndexToFaces(int a, int b) } */ // doess not account for TET(20) invalidity + + +static std::vector numOfUniqueFaces(std::vector &ai) +{ + std::vector aiEdgeNVtx; + std::vector aiOnlyFace; + std::vector aiOnlyEdge; + std::vector aiOnlyVtx; + std::vector aiOnlyTet; + + for (size_t i = 0; i < ai.size(); i++) { + if (ai[i] < 8) aiOnlyVtx.push_back(ai[i]); + else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); + else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); + else aiOnlyTet.push_back(ai[i]); + } + + int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, + {0, -1, 4, 3}, + {1, 4, -1, 5}, + {2, 3, 5, -1}}; + + int edgeToFaceInd[6][2] = {{0, 1}, + {0, 2}, + {0, 3}, + {1, 3}, + {1, 2}, + {2, 3}}; + + int edgeToVtx[6][2] = {{0, 1}, + {1, 2}, + {0, 2}, + {0, 3}, + {1, 3}, + {2, 3}}; + + bool hasDownVtx, alreadyIn; + + for (size_t j = 0; j < aiOnlyEdge.size(); j++) { + hasDownVtx = false; + for (int jj = 0; jj < 2; jj++) { + //hasDownVtx = false; + for (size_t ii = 0; ii < aiOnlyVtx.size(); ii++) { + hasDownVtx = hasDownVtx || (edgeToVtx[aiOnlyEdge[j]-8][jj] == aiOnlyVtx[ii] - 2); + } + } + + if (hasDownVtx == false) { + for (int i = 0; i < 2; i++) { + aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); + } + } + } + + /* + for (size_t j = 0; j < aiOnlyEdge.size(); j++) { + for (int i = 0; i < 2; i++) { + aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); + } + } + */ + + for (size_t j = 0; j < aiOnlyTet.size(); j++) { + for (int jj = 0; jj < 4; jj++) { + aiOnlyFace.push_back(jj+14); + } + } + + std::vector allinvFaces; + + if (aiOnlyFace.size() > 0) + allinvFaces = sortEdgeIndexByFrequency(aiOnlyFace); + + return allinvFaces; +} + +/* static std::vector numOfUniqueFaces(std::vector &ai) { std::vector aiEdgeNVtx; @@ -295,12 +372,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); else aiOnlyTet.push_back(ai[i]); -/* - if (ai[i] > 13 && ai[i] < 20) - aiOnlyFace.push_back(ai[i]); - else - aiEdgeNVtx.push_back(ai[i]); - */ + } int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, @@ -338,14 +410,14 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } - /* + for (size_t j = 0; j < aiOnlyFace.size(); j++) { bool isUnique = false; for (int i = 0; i < 4; i++) { - for (size_t k = 0; k < aiEdgeNVtx.size(); k++) { - if (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]) + for (size_t k = 0; k < aiOnlyEdge.size(); k++) { + if (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiOnlyEdge[k]) aiUniqueFace.push_back(i+14); - isUnique = isUnique || (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiEdgeNVtx[k]); + isUnique = isUnique || (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiOnlyEdge[k]); } } if (isUnique == false) { @@ -353,7 +425,8 @@ static std::vector numOfUniqueFaces(std::vector &ai) aiOnlyFace.erase(aiOnlyFace.begin()+j); } } -*/ + + bool hasDownVtx, alreadyIn; @@ -381,7 +454,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) for (int i = 0; i < 2; i++) { for (size_t k = 0; k < aiOnlyFace.size(); k++) { if (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14) { - aiOnlyFace.erase(aiOnlyFace.begin()+k); + //aiOnlyFace.erase(aiOnlyFace.begin()+k); } } } @@ -430,7 +503,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) } return forFaceMarking; } - +*/ /* static std::vector inspectInvalidies(std::vector ai) { @@ -465,7 +538,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector faceInvalid = numOfUniqueFaces(ai); if (ai.size() == 0) return 0; - if (ai.size() == faceInvalid[0]) return 0; + //if (ai.size() == faceInvalid[0]) return 0; for (size_t ii = 0; ii < ai.size(); ii++) { int dim = (ai[ii]-2)/6; @@ -490,7 +563,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, //ma::Downward ed; //m->getDownward(e,1,ed); bb.push_back(index); - bb.push_back(index); + //bb.push_back(index); break; } //break; @@ -503,8 +576,8 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, for (int i = 0; i < 3; i++) { int j = apf::findIn(ed, 6, edf[i]); - //if (j != -1) - //bb.push_back(j); + if (j != -1) + bb.push_back(j); } break; } @@ -670,6 +743,16 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Downward ed; m->getDownward(e, 1, ed); + for (std::size_t i = 0; i < faceInvalid.size();i++) { + int index = (faceInvalid[i] - 2) % 6; + int md = m->getDimension(); + + if (m->getModelType(m->toModel(fc[index])) == 3) { + faces[n] = fc[index]; + n++; + } + } + /* if (faceInvalid[0] > 0) { for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { int index = (faceInvalid[i] -2) % 6; @@ -681,6 +764,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, } } } + */ /* if (faceInvalid.size() > 1+faceInvalid[0]) { int kkk = faceInvalid.size()-faceInvalid[0]-1; @@ -710,10 +794,15 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, n++; } } + else { + faces[n] = fc[FaceInd1]; + n++; + faces[n] = fc[FaceInd2]; + n++; + } } } - */ - +*/ return n; } @@ -813,10 +902,22 @@ class EdgeSwapper : public ma::Operator virtual int getTargetDimension() {return md;} virtual bool shouldApply(ma::Entity* e) { + std::vector ai = crv::getAllInvalidities(mesh, e); + mesh->getDownward(e, 1, edges); + int niv = ai.size(); + ne = 0; + if (niv != 0) { + ne = markAllEdges(mesh, e, ai, edges); + simplex = e; + } + return (ne > 0); + /* int tag = crv::getTag(adapter,e); ne = markEdges(mesh,e,tag,edges); + simplex = e; return (ne > 0); + */ } virtual bool requestLocality(apf::CavityOp* o) { @@ -827,7 +928,7 @@ class EdgeSwapper : public ma::Operator for (int i = 0; i < ne; ++i){ if (edgeSwap->run(edges[i])){ ns++; - crv::clearTag(adapter,simplex); + // crv::clearTag(adapter,simplex); ma::clearFlag(adapter,edges[i],ma::COLLAPSE | ma::BAD_QUALITY); break; } @@ -1017,11 +1118,12 @@ class FaceOptimizer : public ma::Operator std::vector ai = crv::getAllInvalidities(mesh, e); int niv = ai.size(); mesh->getDownward(e, 2, faces); + numf = 0; if (niv != 0) { numf = markUniqueFaces(mesh, e, ai, faces); simplex = e; - return (numf > 0); } + return (numf > 0); } virtual bool requestLocality(apf::CavityOp* o) @@ -1032,6 +1134,7 @@ class FaceOptimizer : public ma::Operator virtual void apply(){ int invaliditySize = 0; //mesh->getDownward(simplex, 2, faces); + if (numf == 0) return; for (int i = 0; i < numf; i++ ) { if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i], simplex); @@ -1089,11 +1192,12 @@ class EdgeOptimizer : public ma::Operator std::vector ai = crv::getAllInvalidities(mesh, e); mesh->getDownward(e, 1, edges); int niv = ai.size(); + ne = 0; if (niv != 0) { ne = markAllEdges(mesh, e, ai, edges); simplex = e; - return (ne > 0); } + return (ne > 0); } @@ -1103,14 +1207,16 @@ class EdgeOptimizer : public ma::Operator } virtual void apply() { + if (ne == 0) return; for (int i = 0; i < ne; i++ ) { int invaliditySize = 0; + bool hasDecreased = false; if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edges[i], simplex); ceo->setMaxIter(100); ceo->setTol(1e-8); - if (ceo->run(invaliditySize)) { + if (ceo->run(invaliditySize, hasDecreased)) { ns++; if (invaliditySize < 1) break; @@ -1119,6 +1225,12 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) { break; } + /* + if (hasDecreased && ne < 7) { + edges[ne] = edges[i]; + ne++; + } + */ nf++; } @@ -1129,7 +1241,7 @@ class EdgeOptimizer : public ma::Operator cmeo->setMaxIter(200); cmeo->setTol(1e-8); - if (cmeo->run(invaliditySize)) { + if (cmeo->run(invaliditySize, hasDecreased)) { ns++; if (invaliditySize < 1) break; @@ -1138,6 +1250,12 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) { break; } + /* + if (hasDecreased && ne < 7) { + edges[ne] = edges[i]; + ne++; + } + */ nf++; } @@ -1359,17 +1477,23 @@ static int markEdgesToFix(Adapt* a, int flag) while ((e = m->iterate(it))) { - int tag = crv::getTag(a,e); - int n = markEdges(m,e,tag,edges); - - for (int i = 0; i < n; ++i){ - ma::Entity* edge = edges[i]; - PCU_ALWAYS_ASSERT(edge); + //int tag = crv::getTag(a,e); + //int n = markEdges(m,e,tag,edges); + + std::vector ai = crv::getAllInvalidities(m, e); + int niv = ai.size(); - if (edge && !ma::getFlag(a,edge,flag)) { - ma::setFlag(a,edge,flag); - if (a->mesh->isOwned(edge)) - ++count; + if (niv != 0) { + int n = markAllEdges(m, e, ai, edges); + for (int i = 0; i < n; ++i){ + ma::Entity* edge = edges[i]; + PCU_ALWAYS_ASSERT(edge); + + if (edge && !ma::getFlag(a,edge,flag)) { + ma::setFlag(a,edge,flag); + if (a->mesh->isOwned(edge)) + ++count; + } } } } From b69ad47eeccd29b2f83fde66d1816a9f380ed54b Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Fri, 22 Nov 2019 04:02:44 -0500 Subject: [PATCH 29/48] delta value change --- crv/crvFaceOptim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc index e90c1ce34..03a208c39 100644 --- a/crv/crvFaceOptim.cc +++ b/crv/crvFaceOptim.cc @@ -619,7 +619,7 @@ std::vector CrvFaceReshapeObjFunc :: getGrad(std::vector &x) double delx = std::abs(xmx - xmn); double dely = std::abs(ymx - ymn); double delz = std::abs(zmx - zmn); - double delta = 0.0; + double delta = 1.0; for (std::size_t i = 0; i < x.size(); i++) { if (i % 3 == 0) delta = delx; From 8f4594ed00627b46491accc8f12dfcdfb017721f Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sun, 24 Nov 2019 18:42:20 -0500 Subject: [PATCH 30/48] debug-single-pass --- crv/crvAdapt.cc | 3 -- crv/crvEdgeOptim.cc | 14 ++--- crv/crvFaceOptim.cc | 39 ++++++++------ crv/crvModelEdgeOptim.cc | 13 ++--- crv/crvShape.cc | 109 +++++++++++++++++++++++++++++++++------ 5 files changed, 129 insertions(+), 49 deletions(-) diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 8923cab39..4ec595f03 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -168,9 +168,6 @@ static int fixInvalidElements(crv::Adapt* a) crv::fixInvalidEdgesCollapseAndSwap(a); crv::fixInvalidFaces(a); crv::fixInvalidEdges(a); - //crv::fixInvalidFaces(a); - //crv::fixInvalidEdges(a); - crv::fixInvalidEdgesCollapseAndSwap(a); return 0; diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 48aaed16e..1f2011201 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -16,8 +16,8 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { - printf("\n"); - return; + //printf("\n"); + //return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -25,13 +25,14 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) } static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { - /* - return; + + //return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); - std::cout<<"at edge "<< num << std::endl; - */ + int tag = m->getModelTag(m->toModel(edge)); + std::cout<<"at edge "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -930,6 +931,7 @@ bool CrvEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) return true; } else { + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); objF->restoreInitialNodes(); printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"Size DID NOT decrease"<findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -22,13 +22,14 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, int nat) { - /* - return; + +// return; apf::Numbering* n = m->findNumbering("debug_num_face"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, face, 0, 0); - std::cout<<"at face "<< num << std::endl; - */ + int tag = m->getModelTag(m->toModel(face)); + std::cout<<"at face "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { @@ -669,13 +670,13 @@ bool CrvFaceOptim :: run(int &invaliditySize) int thisTetSize = 0; for (int i = 0; i < adj.getSize(); i++) { adj_array[i] = adj[i]; - std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - if (adj[i] == tet) thisTetSize = ai.size(); - sizeHolder.push_back(ai.size()); + //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + //if (adj[i] == tet) thisTetSize = ai.size(); + //sizeHolder.push_back(ai.size()); } - //std::vector ai = crv::getAllInvalidities(mesh, tet); - //invaliditySize = ai.size(); + std::vector ai = crv::getAllInvalidities(mesh, tet); + invaliditySize = ai.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); printTetNumber(mesh, tet); @@ -698,22 +699,26 @@ bool CrvFaceOptim :: run(int &invaliditySize) printTetNumber(mesh, adj[i]); } - bool hasDecreased = false; - invaliditySize = 0; + //bool hasDecreased = false; + //invaliditySize = 0; - if (l->run() && thisTetSize > 0) { + //if (l->run() && thisTetSize > 0) { + if (l->run() && invaliditySize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); + std::vector aiNew = crv::getAllInvalidities(mesh, tet); + /* for (int i = 0; i < adj.getSize(); i++) { std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); invaliditySize = invaliditySize + aiNew.size(); hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } - - if (hasDecreased == false ) { - //invaliditySize = aiNew.size(); +*/ + // if (hasDecreased == false ) { + if (aiNew.size() <= invaliditySize) { + invaliditySize = aiNew.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); printInvalidities(mesh, adj_array, face, adj.getSize()); diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 820d8af62..6346065af 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -16,8 +16,8 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { - printf("\n"); - return; + //printf("\n"); + //return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -26,13 +26,14 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { - /* - return; + + //return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); - std::cout<<"at edge "<< num << std::endl; -*/ + int tag = m->getModelTag(m->toModel(edge)); + std::cout<<"at edge "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); for (std::size_t j = 0; j < ai.size(); j++) { diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 3b770d69d..faecc8bcd 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -23,6 +23,7 @@ #include "crvModelEdgeOptim.h" #include "crvFaceOptim.h" #include "crvQuality.h" +#include "apfNumbering.h" /* This is similar to maShape.cc, conceptually, but different enough * that some duplicate code makes sense */ @@ -280,7 +281,7 @@ static int getCommonEdgeIndexToFaces(int a, int b) */ // doess not account for TET(20) invalidity - +/* static std::vector numOfUniqueFaces(std::vector &ai) { std::vector aiEdgeNVtx; @@ -333,13 +334,13 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } - /* + for (size_t j = 0; j < aiOnlyEdge.size(); j++) { for (int i = 0; i < 2; i++) { aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); } } - */ + for (size_t j = 0; j < aiOnlyTet.size(); j++) { for (int jj = 0; jj < 4; jj++) { @@ -354,8 +355,8 @@ static std::vector numOfUniqueFaces(std::vector &ai) return allinvFaces; } +*/ -/* static std::vector numOfUniqueFaces(std::vector &ai) { std::vector aiEdgeNVtx; @@ -409,9 +410,9 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } } - - - for (size_t j = 0; j < aiOnlyFace.size(); j++) { +///////// +/* + for (size_t j = 0; j < aiOnlyFace.size(); j++) { bool isUnique = false; for (int i = 0; i < 4; i++) { for (size_t k = 0; k < aiOnlyEdge.size(); k++) { @@ -425,8 +426,8 @@ static std::vector numOfUniqueFaces(std::vector &ai) aiOnlyFace.erase(aiOnlyFace.begin()+j); } } - - +////////// +*/ bool hasDownVtx, alreadyIn; @@ -503,7 +504,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) } return forFaceMarking; } -*/ + /* static std::vector inspectInvalidies(std::vector ai) { @@ -538,9 +539,10 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector faceInvalid = numOfUniqueFaces(ai); if (ai.size() == 0) return 0; - //if (ai.size() == faceInvalid[0]) return 0; + if (ai.size() == faceInvalid[0]) return 0; for (size_t ii = 0; ii < ai.size(); ii++) { + int dim = (ai[ii]-2)/6; int index = (ai[ii]-2) % 6; @@ -563,7 +565,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, //ma::Downward ed; //m->getDownward(e,1,ed); bb.push_back(index); - //bb.push_back(index); + bb.push_back(index); break; } //break; @@ -576,8 +578,8 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, for (int i = 0; i < 3; i++) { int j = apf::findIn(ed, 6, edf[i]); - if (j != -1) - bb.push_back(j); + //if (j != -1) + //bb.push_back(j); } break; } @@ -742,7 +744,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, m->getDownward(e, 2, fc); ma::Downward ed; m->getDownward(e, 1, ed); - +/* for (std::size_t i = 0; i < faceInvalid.size();i++) { int index = (faceInvalid[i] - 2) % 6; int md = m->getDimension(); @@ -752,7 +754,8 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, n++; } } - /* +*/ + if (faceInvalid[0] > 0) { for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { int index = (faceInvalid[i] -2) % 6; @@ -764,7 +767,7 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, } } } - */ + /* if (faceInvalid.size() > 1+faceInvalid[0]) { int kkk = faceInvalid.size()-faceInvalid[0]-1; @@ -1614,19 +1617,91 @@ static void optimizeInvalidFaces(Adapt* a) int fixInvalidFaces(Adapt* a) { + + ma::Mesh* mesh = a->mesh; + apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); + apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); + apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); + + apf::MeshEntity* ent; + apf::MeshIterator* it; + + it = mesh->begin(1); + int count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(edge_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(2); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(face_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(3); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(tet_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + optimizeInvalidFaces(a); + mesh->removeNumbering(edge_num); + mesh->removeNumbering(face_num); + mesh->removeNumbering(tet_num); + return 0; } int fixInvalidEdges(Adapt* a) { + ma::Mesh* mesh = a->mesh; + apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); + apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); + apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); + + apf::MeshEntity* ent; + apf::MeshIterator* it; + + it = mesh->begin(1); + int count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(edge_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(2); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(face_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(3); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(tet_num, ent, 0, 0, count); + count++; + } + mesh->end(it); if(a->mesh->getShape()->getOrder() == 2) repositionInvalidEdges(a); else optimizeInvalidEdges(a); + + mesh->removeNumbering(edge_num); + mesh->removeNumbering(face_num); + mesh->removeNumbering(tet_num); /* int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); if (! count){ From eb7471cbce1e5cc254b444f7c98daa59412ed1fd Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sun, 24 Nov 2019 22:11:46 -0500 Subject: [PATCH 31/48] debug_antenna_1_invalidity --- crv/CMakeLists.txt | 2 -- crv/crvEdgeOptim.cc | 4 ++-- crv/crvEdgeOptim.h | 2 +- crv/crvModelEdgeOptim.cc | 4 ++-- crv/crvModelEdgeOptim.h | 2 +- crv/crvShape.cc | 16 ++-------------- 6 files changed, 8 insertions(+), 22 deletions(-) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index da4be73a0..b18d8eb15 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -24,7 +24,6 @@ set(SOURCES crvEdgeOptim.cc crvModelEdgeOptim.cc crvFaceOptim.cc - optim.cc ) # Package headers @@ -34,7 +33,6 @@ set(HEADERS crvModelEdgeOptim.h crvFaceOptim.h LBFGS.h - optim.h crvBezier.h crvTables.h crvQuality.h diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 1f2011201..04c6b40ac 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -868,7 +868,7 @@ void CrvEdgeOptim :: setTol(double tolerance) tol = tolerance; } -bool CrvEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) +bool CrvEdgeOptim :: run(int &invaliditySize) { std::vector sizeHolder; apf::MeshEntity* adj_array[99]; @@ -907,7 +907,7 @@ bool CrvEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) printTetNumber(mesh, adj[i]); } - hasDecreased = false; + bool hasDecreased = false; invaliditySize = 0; if (l->run() && thisTetSize > 0) { diff --git a/crv/crvEdgeOptim.h b/crv/crvEdgeOptim.h index 0f958d904..c80e0fe91 100644 --- a/crv/crvEdgeOptim.h +++ b/crv/crvEdgeOptim.h @@ -69,7 +69,7 @@ class CrvEdgeOptim public: void setMaxIter(int n); void setTol(double tolerance); - bool run(int &invaliditySize, bool &hasDecreased); + bool run(int &invaliditySize); public: apf::Mesh2* mesh; apf::MeshEntity* edge; diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 6346065af..4da5c77d5 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -1173,7 +1173,7 @@ void CrvModelEdgeOptim :: setTol(double tolerance) tol = tolerance; } -bool CrvModelEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) +bool CrvModelEdgeOptim :: run(int &invaliditySize) { std::vector sizeHolder; apf::MeshEntity* adj_array[99]; @@ -1214,7 +1214,7 @@ bool CrvModelEdgeOptim :: run(int &invaliditySize, bool &hasDecreased) printTetNumber(mesh, adj[i]); } - hasDecreased = false; + bool hasDecreased = false; invaliditySize = 0; if (l->run() && thisTetSize > 0) { diff --git a/crv/crvModelEdgeOptim.h b/crv/crvModelEdgeOptim.h index 31c29b0f5..37f758a6a 100644 --- a/crv/crvModelEdgeOptim.h +++ b/crv/crvModelEdgeOptim.h @@ -73,7 +73,7 @@ class CrvModelEdgeOptim public: void setMaxIter(int n); void setTol(double tolerance); - bool run(int &invaliditySize, bool &hasDecreased); + bool run(int &invaliditySize); public: apf::Mesh2* mesh; apf::MeshEntity* edge; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index faecc8bcd..dd39cb557 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -1219,7 +1219,7 @@ class EdgeOptimizer : public ma::Operator ceo->setMaxIter(100); ceo->setTol(1e-8); - if (ceo->run(invaliditySize, hasDecreased)) { + if (ceo->run(invaliditySize)) { ns++; if (invaliditySize < 1) break; @@ -1228,12 +1228,6 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) { break; } - /* - if (hasDecreased && ne < 7) { - edges[ne] = edges[i]; - ne++; - } - */ nf++; } @@ -1244,7 +1238,7 @@ class EdgeOptimizer : public ma::Operator cmeo->setMaxIter(200); cmeo->setTol(1e-8); - if (cmeo->run(invaliditySize, hasDecreased)) { + if (cmeo->run(invaliditySize)) { ns++; if (invaliditySize < 1) break; @@ -1253,12 +1247,6 @@ class EdgeOptimizer : public ma::Operator if (invaliditySize < 1) { break; } - /* - if (hasDecreased && ne < 7) { - edges[ne] = edges[i]; - ne++; - } - */ nf++; } From e03b344be9c2c7e828b690762d9316b1c815db61 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Wed, 27 Nov 2019 10:24:34 -0500 Subject: [PATCH 32/48] Clean up + crvDBG + External LBFGS 1. Combined all the optimization ops into one single header/source 2. Combined all the objective functions into one single header/source 3. Using and external LBFGS optimizer from (git@github.com:yixuan/LBFGSpp.git) 4. Moved most of the debug related routines into crvDBG namespace --- crv/CMakeLists.txt | 21 +- crv/LBFGS.cc | 188 ----- crv/LBFGS.h | 56 -- crv/crvCurveMesh.cc | 3 +- crv/crvDBG.cc | 337 +++++++++ crv/crvDBG.h | 24 + crv/crvEdgeOptim.cc | 957 ------------------------- crv/crvEdgeOptim.h | 84 --- crv/crvFaceOptim.cc | 748 -------------------- crv/crvFaceOptim.h | 80 --- crv/crvModelEdgeOptim.cc | 1260 --------------------------------- crv/crvModelEdgeOptim.h | 88 --- crv/crvObjectiveFunctions.cc | 1276 ++++++++++++++++++++++++++++++++++ crv/crvObjectiveFunctions.h | 205 ++++++ crv/crvOptimizations.cc | 408 +++++++++++ crv/crvOptimizations.h | 97 +++ crv/crvShape.cc | 114 ++- 17 files changed, 2408 insertions(+), 3538 deletions(-) delete mode 100644 crv/LBFGS.cc delete mode 100644 crv/LBFGS.h create mode 100644 crv/crvDBG.cc create mode 100644 crv/crvDBG.h delete mode 100644 crv/crvEdgeOptim.cc delete mode 100644 crv/crvEdgeOptim.h delete mode 100644 crv/crvFaceOptim.cc delete mode 100644 crv/crvFaceOptim.h delete mode 100644 crv/crvModelEdgeOptim.cc delete mode 100644 crv/crvModelEdgeOptim.h create mode 100644 crv/crvObjectiveFunctions.cc create mode 100644 crv/crvObjectiveFunctions.h create mode 100644 crv/crvOptimizations.cc create mode 100644 crv/crvOptimizations.h diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index b18d8eb15..f58ae61da 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -1,6 +1,7 @@ # Package sources set(SOURCES crv.cc + crvDBG.cc crvAdapt.cc crvBernstein.cc crvBezier.cc @@ -20,19 +21,16 @@ set(SOURCES crvTables.cc crvQuality.cc crvVtk.cc - LBFGS.cc - crvEdgeOptim.cc - crvModelEdgeOptim.cc - crvFaceOptim.cc + crvOptimizations.cc + crvObjectiveFunctions.cc ) # Package headers set(HEADERS crv.h - crvEdgeOptim.h - crvModelEdgeOptim.h - crvFaceOptim.h - LBFGS.h + crvDBG.h + crvOptimizations.h + crvObjectiveFunctions.h crvBezier.h crvTables.h crvQuality.h @@ -47,6 +45,13 @@ target_include_directories(crv INTERFACE $ ) +# TODO: Add these to the higher lever cmake file in a proper form +target_include_directories(crv PUBLIC + "/lore/hakimm2/opt/eigen/include/eigen3" + ) +target_include_directories(crv PUBLIC + "/lore/hakimm2/opt/LBFGSpp/include" + ) # Link this package to these libraries target_link_libraries(crv PUBLIC diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc deleted file mode 100644 index 84f13006f..000000000 --- a/crv/LBFGS.cc +++ /dev/null @@ -1,188 +0,0 @@ -#include "LBFGS.h" -#include -#include "apfMatrix.h" - -namespace crv{ - -//void LBFGS::setInitialValue(std::vector x) -//{ -// x0 = x; -//} - -std::vector LBFGS::getCurrentX() -{ - return currentX; -} - -static double dotP(const std::vector &v1, const std::vector &v2) -{ - double sum = 0.0; - for (std::size_t i = 0; i < v1.size(); i++) { - sum += v1[i]*v2[i]; - } - return sum; -} - -double LBFGS::getFvalueAfter() -{ - return fValAfter; -} - -double LBFGS::lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax) -{ - double alpha = 1.0e-4, tolOndeltaX = 1.0e-8; - int itrs = 2000; - double a, alam, alam2 = 0.0, alamin, b, disc, f2 = 0.0; - double rhs1, rhs2, slope = 0.0, sum = 0.0, temp, test, tmplam; - int n = xold.size(); - - std::vector xnew(xold.size(), 0.0); - sum = sqrt(dotP(direction,direction)); - if (sum > stpmax) { - for (int i = 0; i < n; i++) { - direction[i] = direction[i]*stpmax/sum; - } - } -// for (int i = 0; i < n; i++) slope += g[i]*p[i]; - slope = dotP(g,direction); -//if (slope >= 0.0) std::cout<<"slope positive"< test) test = temp; - } - alamin = tolOndeltaX/test; - alam = 1.0; - - double fold = objFunc->getValue(xold); - - for (int k = 0; k < itrs; k++) { - for (int i =0; i < n; i++) xnew[i] = xold[i] + alam*direction[i]; - - double fnew = objFunc->getValue(xnew); - if (alam < alamin || fnew <= fold + alpha*alam*slope) { - return alam; - } - else { - if (alam == 1.0) - tmplam = -slope/(2.0* (fnew-fold-slope)); - else { - rhs1 = fnew - fold - alam*slope; - rhs2 = f2 - fold - alam2*slope; - a = (rhs1/(alam*alam) - rhs2/(alam2*alam2))/(alam - alam2); - b = (-alam2*rhs1/(alam*alam) + alam*rhs2/(alam2*alam2))/(alam-alam2); - if (a == 0.0) tmplam = -slope/(2.0*b); - else { - disc = b*b - 3.0*a*slope; - if (disc < 0.0) tmplam = 0.5*alam; - else if (b <= 0.0) tmplam = (-b + sqrt(disc))/(3.0*a); - else tmplam = -slope/(b + sqrt(disc)); - } - if (tmplam > 0.5*alam) tmplam = 0.5*alam; - } - } - alam2 = alam; - alam = std::max(tmplam, 0.1*alam); - } - return alam; -} - -void LBFGS::moveArrayToLeft(std::vector a[], int r) -{ - for (int i = 0; i < r-1; i++) - a[i] = a[i+1]; -} - -bool LBFGS::run() -{ - std::vector p(x0.size(), 0.0); - std::vector xs[r]; - std::vector gs[r]; - std::vector gdiffs[r]; - double gammas[r]; - - for(int i = 0; i < r; ++i) - { - xs[i] = std::vector(x0.size(), 0.0); - gs[i] = std::vector(x0.size(), 0.0); - gdiffs[i] = std::vector(x0.size(), 0.0); - gammas[i] = 0.0; - } - - xs[0] = x0; - gs[0] = objFunc->getGrad(x0); - - for (std::size_t i = 0; i < xs[0].size(); i++) p[i] = -gs[0][i]; - - for (int k = 0; k < iter; k++) { - int I = 0; - int J = 0; - if (k+1 < r) { - I = k+1; - J = k; - } - else { - I = r-1; - J = I-1; - moveArrayToLeft(xs, r); - moveArrayToLeft(gs, r); - } - double stpmax = (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); - double lambda = lineSearch(xs[J], gs[J], p, stpmax); - - for (std::size_t j = 0; j < xs[I].size(); j++) - xs[I][j] = xs[J][j] + lambda * p[j]; - - gs[I] = objFunc->getGrad(xs[I]); - - if ( I > 0) { - for (std::size_t jj = 0; jj < gs[I].size(); jj++) - gdiffs[I-1][jj] = gs[I][jj] - gs[I-1][jj]; - } - - if ((dotP(gs[I],gs[I]) < tol) || (dotP(gdiffs[I-1], gdiffs[I-1]) < tol)) { - currentX = xs[I]; - fValAfter = objFunc->getValue(xs[I]); - //std::cout<<"number of LBFGS iterations: "<= 0; --i) { - std::vector s(xs[I].size(), 0.0); - std::vector y(xs[I].size(), 0.0); - for( std::size_t j = 0; j < xs[i+1].size(); j++) { - s[j] = xs[i+1][j] - xs[i][j]; - y[j] = gs[i+1][j] - gs[i][j]; - } - double rho = 1 / dotP(s, y); - gammas[i] = rho * dotP(s, p); - for(std::size_t j = 0; j < p.size(); j++) - p[j] = p[j] - gammas[i]*y[j]; - } - - for (int i = 0; i <= I-1; i++) { - std::vector s(xs[I].size(), 0.0); - std::vector y(xs[I].size(), 0.0); - for( std::size_t j = 0; j < xs[i+1].size(); j++) { - s[j] = xs[i+1][j] - xs[i][j]; - y[j] = gs[i+1][j] - gs[i][j]; - } - double rho = 1 / dotP(s, y); - double phi = rho* dotP(y, p); - for(std::size_t j = 0; j < p.size(); j++) - p[j] = p[j] + s[j]* (gammas[i] - phi); - } - - if (dotP(p, gs[I]) > 0) - for (std::size_t j = 0; j < p.size(); j++) p[j] = -p[j]; - - } - return false; - -} - -} // end of namespace - diff --git a/crv/LBFGS.h b/crv/LBFGS.h deleted file mode 100644 index cf2ebad23..000000000 --- a/crv/LBFGS.h +++ /dev/null @@ -1,56 +0,0 @@ - -#ifndef LBFGS_H -#define LBFGS_H - -#include -#include -#include - -namespace crv{ - -class ObjFunction -{ - public: - ObjFunction(){}; - - public: - virtual double getValue(std::vector &x) = 0; - virtual std::vector getGrad(std::vector &x) = 0; - //virtual int getVectorDim() = 0; - virtual int getSpaceDim() = 0; -}; - -class LBFGS -{ -public: - LBFGS(double inTol, int inIter, const std::vector &x, ObjFunction *inObjFunc): - tol(inTol), iter(inIter), x0(x), objFunc(inObjFunc) - { - //setInitialValue(x0); - } - - ~LBFGS() {} - -public: - //void setInitialValue(std::vector x); - std::vector getCurrentX(); - double getFvalueAfter(); - double lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax); - void moveArrayToLeft(std::vector a[], int r); - bool run(); - -public: - double tol; - int iter; - std::vector x0; - ObjFunction *objFunc; - std::vector currentX; - double fValAfter; - -private: - int r = 40; -}; - -} - -#endif diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index 6be389fa3..bcf212b0b 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -9,10 +9,9 @@ #include "crvBezier.h" #include "crvShape.h" #include "crvSnap.h" -#include #include "crvMath.h" #include -#include "crvFaceOptim.h" +#include namespace crv { diff --git a/crv/crvDBG.cc b/crv/crvDBG.cc new file mode 100644 index 000000000..040824dc3 --- /dev/null +++ b/crv/crvDBG.cc @@ -0,0 +1,337 @@ +#include "crv.h" +#include "crvQuality.h" +#include "crvDBG.h" +#include + + +namespace crv_dbg +{ + +void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e, const char* numberingName) +{ + apf::Numbering* n = m->findNumbering(numberingName); + if (!n) return; + printf("TET:: %d\n", apf::getNumber(n, e, 0, 0)); +} + +void printEdgeCavityInvalidities(apf::Mesh2* m, apf::MeshEntity* e, apf::Numbering* n) +{ + if (n) + printf("entity %d, ", apf::getNumber(n, e, 0, 0)); + else + printf("entity, "); + printf("on model %d\n", m->getModelTag(m->toModel(e))); + apf::Adjacent upTets; + m->getAdjacent(e, 3, upTets); + for (std::size_t i = 0; i < upTets.getSize(); i++) { + std::vector ai = crv::getAllInvalidities(m, upTets[i]); + for (std::size_t j = 0; j < ai.size(); j++) { + printf("%d ", ai[j]); + } + printf("\n"); + } +} + +void visualizeCavityMesh(apf::Mesh2* m, apf::MeshEntity* ent, + const char* prefix, apf::Numbering* n, int resolution) +{ + int num = 0; + if (n) + num = apf::getNumber(n, ent, 0, 0); + + int dim = m->getDimension(); + apf::Adjacent e; + m->getAdjacent(ent, dim, e); + + + gmi_model* g = gmi_load(".null"); + apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); + + apf::MeshEntity* newEnt[99]; + + for (int ii = 0; ii < e.getSize(); ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); + } + + newEnt[ii] = dim == 2 ? newFs[0] : tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); + outMesh->acceptChanges(); + } + apf::changeMeshShape(outMesh, crv::getBezier(3), true); + outMesh->acceptChanges(); + + for (int ii = 0; ii < e.getSize(); ii++) { + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh->getDownward(newEnt[ii], d, new_eds); + int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh->setPoint(new_eds[n], i, p); + } + } + } + outMesh->acceptChanges(); + } + + std::stringstream ss; + ss << prefix<< num; + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, resolution, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, resolution, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh, resolution, ss.str().c_str()); + + outMesh->destroyNative(); + apf::destroyMesh(outMesh); +} + + +void visualizeIndividualCavityEntities(apf::Mesh2* m, apf::MeshEntity* ent, + const char* prefix, apf::Numbering* n, int resolution) +{ + int num = 0; + if (n) + num = apf::getNumber(n, ent, 0, 0); + + int dim = m->getDimension(); + apf::Adjacent e; + m->getAdjacent(ent, dim, e); + + + gmi_model* g = gmi_load(".null"); + + int nat = e.getSize(); + apf::Mesh2* outMesh[nat]; + for (int i = 0; i < nat; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); + } + + apf::MeshEntity* newEnt[nat]; + + for (int ii = 0; ii < nat; ii++) { + // Verts + apf::MeshEntity* vs[12]; + apf::MeshEntity* newVs[12]; + int nv = m->getDownward(e[ii], 0, vs); + for(int i = 0; i < nv; ++i) + { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[i], 0, p); + newVs[i] = outMesh[ii]->createVertex(0, p, param); + } + + // Edges + apf::MeshEntity* es[12]; + apf::MeshEntity* newEs[12]; + int ne = m->getDownward(e[ii], 1, es); + for(int i = 0; i < ne; ++i) + { + apf::MeshEntity* evs[2]; + apf::MeshEntity* new_evs[2]; + m->getDownward(es[i], 0, evs); + for (int j = 0; j < 2; j++) { + new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; + } + + newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); + } + // Faces + apf::MeshEntity* fs[12]; + apf::MeshEntity* newFs[12]; + int nf = m->getDownward(e[ii], 2, fs); + for(int i = 0; i < nf; ++i) + { + apf::MeshEntity* fes[3]; + apf::MeshEntity* new_fes[3]; + m->getDownward(fs[i], 1, fes); + for (int j = 0; j < 3; j++) { + new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; + } + newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); + } + + // Regions + apf::MeshEntity* tet; + if (dim == 3) { + tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); + } + + newEnt[ii] = dim == 2 ? newFs[0] : tet; + + PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); + outMesh[ii]->acceptChanges(); + + apf::changeMeshShape(outMesh[ii], crv::getBezier(m->getShape()->getOrder()), true); + outMesh[ii]->acceptChanges(); + + + for (int d = 1; d <= dim; d++) + { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* eds[12]; + int counter = m->getDownward(e[ii], d, eds); + apf::MeshEntity* new_eds[12]; + outMesh[ii]->getDownward(newEnt[ii], d, new_eds); + int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for(int n = 0; n < counter; ++n) { + for(int i = 0; i < non; ++i) { + apf::Vector3 p; + m->getPoint(eds[n], i, p); + outMesh[ii]->setPoint(new_eds[n], i, p); + } + } + } + outMesh[ii]->acceptChanges(); + + std::stringstream ss; + ss << prefix<< num << "_TET_"<< ii; + crv::writeCurvedVtuFiles(outMesh[ii], apf::Mesh::TET, resolution, ss.str().c_str()); + crv::writeCurvedVtuFiles(outMesh[ii], apf::Mesh::TRIANGLE, resolution, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh[ii], resolution, ss.str().c_str()); + + outMesh[ii]->destroyNative(); + apf::destroyMesh(outMesh[ii]); + } +} + +void visualizeTetFaces(apf::Mesh2* m, apf::MeshEntity* e, const char* prefix, int resolution) +{ + if (m->getType(e) != apf::Mesh::TET) + return; + int dim = 3; + + gmi_model* g = gmi_load(".null"); + + apf::Mesh2* outMesh[4]; + for (int i = 0; i < 4; i++) { + outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); + } + + apf::MeshEntity* face[4]; + apf::MeshEntity* newface[4]; + int nf = m->getDownward(e, 2, face); + + for (int i = 0; i < nf; i++) { + + //Verts + apf::MeshEntity* vs[3]; + apf::MeshEntity* newVs[3]; + int nv = m->getDownward(face[i], 0, vs); + for (int j = 0; j < nv; j++) { + apf::Vector3 p; + apf::Vector3 param(0., 0., 0.); + m->getPoint(vs[j], 0, p); + newVs[j] = outMesh[i]->createVertex(0, p, param); + } + + //Edges + apf::MeshEntity* es[3]; + apf::MeshEntity* newEs[3]; + int ne = m->getDownward(face[i], 1, es); + for (int j = 0; j < ne; j++) { + apf::MeshEntity* evs[2]; + apf::MeshEntity* newEvs[2]; + m->getDownward(es[j], 0, evs); + for (int k = 0; k < 2; k++) { + int kk = apf::findIn(vs,nv, evs[k]); + newEvs[k] = newVs[kk]; + } + newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); + } + + //Faces + apf::MeshEntity* fes[3]; + apf::MeshEntity* newFes[3]; + m->getDownward(face[i], 1, fes); + for (int j = 0; j < 3; j++) + newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; + + newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); + + PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); + + outMesh[i]->acceptChanges(); + + apf::changeMeshShape(outMesh[i], crv::getBezier(m->getShape()->getOrder()), true); + outMesh[i]->acceptChanges(); + + for (int d = 1; d < dim; d++) { + if (!m->getShape()->hasNodesIn(d)) continue; + apf::MeshEntity* ent[12]; + int counter = m->getDownward(face[i], d, ent); + apf::MeshEntity* newent[12]; + outMesh[i]->getDownward(newface[i], d, newent); + int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); + for (int n = 0; n < counter; n++) { + for (int j = 0; j < non; j++) { + apf::Vector3 p; + m->getPoint(ent[n], j, p); + outMesh[i]->setPoint(newent[n], j, p); + } + } + } + + outMesh[i]->acceptChanges(); + + std::stringstream ss; + ss << prefix << "_Face_"<< i; + crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, resolution, ss.str().c_str()); + crv::writeCurvedWireFrame(outMesh[i], resolution, ss.str().c_str()); + } +} + + +} diff --git a/crv/crvDBG.h b/crv/crvDBG.h new file mode 100644 index 000000000..e5254ba18 --- /dev/null +++ b/crv/crvDBG.h @@ -0,0 +1,24 @@ +#ifndef CRVDBG_H +#define CRVDBG_H + +#include +#include +#include +#include + +namespace crv_dbg +{ +void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e, const char* numberingName); +void printCavityInvalidities(apf::Mesh2* m, apf::MeshEntity* e, + apf::Numbering* n = 0); + +void visualizeCavityMesh(apf::Mesh2* m, apf::MeshEntity* ent, + const char* prefix, apf::Numbering* n = 0, int resolution = 8); + +void visualizeIndividualCavityEntities(apf::Mesh2* m, apf::MeshEntity* ent, + const char* prefix, apf::Numbering* n = 0, int resolution = 8); + +void visualizeTetFaces(apf::Mesh2* m, apf::MeshEntity* e, + const char* prefix, int resolution = 8); +} +#endif diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc deleted file mode 100644 index 04c6b40ac..000000000 --- a/crv/crvEdgeOptim.cc +++ /dev/null @@ -1,957 +0,0 @@ -#include "crvEdgeOptim.h" -#include "LBFGS.h" -#include "crv.h" -#include "gmi.h" -#include "apfMDS.h" -#include "apfNumbering.h" -#include "crvQuality.h" -#include "crvBezier.h" -#include "crvMath.h" -#include -#include "apfMatrix.h" - -/* static int global_counter = 0; */ -/* static apf::MeshEntity* tetra[100]; */ -/* static int number = 0; */ - -static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ - //printf("\n"); - //return; - apf::Numbering* n = m->findNumbering("debug_num_tet"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, e, 0, 0); - std::cout<<" TET:: "<< num <findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int tag = m->getModelTag(m->toModel(edge)); - std::cout<<"at edge "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); - for (std::size_t j = 0; j < ai.size(); j++) { - printf("%d ", ai[j]); - } - printf("\n"); - } -} - - -static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) -{ - return; - apf::Numbering* n = m->findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); - - apf::MeshEntity* newEnt[99]; - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); - //printf("HERE 02\n")liver tetrahedral element - outMesh->acceptChanges(); - } - - // std::stringstream ss2; - // ss2 << "straight_sided_" << count; - // apf::writeVtkFiles(ss2.str().c_str(), outMesh); - - apf::changeMeshShape(outMesh, crv::getBezier(3), true); - outMesh->acceptChanges(); - - for (int ii = 0; ii < nat; ii++) { - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh->getDownward(newEnt[ii], d, new_eds); - int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh->setPoint(new_eds[n], i, p); - } - } - } - outMesh->acceptChanges(); - } - - std::stringstream ss; - ss << prefix<< num; - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); - - outMesh->destroyNative(); - apf::destroyMesh(outMesh); -} - -static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) -{ - int dim = 0; - if (m->getType(e) == apf::Mesh::TRIANGLE) { - std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[4]; - for (int i = 0; i < 4; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); - } - - apf::MeshEntity* face[4]; - apf::MeshEntity* newface[4]; - int nf = m->getDownward(e, 2, face); - - for (int i = 0; i < nf; i++) { - - //Verts - apf::MeshEntity* vs[3]; - apf::MeshEntity* newVs[3]; - int nv = m->getDownward(face[i], 0, vs); - for (int j = 0; j < nv; j++) { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[j], 0, p); - newVs[j] = outMesh[i]->createVertex(0, p, param); - } - outMesh[i]->acceptChanges(); - - //Edges - apf::MeshEntity* es[3]; - apf::MeshEntity* newEs[3]; - int ne = m->getDownward(face[i], 1, es); - for (int j = 0; j < ne; j++) { - apf::MeshEntity* evs[2]; - apf::MeshEntity* newEvs[2]; - m->getDownward(es[j], 0, evs); - for (int k = 0; k < 2; k++) { - int kk = apf::findIn(vs,nv, evs[k]); - newEvs[k] = newVs[kk]; - } - - newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); - } - - //Faces - apf::MeshEntity* fes[3]; - apf::MeshEntity* newFes[3]; - m->getDownward(face[i], 1, fes); - for (int j = 0; j < 3; j++) - newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; - - newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); - - PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); - outMesh[i]->acceptChanges(); - - apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); - outMesh[i]->acceptChanges(); - - for (int d = 1; d < dim; d++) { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* ent[10]; - int counter = m->getDownward(face[i], d, ent); - apf::MeshEntity* newent[10]; - outMesh[i]->getDownward(newface[i], d, newent); - int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for (int n = 0; n < counter; n++) { - for (int j = 0; j < non; j++) { - apf::Vector3 p; - m->getPoint(ent[n], j, p); - outMesh[i]->setPoint(newent[n], j, p); - } - } - } - - outMesh[i]->acceptChanges(); - - std::stringstream ss; - ss << prefix << "_Face_"<< i; - crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); - } -} - -static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) -{ - apf::Numbering* n = m->findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[nat]; - for (int i = 0; i < nat; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); - } - - apf::MeshEntity* newEnt[99]; - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh[ii]->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); - outMesh[ii]->acceptChanges(); - - apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); - outMesh[ii]->acceptChanges(); - - - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh[ii]->getDownward(newEnt[ii], d, new_eds); - int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh[ii]->setPoint(new_eds[n], i, p); - } - } - } - outMesh[ii]->acceptChanges(); - - std::stringstream ss; - ss << prefix<< num << "_TET_"<destroyNative(); - //apf::destroyMesh(outMesh[ii]); - - visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); - } -} - - -namespace crv{ - -int CrvEdgeReshapeObjFunc :: getSpaceDim() -{ - return P*d; -} - -void CrvEdgeReshapeObjFunc :: getInitEdgeN() -{ - apf::Vector3 intEdgeX; - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - - for (int i = 0; i < numENodes; i++) { - mesh->getPoint(edge, i, intEdgeX); - ien.push_back(intEdgeX); - } -} - -void CrvEdgeReshapeObjFunc :: getInitFaceN() -{ - apf::Adjacent adjF; - apf::Vector3 intFaceX; - mesh->getAdjacent(edge, 2, adjF); - int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - for (int j = 0; j < numFNodes; j++) { - mesh->getPoint(adjF[i], j, intFaceX); - ifn.push_back(intFaceX); - } - } -} - -void CrvEdgeReshapeObjFunc :: getInitTetN() -{ - apf::Adjacent adjT; - apf::Vector3 intTetX; - mesh->getAdjacent(edge, 3, adjT); - int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - for (int j = 0; j < numTNodes; j++) { - mesh->getPoint(adjT[i], j, intTetX); - itn.push_back(intTetX); - } - } -} - -std::vector CrvEdgeReshapeObjFunc :: getInitialGuess() -{ - return convertNodeVectorToX(ien, ifn, itn); -} - -std::vector CrvEdgeReshapeObjFunc :: convertNodeVectorToX(std::vector en, std::vector fn, std::vector tn) -{ - std::vector x0; - for (int i = 0; i < P-1; i++) - for (int j = 0; j < 3; j++) - x0.push_back(en[i][j]); - - for (std::size_t i = 0; i < fn.size(); i++) - for (int j = 0; j < 3; j++) - x0.push_back(fn[i][j]); - - if (d > 2 && P > 3) { - for (std::size_t i = 0; i < tn.size(); i++) - for (int j = 0; j < 3; j++) - x0.push_back(tn[i][j]); - } - return x0; -} - -std::vector CrvEdgeReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) -{ - std::vector a; - apf::Vector3 v; - if (d == 2) { - std::size_t num = x.size()/d; - //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - //check later for 2D case:: x should not include z coordinate in optim search - for (std::size_t i = 0; i < num; i++) { - v = {x[d*i], x[d*i + 1], 0.0}; - a.push_back(v); - } - } - if (d == 3) { - std::size_t num = x.size()/d; - //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (std::size_t i = 0; i < num; i++) { - v = {x[d*i], x[d*i + 1], x[d*i + 2]}; - a.push_back(v); - } - } - return a; -} - -void CrvEdgeReshapeObjFunc :: blendTris(const std::vector &egn, std::vector &faceNodes) -{ - apf::Vector3 xi; - apf::Adjacent adjF; - apf::Adjacent adjE; - std::vector cien (ien.begin(),ien.end()); - - mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - mesh->getAdjacent(adjF[i], 1, adjE); - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - for (std::size_t j = 0; j < adjE.getSize(); j++) { - if (adjE[j] == edge) { - int jj = 1; - - if ( j == 0) - jj = 2; - else if ( j == 1) - jj = 0; - else - jj = 1; - - for (int k = 0; k < numFNodes; k++) { - getBezierNodeXi(mesh->TRIANGLE, P, k, xi); - for (std::size_t ii = 0; ii < egn.size(); ii++) { - double factor = 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) - + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); - faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - cien[ii])*factor; - } - } - } - } - } -} - -void CrvEdgeReshapeObjFunc :: updateNodes(std::vector ed, std::vector fa, std::vector te) -{ - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < numENodes; i++) - mesh->setPoint(edge, i, ed[i]); - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - for (int j = 0; j < numFNodes; j++) - mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); - } - - if (d == 3 && P > 3) { - apf::Adjacent adjT; - mesh->getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); - for (int j =0; j < numTNodes; j++) - mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); - } - } -} - - -void CrvEdgeReshapeObjFunc :: setNodes(std::vector &x) -{ - std::vector en;// (ien.begin(), ien.end()); - std::vector fn;// (ifn.begin(), ifn.end()); - std::vector tn;// (itn.begin(), itn.end()); - std::vector nod = convertXtoNodeVector(x); - //blendTris(en, fn); - //from all internal node vector to distict vector of nodes - - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i getShape()->countNodesOn(mesh->TRIANGLE); - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - - for (std::size_t i = nEN; i < nEN + nFN*adjF.getSize(); i++) - fn.push_back(nod[i]); - - if (d > 2 && P > 3) { - //int nTN = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = nEN+nFN; i CrvEdgeReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(v); - } - } - if (d == 2) { - apf::Adjacent adjF; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 2, adjF); - apf::Vector3 point; - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjF[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) { - if (k < 2) m[j][k] = point[k]; - else m[j][2] = 1.0; - } - } - double v = getDeterminant(m); - vol.push_back(v); - } - } - return vol; -} - -double CrvEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 2; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["< &x) -{ - setNodes(x); - - double sum = 0.0; - if (d == 2) { - apf::Adjacent adjF; - apf::NewArray allNodes; - mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); - } - -restoreInitialNodes(); - } - - if (d == 3) { - apf::Adjacent adjT; - apf::NewArray allNodes; - mesh->getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); - } -/* - apf::NewArray eCP; - apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); - apf::getVectorNodes(Edl, eCP); - - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - - double xr = 1.0; - double xir = 1.0; - //double alpha = 1.0; - double beta = 0.0; - double ad = 0.0; - apf::Vector3 x1, x0; - apf::Vector3 xi2, xi1, xi0; - - for (int i = 0; i < nEN; i++) { - getBezierNodeXi(mesh->getType(edge), P, i, xi1); - if (i > 0 && i < nEN - 1) { - getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); - getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); - x1 = eCP[2+i+1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[2+i-1]; - xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); - } - else if ( i == 0) { - getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); - x1 = eCP[2+i+1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[0]; - xir = (xi2[0] - xi1[0])/(xi1[0] + 1); // parent coordinate[-1,1] - } - else { - getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); - x1 = eCP[1] - eCP[2+i]; - x0 = eCP[2+i] - eCP[2+i-1]; - xir = (1 - xi1[0])/(xi1[0] - xi0[0]); - } - - // if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) - // alpha = 0.5*(xi1[0]+1.0); - // else - // alpha = 1.0 - 0.5*(xi1[0]+1.0); - - xr = (x1.getLength()/x0.getLength()); - ad = (xr/xir - 1);//(alpha*alpha); - beta = beta + ad*ad; - - //sum = sum + ad*ad; - } - - apf::destroyElement(Edl); -*/ -/* - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - apf::NewArray fCP; - apf::Vector3 xif; - double a[3] = {1.0, 1.0, 1.0}; - double b[3] = {1.0, 1.0, 1.0}; - double aratio = 0.0; - //double wfactor = 1.0; - double gamma = 0.0; - - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(Fal, fCP); - int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - - int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; - - double triAphys = getAr(fCP[0], fCP[1], fCP[2]); - apf::Vector3 prt0 = {1, 0, 0}; - apf::Vector3 prt1 = {0, 1, 0}; - apf::Vector3 prt2 = {0, 0, 1}; - double triAparnt = getAr(prt0, prt1, prt2); - - for (int j = 0; j < nFN; j++) { - getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); - apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; - a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); - b[0] = getAr(xifm, prt0, prt1); - a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); - b[1] = getAr(xifm, prt1, prt2); - a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); - b[2] = getAr(xifm, prt2, prt1); - - //for (int jj = 0; jj < 3; jj++) { - // if (xifm[i] < wfactor) - // wfactor = xifm[i]; - //} - - for (int k = 0; k < 3; k++) { - aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); //(wfactor*wfactor); - gamma = gamma + aratio*aratio; - - //sum = sum + aratio *aratio; - } - } - //sum = sum*(1 + gamma); - //std::cout<<"sum and ratio------ "<< sum <<" "< CrvEdgeReshapeObjFunc :: getGrad(std::vector &x) -{ - //double fold = getValue(x); - double eps = 1.0e-5; - double h = eps; - std::vector g; - double xmx = x[0]; - double xmn = x[0]; - double ymx = x[1]; - double ymn = x[1]; - double zmx = x[2]; - double zmn = x[2]; - double df = 0.0, dff = 0.0, dbb = 0.0; - - for (std::size_t i = 0; i < x.size(); i+=3) { - if (x[i] >= xmx) xmx = x[i]; - if (x[i] <= xmn) xmn = x[i]; - } - - for (std::size_t i = 1; i < x.size(); i+=3) { - if (x[i] >= ymx) ymx = x[i]; - if (x[i] <= ymn) ymn = x[i]; - } - - for (std::size_t i = 2; i < x.size(); i+=3) { - if (x[i] >= zmx) zmx = x[i]; - if (x[i] <= zmn) zmn = x[i]; - } - - double delx = std::abs(xmx - xmn); - double dely = std::abs(ymx - ymn); - double delz = std::abs(zmx - zmn); - double delta = 1.0; - - for (std::size_t i = 0; i < x.size(); i++) { - if (i % 3 == 0) delta = delx; - if (i % 3 == 1) delta = dely; - if (i % 3 == 2) delta = delz; - - h = eps * delta; - - //if (std::abs(x[i]) > eps) - // h = eps * std::abs(x[i]); - //else - // h = eps; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; -/* - dff = (ff - fold)/h; - dbb = (fold - fb)/h; - df = (dff + dbb)/(2.0); -*/ - df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} - -void CrvEdgeOptim :: setMaxIter(int n) -{ - iter = n; -} - -void CrvEdgeOptim :: setTol(double tolerance) -{ - tol = tolerance; -} - -bool CrvEdgeOptim :: run(int &invaliditySize) -{ - std::vector sizeHolder; - apf::MeshEntity* adj_array[99]; - apf::Adjacent adj; - mesh->getAdjacent(edge, 3, adj); - int thisTetSize = 0; - - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; - std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - if (adj[i] == tet) thisTetSize = ai.size(); - sizeHolder.push_back(ai.size()); - - } - - //std::vector ai = crv::getAllInvalidities(mesh, tet); - //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - printTetNumber(mesh, tet); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); - std::vector x0 = objF->getInitialGuess(); - //double f0 = objF->getValue(x0); - //std::cout<< "fval at x0 " << f0<getDownward(adj[i], 1, ed); - int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d edge, TET %d; ", edgeIndex, thisTETnum); - printTetNumber(mesh, adj[i]); - } - - bool hasDecreased = false; - invaliditySize = 0; - - if (l->run() && thisTetSize > 0) { - finalX = l->currentX; - fval = l->fValAfter; - objF->setNodes(finalX); - - - for (int i = 0; i < adj.getSize(); i++) { - std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); - invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); - } - - if (hasDecreased == false ) { - //invaliditySize = 0; - //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - std::cout<<"--------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - std::cout<<"Size DID NOT decrease"<currentX; - //objF->setNodes(finalX); - //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - if (thisTetSize == 0) { - std::cout<<" No Optimization tried"< -#include -#include -#include "apf.h" -#include "apfMesh.h" -#include "apfMesh2.h" -#include "LBFGS.h" -#include "apfShape.h" - -namespace crv{ - -class CrvEdgeReshapeObjFunc : public ObjFunction -{ - public: - CrvEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) - { - P = mesh->getShape()->getOrder(); - d = mesh->getDimension(); - getSpaceDim(); - getVolume(); - getInitEdgeN(); - getInitFaceN(); - getInitTetN(); - } - ~CrvEdgeReshapeObjFunc(){} - - public: - int getSpaceDim(); - double getValue(std::vector &x); - std::vector getGrad(std::vector &x); - std::vector getInitialGuess(); - void setNodes(std::vector &x); - void restoreInitialNodes(); - int P; //order - int d; //dimension - - private: - void getInitEdgeN(); - void getInitFaceN(); - void getInitTetN(); - std::vector convertNodeVectorToX(std::vector en, std::vector fn, std::vector tn); - std::vector convertXtoNodeVector(const std::vector &x); - void blendTris(const std::vector &edgeNodes, std::vector &faceNodes); - //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); - void updateNodes(std::vector ed, std::vector fa, std::vector te); - std::vector getVolume(); - double computeFValOfElement(apf::NewArray &nodes, double volm); - protected: - apf::Mesh2* mesh; - apf::MeshEntity* edge; - apf::MeshEntity* tet; - std::vector vol; - std::vector ien; - std::vector ifn; - std::vector itn; -}; - -class CrvEdgeOptim -{ - public: - CrvEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) {} - ~CrvEdgeOptim(){} - - public: - void setMaxIter(int n); - void setTol(double tolerance); - bool run(int &invaliditySize); - public: - apf::Mesh2* mesh; - apf::MeshEntity* edge; - apf::MeshEntity* tet; - int iter; - double tol; - std::vector finalX; - double fval; -}; -} - -#endif diff --git a/crv/crvFaceOptim.cc b/crv/crvFaceOptim.cc deleted file mode 100644 index 78f25e13d..000000000 --- a/crv/crvFaceOptim.cc +++ /dev/null @@ -1,748 +0,0 @@ -#include "crvFaceOptim.h" -#include "LBFGS.h" -#include "crv.h" -#include "crvQuality.h" -#include "crvBezier.h" -#include "crvMath.h" -#include -#include "apfMatrix.h" -#include "apfNumbering.h" -#include "gmi.h" -#include "apfMDS.h" - -static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ - // printf("\n"); - // return; - apf::Numbering* n = m->findNumbering("debug_num_tet"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, e, 0, 0); - std::cout<<" TET:: "<< num <findNumbering("debug_num_face"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, face, 0, 0); - int tag = m->getModelTag(m->toModel(face)); - std::cout<<"at face "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); - for (std::size_t j = 0; j < ai.size(); j++) { - printf("%d ", ai[j]); - } - printf("\n"); - } -} - -static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, const char* prefix, int nat) -{ - return; - apf::Numbering* n = m->findNumbering("debug_num_face"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, face, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); - - apf::MeshEntity* newEnt[99]; - - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); - //printf("HERE 02\n")liver tetrahedral element - outMesh->acceptChanges(); - } - apf::changeMeshShape(outMesh, crv::getBezier(3), true); - outMesh->acceptChanges(); - - for (int ii = 0; ii < nat; ii++) { - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh->getDownward(newEnt[ii], d, new_eds); - int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh->setPoint(new_eds[n], i, p); - } - } - } - outMesh->acceptChanges(); - } - - std::stringstream ss; - ss << prefix<< num; - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); - - outMesh->destroyNative(); - apf::destroyMesh(outMesh); -} - -static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) -{ - int dim = 0; - if (m->getType(e) == apf::Mesh::TRIANGLE) { - std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[4]; - for (int i = 0; i < 4; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); - } - - apf::MeshEntity* face[4]; - apf::MeshEntity* newface[4]; - int nf = m->getDownward(e, 2, face); - for (int i = 0; i < nf; i++) { - - //Verts - apf::MeshEntity* vs[3]; - apf::MeshEntity* newVs[3]; - int nv = m->getDownward(face[i], 0, vs); - for (int j = 0; j < nv; j++) { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[j], 0, p); - newVs[j] = outMesh[i]->createVertex(0, p, param); - } - outMesh[i]->acceptChanges(); - - //Edges - apf::MeshEntity* es[3]; - apf::MeshEntity* newEs[3]; - int ne = m->getDownward(face[i], 1, es); - for (int j = 0; j < ne; j++) { - apf::MeshEntity* evs[2]; - apf::MeshEntity* newEvs[2]; - m->getDownward(es[j], 0, evs); - for (int k = 0; k < 2; k++) { - int kk = apf::findIn(vs,nv, evs[k]); - newEvs[k] = newVs[kk]; - } - - newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); - } - - //Faces - apf::MeshEntity* fes[3]; - apf::MeshEntity* newFes[3]; - m->getDownward(face[i], 1, fes); - for (int j = 0; j < 3; j++) - newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; - - newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); - - PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); - outMesh[i]->acceptChanges(); - - apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); - outMesh[i]->acceptChanges(); - - for (int d = 1; d < dim; d++) { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* ent[10]; - int counter = m->getDownward(face[i], d, ent); - apf::MeshEntity* newent[10]; - outMesh[i]->getDownward(newface[i], d, newent); - int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for (int n = 0; n < counter; n++) { - for (int j = 0; j < non; j++) { - apf::Vector3 p; - m->getPoint(ent[n], j, p); - outMesh[i]->setPoint(newent[n], j, p); - } - } - } - - outMesh[i]->acceptChanges(); - - std::stringstream ss; - ss << prefix << "_Face_"<< i; - crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); - } -} - -static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, const char* prefix, int nat) -{ - apf::Numbering* n = m->findNumbering("debug_num_face"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, face, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[nat]; - for (int i = 0; i < nat; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); - } - - apf::MeshEntity* newEnt[99]; - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh[ii]->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); - outMesh[ii]->acceptChanges(); - - apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); - outMesh[ii]->acceptChanges(); - - - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh[ii]->getDownward(newEnt[ii], d, new_eds); - int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh[ii]->setPoint(new_eds[n], i, p); - } - } - } - outMesh[ii]->acceptChanges(); - - std::stringstream ss; - ss << prefix<< num << "_TET_"<destroyNative(); - //apf::destroyMesh(outMesh[ii]); - - visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); - } -} - - - - -namespace crv{ - -int CrvFaceReshapeObjFunc :: getSpaceDim() -{ - return P*d; -} - -void CrvFaceReshapeObjFunc :: getInitFaceN() -{ - apf::Vector3 intFaceX; - int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); - for (int j = 0; j < numFNodes; j++) { - mesh->getPoint(face, j, intFaceX); - ifn.push_back(intFaceX); - } -} - -void CrvFaceReshapeObjFunc :: getInitTetN() -{ - apf::Adjacent adjT; - apf::Vector3 intTetX; - mesh->getAdjacent(face, 3, adjT); - int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - for (int j = 0; j < numTNodes; j++) { - mesh->getPoint(adjT[i], j, intTetX); - itn.push_back(intTetX); - } - } -} - -std::vector CrvFaceReshapeObjFunc :: getInitialGuess() -{ - return convertNodeVectorToX(ifn); -} - -std::vector CrvFaceReshapeObjFunc :: convertNodeVectorToX(std::vector fn) -{ - std::vector x0; - - for (std::size_t i = 0; i < fn.size(); i++) - for (int j = 0; j < 3; j++) - x0.push_back(fn[i][j]); - - return x0; -} - -std::vector CrvFaceReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) -{ - std::vector a; - apf::Vector3 v; - std::size_t num = x.size()/d; - //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (std::size_t i = 0; i < num; i++) { - v = {x[d*i], x[d*i + 1], x[d*i + 2]}; - a.push_back(v); - } - - return a; -} - -void CrvFaceReshapeObjFunc :: updateNodes(std::vector fa, std::vector te) -{ - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(face)); - for (int j = 0; j < numFNodes; j++) - mesh->setPoint(face, j, fa[j]); - - if (d == 3 && P > 3) { - apf::Adjacent adjT; - mesh->getAdjacent(face, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); - for (int j =0; j < numTNodes; j++) - mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); - } - } -} - -void CrvFaceReshapeObjFunc :: setNodes(std::vector &x) -{ - std::vector fn;// (ifn.begin(), ifn.end()); - std::vector tn;// (itn.begin(), itn.end()); - std::vector nod = convertXtoNodeVector(x); - //blendTris(en, fn); - //from all internal node vector to distict vector of nodes - - int nFN = mesh->getShape()->countNodesOn(mesh->getType(face)); - for (int i = 0; i 2 && P > 3) { - //int nTN = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = nFN; i CrvFaceReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(face, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(v); - } - } - return vol; -} - -static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) -{ - p1 = p1 - p0; - p2 = p2 - p0; - double area = (apf::cross(p1, p2)).getLength(); - return (area/2.0); -} - -double CrvFaceReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 6; - else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 3; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double fun = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["< &x) -{ - setNodes(x); - - double sum = 0.0; - - if (d == 3) { - apf::Adjacent adjT; - apf::NewArray allNodes; - mesh->getAdjacent(face, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); - } -/* - apf::NewArray fCP; - apf::Vector3 xif; - double a[3] = {1.0, 1.0, 1.0}; - double b[3] = {1.0, 1.0, 1.0}; - double aratio = 0.0; - //double wfactor = 1.0; - double gamma = 0.0; - - apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), face); - apf::getVectorNodes(Fal, fCP); - int nFN = mesh->getShape()->countNodesOn(mesh->getType(face)); - - int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; - - double triAphys = getAr(fCP[0], fCP[1], fCP[2]); - apf::Vector3 prt0 = {1, 0, 0}; - apf::Vector3 prt1 = {0, 1, 0}; - apf::Vector3 prt2 = {0, 0, 1}; - double triAparnt = getAr(prt0, prt1, prt2); - - for (int j = 0; j < nFN; j++) { - getBezierNodeXi(mesh->getType(face), P, j, xif); - apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; - a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); - b[0] = getAr(xifm, prt0, prt1); - a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); - b[1] = getAr(xifm, prt1, prt2); - a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); - b[2] = getAr(xifm, prt2, prt1); - - for (int k = 0; k < 3; k++) { - aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); - gamma = gamma + aratio*aratio; - } - } - - apf::destroyElement(Fal); - - sum = sum*(1 + gamma); - */ - restoreInitialNodes(); - } - return sum; -} - -std::vector CrvFaceReshapeObjFunc :: getGrad(std::vector &x) -{ - //double fold = getValue(x); - double eps = 1.0e-4; - double h = eps; - std::vector g; - double xmx = x[0]; - double xmn = x[0]; - double ymx = x[1]; - double ymn = x[1]; - double zmx = x[2]; - double zmn = x[2]; - double df = 0.0, dff = 0.0, dbb = 0.0; - - for (std::size_t i = 0; i < x.size(); i+=3) { - if (x[i] >= xmx) xmx = x[i]; - if (x[i] <= xmn) xmn = x[i]; - } - - for (std::size_t i = 1; i < x.size(); i+=3) { - if (x[i] >= ymx) ymx = x[i]; - if (x[i] <= ymn) ymn = x[i]; - } - - for (std::size_t i = 2; i < x.size(); i+=3) { - if (x[i] >= zmx) zmx = x[i]; - if (x[i] <= zmn) zmn = x[i]; - } - - double delx = std::abs(xmx - xmn); - double dely = std::abs(ymx - ymn); - double delz = std::abs(zmx - zmn); - double delta = 1.0; - - for (std::size_t i = 0; i < x.size(); i++) { - if (i % 3 == 0) delta = delx; - if (i % 3 == 1) delta = dely; - if (i % 3 == 2) delta = delz; - - if (delta < eps) - h = eps * std::abs(x[i]); - else - h = eps * delta; - - //if (std::abs(x[i]) > eps) - // h = eps * std::abs(x[i]); - //else - // h = eps; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; - - df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} - -void CrvFaceOptim :: setMaxIter(int n) -{ - iter = n; -} - -void CrvFaceOptim :: setTol(double tolerance) -{ - tol = tolerance; -} - -bool CrvFaceOptim :: run(int &invaliditySize) -{ - std::vector sizeHolder; - apf::MeshEntity* adj_array[99]; - apf::Adjacent adj; - mesh->getAdjacent(face, 3, adj); - int thisTetSize = 0; - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; - //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - //if (adj[i] == tet) thisTetSize = ai.size(); - //sizeHolder.push_back(ai.size()); - } - - std::vector ai = crv::getAllInvalidities(mesh, tet); - invaliditySize = ai.size(); - //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); - printTetNumber(mesh, tet); - printInvalidities(mesh, adj_array, face, adj.getSize()); - CrvFaceReshapeObjFunc *objF = new CrvFaceReshapeObjFunc(mesh, face, tet); - std::vector x0 = objF->getInitialGuess(); - //double f0 = objF->getValue(x0); - //std::cout<< "fval at x0 " << f0<getDownward(adj[i], 2, fc); - int faceIndex = apf::findIn(fc, 4, face); - printf("reshape tried on %d face, TET %d ",faceIndex, thisTETnum); - printTetNumber(mesh, adj[i]); - } - - //bool hasDecreased = false; - //invaliditySize = 0; - - //if (l->run() && thisTetSize > 0) { - if (l->run() && invaliditySize > 0) { - finalX = l->currentX; - fval = l->fValAfter; - objF->setNodes(finalX); - - std::vector aiNew = crv::getAllInvalidities(mesh, tet); - /* - for (int i = 0; i < adj.getSize(); i++) { - std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); - invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); - } -*/ - // if (hasDecreased == false ) { - if (aiNew.size() <= invaliditySize) { - invaliditySize = aiNew.size(); - //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); - printInvalidities(mesh, adj_array, face, adj.getSize()); - std::cout<<"----------------------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, face, adj.getSize()); - std::cout<<"Size didNOT decrease"< -#include -#include -#include "apf.h" -#include "apfMesh.h" -#include "apfMesh2.h" -#include "LBFGS.h" -#include "apfShape.h" - -namespace crv{ - -class CrvFaceReshapeObjFunc : public ObjFunction -{ - public: - CrvFaceReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : - mesh(m), face(f), tet(t) - { - P = mesh->getShape()->getOrder(); - d = mesh->getDimension(); - getSpaceDim(); - getVolume(); - getInitFaceN(); - getInitTetN(); - } - ~CrvFaceReshapeObjFunc() {} - - public: - int getSpaceDim(); - double getValue(std::vector &x); - std::vector getGrad(std::vector &x); - std::vector getInitialGuess(); - void setNodes(std::vector &x); - void restoreInitialNodes(); - int P; //order - int d; //dimension - - private: - void getInitFaceN(); - void getInitTetN(); - std::vector convertNodeVectorToX(std::vector fn); - std::vector convertXtoNodeVector(const std::vector &x); - //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); - void updateNodes(std::vector fa, std::vector te); - std::vector getVolume(); - double computeFValOfElement(apf::NewArray &nodes, double volm); - protected: - apf::Mesh2* mesh; - apf::MeshEntity* face; - apf::MeshEntity* tet; - std::vector vol; - std::vector ifn; - std::vector itn; -}; - -class CrvFaceOptim -{ - public: - CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : - mesh(m), face(f), tet(t) {} - ~CrvFaceOptim(){} - - public: - void setMaxIter(int n); - void setTol(double tolerance); - bool run(int &invaliditySize); - public: - apf::Mesh2* mesh; - apf::MeshEntity* face; - apf::MeshEntity* tet; - int iter; - double tol; - std::vector finalX; - double fval; -}; -} - -#endif diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc deleted file mode 100644 index 4da5c77d5..000000000 --- a/crv/crvModelEdgeOptim.cc +++ /dev/null @@ -1,1260 +0,0 @@ -#include "crvModelEdgeOptim.h" -#include "LBFGS.h" -#include "crv.h" -#include "gmi.h" -#include "apfMDS.h" -#include "apfNumbering.h" -#include "crvQuality.h" -#include "crvBezier.h" -#include "crvBezierShapes.h" -#include "crvTables.h" -#include "crvSnap.h" -#include "crvMath.h" -#include -#include "apfMatrix.h" -#include - -static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) -{ - //printf("\n"); - //return; - apf::Numbering* n = m->findNumbering("debug_num_tet"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, e, 0, 0); - std::cout<<" TET:: "<< num <findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int tag = m->getModelTag(m->toModel(edge)); - std::cout<<"at edge "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); - for (std::size_t j = 0; j < ai.size(); j++) { - printf("%d ", ai[j]); - } - printf("\n"); - } -} - - -static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) -{ - return; - apf::Numbering* n = m->findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - apf::Mesh2* outMesh = apf::makeEmptyMdsMesh(g, dim, false); - - apf::MeshEntity* newEnt[99]; - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh->getType(newEnt[ii])); - //printf("HERE 02\n")liver tetrahedral element - outMesh->acceptChanges(); - } - - // std::stringstream ss2; - // ss2 << "straight_sided_" << count; - // apf::writeVtkFiles(ss2.str().c_str(), outMesh); - - apf::changeMeshShape(outMesh, crv::getBezier(3), true); - outMesh->acceptChanges(); - - for (int ii = 0; ii < nat; ii++) { - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh->getDownward(newEnt[ii], d, new_eds); - int non = outMesh->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh->setPoint(new_eds[n], i, p); - } - } - } - outMesh->acceptChanges(); - } - - std::stringstream ss; - ss << prefix<< num; - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TET, 8, ss.str().c_str()); - crv::writeCurvedVtuFiles(outMesh, apf::Mesh::TRIANGLE, 8, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh, 8, ss.str().c_str()); - - outMesh->destroyNative(); - apf::destroyMesh(outMesh); -} - -static void visualizeAllFacesOfTet(apf::Mesh2* m, apf::MeshEntity* e, int count, const char* prefix) -{ - int dim = 0; - if (m->getType(e) == apf::Mesh::TRIANGLE) { - std::cout<<"the entity is not a TET"<getType(e) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[4]; - for (int i = 0; i < 4; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, 2, false); - } - - apf::MeshEntity* face[4]; - apf::MeshEntity* newface[4]; - int nf = m->getDownward(e, 2, face); - for (int i = 0; i < nf; i++) { - - //Verts - apf::MeshEntity* vs[3]; - apf::MeshEntity* newVs[3]; - int nv = m->getDownward(face[i], 0, vs); - for (int j = 0; j < nv; j++) { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[j], 0, p); - newVs[j] = outMesh[i]->createVertex(0, p, param); - } - outMesh[i]->acceptChanges(); - - //Edges - apf::MeshEntity* es[3]; - apf::MeshEntity* newEs[3]; - int ne = m->getDownward(face[i], 1, es); - for (int j = 0; j < ne; j++) { - apf::MeshEntity* evs[2]; - apf::MeshEntity* newEvs[2]; - m->getDownward(es[j], 0, evs); - for (int k = 0; k < 2; k++) { - int kk = apf::findIn(vs,nv, evs[k]); - newEvs[k] = newVs[kk]; - } - - newEs[j] = outMesh[i]->createEntity(apf::Mesh::EDGE, 0, newEvs); - } - - //Faces - apf::MeshEntity* fes[3]; - apf::MeshEntity* newFes[3]; - m->getDownward(face[i], 1, fes); - for (int j = 0; j < 3; j++) - newFes[j] = newEs[apf::findIn(es, ne, fes[j])]; - - newface[i] = outMesh[i]->createEntity(apf::Mesh::TRIANGLE, 0, newFes); - - PCU_ALWAYS_ASSERT(m->getType(face[i]) == outMesh[i]->getType(newface[i])); - outMesh[i]->acceptChanges(); - - apf::changeMeshShape(outMesh[i], crv::getBezier(3), true); - outMesh[i]->acceptChanges(); - - for (int d = 1; d < dim; d++) { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* ent[10]; - int counter = m->getDownward(face[i], d, ent); - apf::MeshEntity* newent[10]; - outMesh[i]->getDownward(newface[i], d, newent); - int non = outMesh[i]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for (int n = 0; n < counter; n++) { - for (int j = 0; j < non; j++) { - apf::Vector3 p; - m->getPoint(ent[n], j, p); - outMesh[i]->setPoint(newent[n], j, p); - } - } - } - - outMesh[i]->acceptChanges(); - - std::stringstream ss; - ss << prefix << "_Face_"<< i; - crv::writeCurvedVtuFiles(outMesh[i], apf::Mesh::TRIANGLE, 40, ss.str().c_str()); - crv::writeCurvedWireFrame(outMesh[i], 50, ss.str().c_str()); - } -} - -static void makeIndividualTetsFromFacesOrEdges(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) -{ - apf::Numbering* n = m->findNumbering("debug_num_edge"); - PCU_ALWAYS_ASSERT(n); - int num = apf::getNumber(n, edge, 0, 0); - int dim = 0; - if (m->getType(e[0]) == apf::Mesh::TRIANGLE) - dim = 2; - else if (m->getType(e[0]) == apf::Mesh::TET) - dim = 3; - else - PCU_ALWAYS_ASSERT(0); - - gmi_model* g = gmi_load(".null"); - - apf::Mesh2* outMesh[nat]; - for (int i = 0; i < nat; i++) { - outMesh[i] = apf::makeEmptyMdsMesh(g, dim, false); - } - - apf::MeshEntity* newEnt[99]; - - for (int ii = 0; ii < nat; ii++) { - // Verts - apf::MeshEntity* vs[12]; - apf::MeshEntity* newVs[12]; - int nv = m->getDownward(e[ii], 0, vs); - for(int i = 0; i < nv; ++i) - { - apf::Vector3 p; - apf::Vector3 param(0., 0., 0.); - m->getPoint(vs[i], 0, p); - newVs[i] = outMesh[ii]->createVertex(0, p, param); - } - - // Edges - apf::MeshEntity* es[12]; - apf::MeshEntity* newEs[12]; - int ne = m->getDownward(e[ii], 1, es); - for(int i = 0; i < ne; ++i) - { - apf::MeshEntity* evs[2]; - apf::MeshEntity* new_evs[2]; - m->getDownward(es[i], 0, evs); - for (int j = 0; j < 2; j++) { - new_evs[j] = newVs[apf::findIn(vs, nv, evs[j])]; - } - - newEs[i] = outMesh[ii]->createEntity(apf::Mesh::EDGE, 0, new_evs); - } - // Faces - apf::MeshEntity* fs[12]; - apf::MeshEntity* newFs[12]; - int nf = m->getDownward(e[ii], 2, fs); - for(int i = 0; i < nf; ++i) - { - apf::MeshEntity* fes[3]; - apf::MeshEntity* new_fes[3]; - m->getDownward(fs[i], 1, fes); - for (int j = 0; j < 3; j++) { - new_fes[j] = newEs[apf::findIn(es, ne, fes[j])]; - } - newFs[i] = outMesh[ii]->createEntity(apf::Mesh::TRIANGLE, 0, new_fes); - } - - // Regions - apf::MeshEntity* tet; - if (dim == 3) { - tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); - } - - if (dim == 2) - newEnt[ii] = newFs[0]; - else - newEnt[ii] = tet; - - PCU_ALWAYS_ASSERT(m->getType(e[ii]) == outMesh[ii]->getType(newEnt[ii])); - outMesh[ii]->acceptChanges(); - - apf::changeMeshShape(outMesh[ii], crv::getBezier(3), true); - outMesh[ii]->acceptChanges(); - - - for (int d = 1; d <= dim; d++) - { - if (!m->getShape()->hasNodesIn(d)) continue; - apf::MeshEntity* eds[12]; - int counter = m->getDownward(e[ii], d, eds); - apf::MeshEntity* new_eds[12]; - outMesh[ii]->getDownward(newEnt[ii], d, new_eds); - int non = outMesh[ii]->getShape()->countNodesOn(apf::Mesh::simplexTypes[d]); - for(int n = 0; n < counter; ++n) { - for(int i = 0; i < non; ++i) { - apf::Vector3 p; - m->getPoint(eds[n], i, p); - outMesh[ii]->setPoint(new_eds[n], i, p); - } - } - } - outMesh[ii]->acceptChanges(); - - std::stringstream ss; - ss << prefix<< num << "_TET_"<destroyNative(); - //apf::destroyMesh(outMesh[ii]); - - visualizeAllFacesOfTet(m, e[ii], ii, ss.str().c_str()); - } -} - -namespace crv{ - -int CrvModelEdgeReshapeObjFunc :: getSpaceDim() -{ - return P*d; -} - -void CrvModelEdgeReshapeObjFunc :: getInitEdgeN() -{ - apf::Vector3 intEdgeX; - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - - for (int i = 0; i < numENodes; i++) { - mesh->getPoint(edge, i, intEdgeX); - ien.push_back(intEdgeX); - } -} - -apf::Vector3 getInterpolatingPointOnFace(apf::Mesh* mesh, apf::MeshEntity* face, int odr, int whichNode) -{ - std::vector faceIp; - apf::Vector3 xi; - apf::NewArray allCntrlP; - apf::Element* Fa = apf::createElement(mesh->getCoordinateField(), face); - apf::getVectorNodes(Fa, allCntrlP); - - int nFn = mesh->getShape()->countNodesOn(mesh->getType(face)); - apf::Vector3 blTri; - //apf::NewArray rhs(n); - int j = 0; - - getBezierNodeXi(apf::Mesh::TRIANGLE, odr, whichNode, xi); - blTri.zero(); - - for (int ii = 0; ii < odr+1; ii++) { - for (int jj = 0; jj < odr+1-ii; jj++) { - double bFactor = trinomial(odr, ii, jj) * Bijk(ii, jj, odr-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); - blTri = blTri + allCntrlP[getTriNodeIndex(odr, ii, jj)] * bFactor; - } - } - - apf::destroyElement(Fa); - return blTri; -} - -void CrvModelEdgeReshapeObjFunc :: getInitFaceN() -{ - apf::Adjacent adjF; - apf::Vector3 intFaceX; - apf::Vector3 ipFN; - mesh->getAdjacent(edge, 2, adjF); - int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - for (int j = 0; j < numFNodes; j++) { - mesh->getPoint(adjF[i], j, intFaceX); - ifn.push_back(intFaceX); - //ipFN = getInterpolatingPointOnFace(mesh, adjF[i], P, j); - //itpfn.push_back(ipFN); - } - } -} - -void CrvModelEdgeReshapeObjFunc :: getInitTetN() -{ - apf::Adjacent adjT; - apf::Vector3 intTetX; - mesh->getAdjacent(edge, 3, adjT); - int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - for (int j = 0; j < numTNodes; j++) { - mesh->getPoint(adjT[i], j, intTetX); - itn.push_back(intTetX); - } - } -} - -std::vector CrvModelEdgeReshapeObjFunc :: getParamCoords() -{ - apf::Vector3 xi; - apf::Vector3 param; - std::vector xp; - - int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < numENodes; i++) { - getBezierNodeXi(mesh->getType(edge), P, i, xi); - transferParametricOnEdgeSplit(mesh, edge, 0.5*(xi[0]+1.0), param); - for (int j = 0; j < 3; j++) { - xp.push_back(param[j]); - } - } - - apf::Vector3 xif; - apf::Vector3 paramf; - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - for (int j = 0; j < numFNodes; j++) { - getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); - transferParametricOnTriSplit(mesh, adjF[i], xif, paramf); - for (int k = 0; k < 3; k++) { - xp.push_back(paramf[k]); - } - } - } - else { - apf::Vector3 intFN; - for (int j = 0; j < numFNodes; j++) { - mesh->getPoint(adjF[i], j, intFN); - for (int k = 0; k < 3; k++) - xp.push_back(intFN[k]); - } - } - } - - return xp; -} - -std::vector CrvModelEdgeReshapeObjFunc :: convertParamCoordsToNodeVector(const std::vector &x) -{ - apf::ModelEntity* me = mesh->toModel(edge); - std::vector edn; - std::vector vn = convertXtoNodeVector(x); - int nENodes = mesh->getShape()->countNodesOn(mesh->EDGE); - for (int i = 0; i < nENodes; i++) { - apf::Vector3 coorde; - mesh->snapToModel(me, vn[i], coorde); - edn.push_back(coorde); - } - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - int numFNTotal = 0; - for (std::size_t i = 0; i < adjF.getSize(); i++) { - int nFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - apf::ModelEntity* mef = mesh->toModel(adjF[i]); - for (int j = 0; j < nFNodes; j++) { - apf::Vector3 coordf; - mesh->snapToModel(mef, vn[nENodes+numFNTotal], coordf); - edn.push_back(coordf); - numFNTotal++; - } - } - else { - for (int j = 0; j < nFNodes; j++) { - edn.push_back(vn[nENodes+numFNTotal]); - numFNTotal++; - } - } - - } - - return edn; -} - -std::vector CrvModelEdgeReshapeObjFunc :: getInitialGuess() -{ - return getParamCoords(); -} - -std::vector CrvModelEdgeReshapeObjFunc :: convertXtoNodeVector(const std::vector &x) -{ - std::vector a; - apf::Vector3 v; - - if (d == 3) { - std::size_t num = x.size()/d; - //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (std::size_t i = 0; i < num; i++) { - v = {x[d*i], x[d*i + 1], x[d*i + 2]}; - a.push_back(v); - } - } - return a; -} - -void CrvModelEdgeReshapeObjFunc :: blendTris(const std::vector &egn, std::vector &faceNodes) -{ - apf::Vector3 xi; - apf::Adjacent adjF; - apf::Adjacent adjE; - - mesh->getAdjacent(edge, 2, adjF); - - for (std::size_t i = 0; i < adjF.getSize(); i++) { - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - mesh->getAdjacent(adjF[i], 1, adjE); - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - - for (std::size_t j = 0; j < adjE.getSize(); j++) { - if (adjE[j] == edge) { - int jj = 1; - - if ( j == 0) - jj = 2; - else if ( j == 1) - jj = 0; - else - jj = 1; - - for (int k = 0; k < numFNodes; k++) { - getBezierNodeXi(mesh->TRIANGLE, P, k, xi); - for (std::size_t ii = 0; ii < egn.size(); ii++) { - double factor = 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) - + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); - faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - ien[ii])*factor; - } - } - } - } - } - } -} - -std::vector CrvModelEdgeReshapeObjFunc :: getFaceControlPointsFromInterpolatingPoints(apf::MeshEntity* face, const std::vector &faceInterpolatingP) -{ - std::vector faceControlP; - apf::Vector3 xi; - apf::NewArray allCntrlP; - apf::Element* Fa = apf::createElement(mesh->getCoordinateField(), face); - apf::getVectorNodes(Fa, allCntrlP); - - int n = mesh->getShape()->countNodesOn(mesh->getType(face)); - mth::Matrix A(n, n); - mth::Matrix Ainv(n, n); - apf::NewArray rhs(n); - int j = 0; - - for (int i = 0; i < n; i++) { - getBezierNodeXi(apf::Mesh::TRIANGLE, P, i, xi); - rhs[i].zero(); - for (int ii = 0; ii < P+1; ii++) { - for (int jj = 0; jj < P+1-ii; jj++) { - if (ii == 0 || jj == 0 || (ii+jj == P)) { - double bFactor = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); - rhs[i] += allCntrlP[getTriNodeIndex(P, ii, jj)] * bFactor; - } - else { - j = getTriNodeIndex(P, ii, jj) - 3*P; //3P is the total number of nodes on all edges - A(i, j) = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); - } - } - } - rhs[i] = faceInterpolatingP[i] - rhs[i]; - } - apf::destroyElement(Fa); - - if (n > 1) - invertMatrixWithPLU(n, A, Ainv); - else - Ainv(0,0) = 1./A(0,0); - - for (int i = 0; i < n; i++) { - apf::Vector3 fcp(0., 0., 0.); - for (int j = 0; j < n; j++) - fcp += rhs[j]*Ainv(i, j); - faceControlP.push_back(fcp); - } - - return faceControlP; -} - -void CrvModelEdgeReshapeObjFunc :: updateNodes(std::vector ed, std::vector fa, std::vector te, bool isInitialX) -{ - if (!isInitialX) { - apf::NewArray eIntpCords; - apf::Element* Ed = apf::createElement(mesh->getCoordinateField(), edge); - apf::getVectorNodes(Ed, eIntpCords); - apf::NewArray trsCoff; - - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - apf::NewArray contP(nEN); - - for (int i = 0; i < nEN; i++) { - for (int j = 0; j < 3; j++) - eIntpCords[2+i][j] = ed[i][j]; - } - - getBezierTransformationCoefficients(P, mesh->getType(edge), trsCoff); - crv::convertInterpolationPoints(nEN+2, nEN, eIntpCords, trsCoff, contP); - - for (int i = 0; i < nEN; i++) - mesh->setPoint(edge, i, contP[i]); - - apf::destroyElement(Ed); - } - else { - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < nEN; i++) - mesh->setPoint(edge, i, ed[i]); - } - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - std::vector fNd; - - if (!isInitialX) { - for (std::size_t i = 0; i < adjF.getSize(); i++) { - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - fNd.clear(); - - for (int j = 0; j < numFNodes; j++) - fNd.push_back(fa[numFNodes*i + j]); - - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - std::vector fCN = getFaceControlPointsFromInterpolatingPoints(adjF[i], fNd); - - for (int j = 0; j < numFNodes; j++) - mesh->setPoint(adjF[i], j, fCN[j]); - } - else { - for (int j = 0; j < numFNodes; j++) - mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); - } - } - } - else { - for (std::size_t i = 0; i < adjF.getSize(); i++) { - int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - for (int j = 0; j < numFNodes; j++) - mesh->setPoint(adjF[i], j, fa[numFNodes*i+j]); - } - } - - if (d == 3 && P > 3) { - apf::Adjacent adjT; - mesh->getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); - for (int j =0; j < numTNodes; j++) - mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); - } - } - - apf::synchronize(mesh->getCoordinateField()); -} - -void CrvModelEdgeReshapeObjFunc :: setNodes(std::vector &x) -{ - std::vector en; - std::vector fn; - std::vector tn; - std::vector nod = convertParamCoordsToNodeVector(x); - //std::vector fnewN; - - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - for (int i = 0; i < nEN; i++) - en.push_back(nod[i]); - - //for (size_t i = 0; i < itpfn.size(); i++) - // fnewN.push_back(itpfn[i]); - - //blendTris(en, fnewN); - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - int kk = 0; - int nFN = mesh->getShape()->countNodesOn(mesh->TRIANGLE); - - for (std::size_t i = 0; i < adjF.getSize(); i++) { - for (int j = 0; j < nFN; j++) - fn.push_back(nod[nEN+i*nFN+j]); - } - - if (d > 2 && P > 3) { - //int nTN = mesh->getShape()->countNodesOn(mesh->TET); - for (std::size_t i = nEN+nFN; i CrvModelEdgeReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(std::abs(v)); - } - } - if (d == 2) { - apf::Adjacent adjF; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 2, adjF); - apf::Vector3 point; - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjF[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) { - if (k < 2) m[j][k] = point[k]; - else m[j][2] = 1.0; - } - } - double v = getDeterminant(m); - vol.push_back(v); - } - } - return vol; -} - -static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) -{ - p1 = p1 - p0; - p2 = p2 - p0; - double area = (apf::cross(p1, p2)).getLength(); - return (area/2.0); -} - -static double getArea(apf::Mesh* mesh, apf::MeshEntity* e) -{ - apf::MeshEntity* ver[3]; - mesh->getDownward(e, 0, ver); - apf::Vector3 point0, point1, point2; - - mesh->getPoint(ver[0], 0, point0); - mesh->getPoint(ver[1], 0, point1); - mesh->getPoint(ver[2], 0, point2); - - point1 = point1 - point0; - point2 = point2 - point0; - - double area = (apf::cross(point1, point2)).getLength(); - - return (area/2.0); -} - - -double CrvModelEdgeReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 2; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["< &x) -{ - setNodes(x); - - double sum = 0.0; - if (d == 2) { - apf::Adjacent adjF; - apf::NewArray allNodes; - mesh->getAdjacent(edge, 2, adjF); - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); - } - - restoreInitialNodes(); - } - - if (d == 3) { - apf::Adjacent adjT; - apf::NewArray allNodes; - mesh->getAdjacent(edge, 3, adjT); - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); - } - - /* apf::NewArray eCP; */ - /* apf::Element* Edl = apf::createElement(mesh->getCoordinateField(), edge); */ - /* apf::getVectorNodes(Edl, eCP); */ - /* int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); */ - /* double xr = 1.0; */ - /* double xir = 1.0; */ - /* //double alpha = 1.0; */ - /* double ad = 0.0; */ - /* apf::Vector3 x1, x0; */ - /* apf::Vector3 xi2, xi1, xi0; */ - /* double beta = 0.0; */ - - /* apf::MeshElement* mEdl = apf::createMeshElement(mesh, edge); */ - /* for (int i = 0; i getType(edge), P, i, xi1); */ - /* apf::mapLocalToGlobal(mEdl, xi1, scord); */ - /* eCP[2+i] = scord; */ - /* } */ - /* apf::destroyMeshElement(mEdl); */ - - double ad = 0.0; - double xr = 1.0; - double xir = 1.0; - int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); - double beta = 0.0; - std::vector xs; - xs.clear(); - std::vector xis; - xis.clear(); - xis.push_back(apf::Vector3(-1.0, 0.0, 0.0)); - for (int i = 0; i getType(edge), P, i, currentXi); - xis.push_back(currentXi); - } - xis.push_back(apf::Vector3(+1.0, 0.0, 0.0)); - - apf::MeshElement* me = apf::createMeshElement(mesh, edge); - for (int i = 0; i < xis.size(); i++) { - apf::Vector3 scord; - apf::mapLocalToGlobal(me, xis[i], scord); - xs.push_back(scord); - } - apf::destroyMeshElement(me); - - - - /* for (int i = 0; i < nEN; i++) { */ - /* getBezierNodeXi(mesh->getType(edge), P, i, xi1); */ - /* if (i > 0 && i < nEN - 1) { */ - /* getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); */ - /* getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); */ - /* x1 = eCP[2+i+1] - eCP[2+i]; */ - /* x0 = eCP[2+i] - eCP[2+i-1]; */ - /* xir = (xi2[0] - xi1[0])/(xi1[0] - xi0[0]); */ - /* } */ - /* else if ( i == 0) { */ - /* getBezierNodeXi(mesh->getType(edge), P, i+1, xi2); */ - /* x1 = eCP[2+i+1] - eCP[2+i]; */ - /* x0 = eCP[2+i] - eCP[0]; */ - /* xir = (xi2[0] - xi1[0])/(xi1[0] + 1.0); // parent coordinate[-1,1] */ - /* } */ - /* else { */ - /* getBezierNodeXi(mesh->getType(edge), P, i-1, xi0); */ - /* x1 = eCP[1] - eCP[2+i]; */ - /* x0 = eCP[2+i] - eCP[2+i-1]; */ - /* xir = (1.0 - xi1[0])/(xi1[0] - xi0[0]); */ - /* } */ - - /* //if (0.5*(xi1[0]+1.0) < 1.0 - 0.5*(xi1[0]+1.0)) */ - /* // alpha = 0.5*(xi1[0]+1.0); */ - /* //else */ - /* // alpha = 1.0 - 0.5*(xi1[0]+1.0); */ - - /* xr = (x1.getLength()/x0.getLength()); */ - /* ad = (1.0*xr/xir - 1.0); //(alpha*alpha); */ - /* beta = beta + ad*ad; */ - /* //sum = sum + ad*ad; */ - /* } */ - - for (int i = 1; i < xs.size()-1; i++) { - - xr = (xs[i] - xs[0]).getLength() / - (xs[xs.size()-1] - xs[0]).getLength(); - xir = (xis[i] - xis[0]).getLength() / - (xis[xs.size()-1] - xis[0]).getLength(); - ad = (1.0*xr/xir - 1.0); //(alpha*alpha); - beta = beta + ad*ad; - //sum = sum + ad*ad; - } - - //sum = sum*(1 + beta); - /* apf::destroyElement(Edl); */ - - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - - std::vector xfs; - std::vector xifs; - double arPhys[3] = {1.0, 1.0, 1.0}; - double arParnt[3] = {1.0, 1.0, 1.0}; - double adf; - double gamma = 0.0; - - for (std::size_t i = 0; i < adjF.getSize(); i++) { - xfs.clear(); - xifs.clear(); - adf = 0.0; - - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - apf::Vector3 faceXi; - for (int j = 0; j < nFN; j++) { - getBezierNodeXi(mesh->getType(adjF[i]), P, j, faceXi); - xifs.push_back(faceXi); - } - xifs.push_back(apf::Vector3(0.0, 0.0, 0.0)); - xifs.push_back(apf::Vector3(1.0, 0.0, 0.0)); - xifs.push_back(apf::Vector3(0.0, 1.0, 0.0)); - - apf::MeshElement* mef = apf::createMeshElement(mesh, adjF[i]); - for (size_t k = 0; k < xifs.size(); k++) { - apf::Vector3 fcord; - apf::mapLocalToGlobal(mef, xifs[k], fcord); - xfs.push_back(fcord); - } - apf::destroyMeshElement(mef); - - double triPhys = getAr(xfs[xifs.size()-1], xfs[xifs.size()-2], xfs[xifs.size()-3]); - double triParnt = getAr(xifs[xifs.size()-1], xifs[xifs.size()-2], xifs[xifs.size()-3]); - - for (int j = 0; j < nFN; j++) { - /* - arPhys[0] = getAr(xfs[j], xfs[xifs.size()-1], xfs[xifs.size()-2]); - arParnt[0] = getAr(xifs[j], xifs[xifs.size()-1], xifs[xifs.size()-2]); - - arPhys[1] = getAr(xfs[j], xfs[xifs.size()-2], xfs[xifs.size()-3]); - arParnt[1] = getAr(xifs[j], xifs[xifs.size()-2], xifs[xifs.size()-3]); - - arPhys[2] = getAr(xfs[j], xfs[xifs.size()-1], xfs[xifs.size()-3]); - arParnt[2] = getAr(xifs[j], xifs[xifs.size()-1], xifs[xifs.size()-3]); - */ - for (int k = 0; k < 2; k++) { - arPhys[k] = getAr(xfs[j], xfs[xifs.size()-(3-k)], xfs[xifs.size()-(2-k)]); - arParnt[k] = getAr(xifs[j], xifs[xifs.size()-(3-k)], xifs[xifs.size()-(2-k)]); - adf = (1.0*arPhys[k]*triParnt/(arParnt[k]*triPhys) - 1); - gamma = gamma + adf*adf; - } - } - } - } - - -/* - apf::Adjacent adjF; - mesh->getAdjacent(edge, 2, adjF); - - apf::NewArray fCP; - apf::Vector3 xif; - double a[3] = {1.0, 1.0, 1.0}; - double b[3] = {1.0, 1.0, 1.0}; - double aratio = 0.0; - //double wfactor = 1.0; - double gamma = 0.0; - - for (std::size_t i = 0; i < adjF.getSize(); i++) { - if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { - apf::Element* Fal = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(Fal, fCP); - int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); - - int vN[3] = {getTriNodeIndex(P, P, 0), getTriNodeIndex(P, 0, P), getTriNodeIndex(P, 0, 0)}; - - apf::MeshElement* mfel = apf::createMeshElement(mesh, adjF[i]); - for (int j = 0; j < nFN; j++) { - getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); - apf::Vector3 sfcord; - apf::mapLocalToGlobal(mfel, xif, sfcord); - fCP[3*P + j] = sfcord; - } - apf::destroyMeshElement(mfel); - - double triAphys = getAr(fCP[0], fCP[1], fCP[2]); - apf::Vector3 prt0 = {0, 0, 0}; - apf::Vector3 prt1 = {1, 0, 0}; - apf::Vector3 prt2 = {0, 1, 0}; - double triAparnt = getAr(prt0, prt1, prt2); - - for (int j = 0; j < nFN; j++) { - getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); - apf::Vector3 xifm = {1.0-xif[0]-xif[1], xif[0], xif[1]}; - a[0] = getAr(fCP[3*P + j], fCP[vN[0]], fCP[vN[1]]); - b[0] = getAr(xifm, prt0, prt1); - a[1] = getAr(fCP[3*P + j], fCP[vN[1]], fCP[vN[2]]); - b[1] = getAr(xifm, prt1, prt2); - a[2] = getAr(fCP[3*P + j], fCP[vN[2]], fCP[vN[0]]); - b[2] = getAr(xifm, prt2, prt1); - - for (int k = 0; k < 3; k++) { - aratio = (a[k]*triAparnt/(b[k]*triAphys) - 1.0); - gamma = gamma + aratio*aratio; - } - } - apf::destroyElement(Fal); - } - } -*/ - /* double gamma = 0.0; */ - sum = sum*(1 + beta + 0.3*gamma); - - restoreInitialNodes(); - } - return sum; -} - -std::vector CrvModelEdgeReshapeObjFunc :: getGrad(std::vector &x) -{ - //double fold = getValue(x); - double eps = 1.0e-5; - double h = eps; - std::vector g; - /* - std::vector par; - - apf::MeshEntity* v[2]; - mesh->getDownward(edge, 0, v); - - for (int i = 0; i<2; i++) - mesh->getParam(v[i], par[i]); - - double delx = std::abs(par[0][0] - par[1][0]); - double dely = std::abs(par[0][1] - par[1][1]); - double delz = std::abs(par[0][2] - par[1][2]); - double delta = 1.0; -*/ - for (std::size_t i = 0; i < x.size(); i++) { - /* - if (i % 3 == 0) delta = delx; - //if (i % 3 == 1) delta = dely; - //if (i % 3 == 2) delta = delz; - - if (delta < eps) - h = eps; - else - h = eps * delta; -*/ - if (std::abs(x[i]) > eps) - h = eps * std::abs(x[i]); - else - h = eps; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; -/* - dff = (ff - fold)/h; - dbb = (fold - fb)/h; - df = (dff + dbb)/(2.0); -*/ - double df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} - -void CrvModelEdgeOptim :: setMaxIter(int n) -{ - iter = n; -} - -void CrvModelEdgeOptim :: setTol(double tolerance) -{ - tol = tolerance; -} - -bool CrvModelEdgeOptim :: run(int &invaliditySize) -{ - std::vector sizeHolder; - apf::MeshEntity* adj_array[99]; - apf::Adjacent adj; - mesh->getAdjacent(edge, 3, adj); - int cInvT = 0; - int thisTetSize = 0; - - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; - std::vector ai = crv::getAllInvalidities(mesh, adj[i]); - if (adj[i] == tet) thisTetSize = ai.size(); - sizeHolder.push_back(ai.size()); - } - - //std::vector ai = crv::getAllInvalidities(mesh,tet); - //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - printTetNumber(mesh, tet); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - - CrvModelEdgeReshapeObjFunc *objF = new CrvModelEdgeReshapeObjFunc(mesh, edge, tet); - std::vector x0 = objF->getInitialGuess(); - - - //double f0 = objF->getValue(x0); - //std::cout<< "fval at x0 " << f0<getDownward(adj[i], 1, ed); - int edgeIndex = apf::findIn(ed, 6, edge); - printf("reshape tried on %d Medge, TET %d ", edgeIndex, thisTETnum); - printTetNumber(mesh, adj[i]); - } - - bool hasDecreased = false; - invaliditySize = 0; - - if (l->run() && thisTetSize > 0) { - finalX = l->currentX; - fval = l->fValAfter; - objF->setNodes(finalX); - - for (int i = 0; i < adj.getSize(); i++) { - std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); - invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); - } - - if (hasDecreased == false) { - //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - std::cout<<"--------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, edge, adj.getSize()); - std::cout<<"size did not decrease"<currentX; - //objF->setNodes(finalX); - if (thisTetSize == 0) { - std::cout<<"No Optimization tried"< -#include -#include -#include "apf.h" -#include "apfMesh.h" -#include "apfMesh2.h" -#include "LBFGS.h" -#include "apfShape.h" - -namespace crv{ - -class CrvModelEdgeReshapeObjFunc : public ObjFunction -{ - public: - CrvModelEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) - { - P = mesh->getShape()->getOrder(); - d = mesh->getDimension(); - getSpaceDim(); - getVolume(); - getInitEdgeN(); - getInitFaceN(); - getInitTetN(); - } - ~CrvModelEdgeReshapeObjFunc(){} - - public: - int getSpaceDim(); - double getValue(std::vector &x); - std::vector getGrad(std::vector &x); - std::vector getInitialGuess(); - void setNodes(std::vector &x); - void restoreInitialNodes(); - int P; //order - int d; //dimension - - private: - void getInitEdgeN(); - void getInitFaceN(); - void getInitTetN(); - std::vector getParamCoords(); - std::vector convertParamCoordsToNodeVector(const std::vector &x); - std::vector convertXtoNodeVector(const std::vector &x); - void blendTris(const std::vector &edgeNodes, std::vector &faceNodes); - //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); - std::vector getFaceControlPointsFromInterpolatingPoints(apf::MeshEntity* face, const std::vector &faceInterpolatingP); - void updateNodes(std::vector ed, std::vector fa, std::vector te, bool isInitialX); - std::vector getVolume(); - double computeFValOfElement(apf::NewArray &nodes, double volm); - protected: - apf::Mesh2* mesh; - apf::MeshEntity* edge; - apf::MeshEntity* tet; - std::vector vol; - std::vector ien; - std::vector ifn; - std::vector itpfn; - std::vector itn; - -}; - -class CrvModelEdgeOptim -{ - public: - CrvModelEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) {} - ~CrvModelEdgeOptim(){} - - public: - void setMaxIter(int n); - void setTol(double tolerance); - bool run(int &invaliditySize); - public: - apf::Mesh2* mesh; - apf::MeshEntity* edge; - apf::MeshEntity* tet; - int iter; - double tol; - std::vector finalX; - double fval; -}; -} - -#endif diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc new file mode 100644 index 000000000..6d1397be7 --- /dev/null +++ b/crv/crvObjectiveFunctions.cc @@ -0,0 +1,1276 @@ +#include +#include "crv.h" +#include "crvSnap.h" +#include "crvObjectiveFunctions.h" +#include "crvBezier.h" +#include "crvQuality.h" +#include "crvMath.h" + + + +static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) +{ + p1 = p1 - p0; + p2 = p2 - p0; + double area = (apf::cross(p1, p2)).getLength(); + return (area/2.0); +} + + +namespace crv +{ + +int InternalEdgeReshapeObjFunc :: getSpaceDim() +{ + return P*d; +} + +double InternalEdgeReshapeObjFunc :: getValue(const vector &x) +{ + setNodes(x); + double sum = 0.0; + if (d == 2) { + apf::Adjacent adjF; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + // TODO: In the original code this line is commented. Why? + restoreInitialNodes(); + } + return sum; +} + + +vector InternalEdgeReshapeObjFunc :: getGrad(const vector &_x) +{ + vector x; + for (int i = 0; i < _x.size(); i++) + x.push_back(_x[i]); + + // TODO: Why these values? + double eps = 1.0e-5; + double delta = 1.0; + double h = eps; + + vector g; + double xmx = x[0]; + double xmn = x[0]; + double ymx = x[1]; + double ymn = x[1]; + double zmx = x[2]; + double zmn = x[2]; + double df = 0.0, dff = 0.0, dbb = 0.0; + + for (std::size_t i = 0; i < x.size(); i+=3) { + if (x[i] >= xmx) xmx = x[i]; + if (x[i] <= xmn) xmn = x[i]; + } + + for (std::size_t i = 1; i < x.size(); i+=3) { + if (x[i] >= ymx) ymx = x[i]; + if (x[i] <= ymn) ymn = x[i]; + } + + for (std::size_t i = 2; i < x.size(); i+=3) { + if (x[i] >= zmx) zmx = x[i]; + if (x[i] <= zmn) zmn = x[i]; + } + + double delx = std::abs(xmx - xmn); + double dely = std::abs(ymx - ymn); + double delz = std::abs(zmx - zmn); + + for (std::size_t i = 0; i < x.size(); i++) { + if (i % 3 == 0) delta = delx; + if (i % 3 == 1) delta = dely; + if (i % 3 == 2) delta = delz; + + h = eps * delta; + + x[i] = x[i] + h; + double ff = getValue(x); + x[i] = x[i] - h; + + x[i] = x[i] - h; + double fb = getValue(x); + x[i] = x[i] + h; + + df = (ff - fb)/(2.0 * h); + g.push_back(df); + } + return g; +} + +vector InternalEdgeReshapeObjFunc :: getInitialGuess() +{ + return convertNodeVectorToX(ien, ifn, itn); +} + +void InternalEdgeReshapeObjFunc :: setNodes(const vector &x) +{ + std::vector en;// (ien.begin(), ien.end()); + std::vector fn;// (ifn.begin(), ifn.end()); + std::vector tn;// (itn.begin(), itn.end()); + std::vector nod = convertXtoNodeVector(x); + //blendTris(en, fn); + //from all internal node vector to distict vector of nodes + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i getShape()->countNodesOn(mesh->TRIANGLE); + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + + for (std::size_t i = nEN; i < nEN + nFN*adjF.getSize(); i++) + fn.push_back(nod[i]); + + if (d > 2 && P > 3) { + //int nTN = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = nEN+nFN; i getShape()->countNodesOn(mesh->getType(edge)); + + for (int i = 0; i < numENodes; i++) { + mesh->getPoint(edge, i, intEdgeX); + ien.push_back(intEdgeX); + } +} + +void InternalEdgeReshapeObjFunc :: getInitFaceN() +{ + apf::Adjacent adjF; + apf::Vector3 intFaceX; + mesh->getAdjacent(edge, 2, adjF); + int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFaceX); + ifn.push_back(intFaceX); + } + } +} + +void InternalEdgeReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(edge, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +vector InternalEdgeReshapeObjFunc :: convertNodeVectorToX( + const vector &en, + const vector &fn, + const vector &tn) +{ + vector x0; + for (int i = 0; i < P-1; i++) + for (int j = 0; j < 3; j++) + x0.push_back(en[i][j]); + + for (std::size_t i = 0; i < fn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(fn[i][j]); + + // TODO: Why Is There a Need For if conditions? + // Isn't tn.size() == 0 when there are no tets in the mesh? + // or when the order of the mesh is less than 4 + if (d > 2 && P > 3) { + for (std::size_t i = 0; i < tn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(tn[i][j]); + } + return x0; +} + +vector InternalEdgeReshapeObjFunc :: convertXtoNodeVector(const vector &x) +{ + std::vector a; + apf::Vector3 v; + if (d == 2) { + std::size_t num = x.size()/d; // TODO: this seems unsafe + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + //check later for 2D case:: x should not include z coordinate in optim search + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], 0.0}; + a.push_back(v); + } + } + if (d == 3) { + std::size_t num = x.size()/d; // TODO: this seems unsafe + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + } + return a; +} + +void InternalEdgeReshapeObjFunc :: blendTris( + const vector &egn, + vector &faceNodes) +{ + apf::Vector3 xi; + apf::Adjacent adjF; + apf::Adjacent adjE; + std::vector cien (ien.begin(),ien.end()); + + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + mesh->getAdjacent(adjF[i], 1, adjE); + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (std::size_t j = 0; j < adjE.getSize(); j++) { + if (adjE[j] == edge) { + int jj = 1; + if ( j == 0) + jj = 2; + else if ( j == 1) + jj = 0; + else + jj = 1; + + for (int k = 0; k < numFNodes; k++) { + getBezierNodeXi(mesh->TRIANGLE, P, k, xi); + for (std::size_t ii = 0; ii < egn.size(); ii++) { + double factor = + 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) + + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); + faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - cien[ii]) * factor; + } + } + } + } + } +} + +void InternalEdgeReshapeObjFunc :: updateNodes( + const vector &ed, + const vector &fa, + const vector &te) +{ + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < numENodes; i++) + mesh->setPoint(edge, i, ed[i]); + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); + } + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } +} + +std::vector InternalEdgeReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(v); + } + } + if (d == 2) { + apf::Adjacent adjF; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 2, adjF); + apf::Vector3 point; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjF[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) { + if (k < 2) m[j][k] = point[k]; + else m[j][2] = 1.0; + } + } + double v = getDeterminant(m); + vol.push_back(v); + } + } + return vol; +} + +double InternalEdgeReshapeObjFunc :: computeFValOfElement( + apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< &x) +{ + setNodes(x); + + double sum = 0.0; + if (d == 2) { + apf::Adjacent adjF; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + + double ad = 0.0; + double xr = 1.0; + double xir = 1.0; + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + double beta = 0.0; + std::vector xs; + xs.clear(); + std::vector xis; + xis.clear(); + xis.push_back(apf::Vector3(-1.0, 0.0, 0.0)); + for (int i = 0; i getType(edge), P, i, currentXi); + xis.push_back(currentXi); + } + xis.push_back(apf::Vector3(+1.0, 0.0, 0.0)); + + apf::MeshElement* me = apf::createMeshElement(mesh, edge); + for (int i = 0; i < xis.size(); i++) { + apf::Vector3 scord; + apf::mapLocalToGlobal(me, xis[i], scord); + xs.push_back(scord); + } + apf::destroyMeshElement(me); + + for (int i = 1; i < xs.size()-1; i++) { + + xr = (xs[i] - xs[0]).getLength() / + (xs[xs.size()-1] - xs[0]).getLength(); + xir = (xis[i] - xis[0]).getLength() / + (xis[xs.size()-1] - xis[0]).getLength(); + ad = (1.0*xr/xir - 1.0); //(alpha*alpha); + beta = beta + ad*ad; + //sum = sum + ad*ad; + } + + //sum = sum*(1 + beta); + /* apf::destroyElement(Edl); */ + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + + std::vector xfs; + std::vector xifs; + double arPhys[3] = {1.0, 1.0, 1.0}; + double arParnt[3] = {1.0, 1.0, 1.0}; + double adf; + double gamma = 0.0; + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + xfs.clear(); + xifs.clear(); + adf = 0.0; + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + int nFN = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + apf::Vector3 faceXi; + for (int j = 0; j < nFN; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, faceXi); + xifs.push_back(faceXi); + } + xifs.push_back(apf::Vector3(0.0, 0.0, 0.0)); + xifs.push_back(apf::Vector3(1.0, 0.0, 0.0)); + xifs.push_back(apf::Vector3(0.0, 1.0, 0.0)); + + apf::MeshElement* mef = apf::createMeshElement(mesh, adjF[i]); + for (size_t k = 0; k < xifs.size(); k++) { + apf::Vector3 fcord; + apf::mapLocalToGlobal(mef, xifs[k], fcord); + xfs.push_back(fcord); + } + apf::destroyMeshElement(mef); + + double triPhys = getAr(xfs[xifs.size()-1], xfs[xifs.size()-2], xfs[xifs.size()-3]); + double triParnt = getAr(xifs[xifs.size()-1], xifs[xifs.size()-2], xifs[xifs.size()-3]); + + for (int j = 0; j < nFN; j++) { + for (int k = 0; k < 2; k++) { + arPhys[k] = getAr(xfs[j], xfs[xifs.size()-(3-k)], xfs[xifs.size()-(2-k)]); + arParnt[k] = getAr(xifs[j], xifs[xifs.size()-(3-k)], xifs[xifs.size()-(2-k)]); + adf = (1.0*arPhys[k]*triParnt/(arParnt[k]*triPhys) - 1); + gamma = gamma + adf*adf; + } + } + } + } + /* double gamma = 0.0; */ + sum = sum*(1 + beta + 0.3*gamma); + restoreInitialNodes(); + } + return sum; +} + +vector BoundaryEdgeReshapeObjFunc :: getGrad(const vector &_x) +{ + vector x; + for (int i = 0; i < _x.size(); i++) { + x[i] = _x[i]; + } + + //double fold = getValue(x); + double eps = 1.0e-5; + double h = eps; + vector g; + for (std::size_t i = 0; i < x.size(); i++) { + if (std::abs(x[i]) > eps) + h = eps * std::abs(x[i]); + else + h = eps; + + x[i] = x[i] + h; + double ff = getValue(x); + x[i] = x[i] - h; + + x[i] = x[i] - h; + double fb = getValue(x); + x[i] = x[i] + h; + double df = (ff - fb)/(2.0 * h); + g.push_back(df); + } + return g; +} + +vector BoundaryEdgeReshapeObjFunc :: getInitialGuess() +{ + return getParamCoords(); +} + +void BoundaryEdgeReshapeObjFunc :: setNodes(const vector &x) +{ + vector en; + vector fn; + vector tn; + vector nod = convertParamCoordsToNodeVector(x); + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < nEN; i++) + en.push_back(nod[i]); + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + int kk = 0; + int nFN = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < nFN; j++) + fn.push_back(nod[nEN+i*nFN+j]); + } + + if (d > 2 && P > 3) { + for (std::size_t i = nEN+nFN; i getShape()->countNodesOn(mesh->getType(edge)); + + for (int i = 0; i < numENodes; i++) { + mesh->getPoint(edge, i, intEdgeX); + ien.push_back(intEdgeX); + } +} + +void BoundaryEdgeReshapeObjFunc :: getInitFaceN() +{ + apf::Adjacent adjF; + apf::Vector3 intFaceX; + apf::Vector3 ipFN; + mesh->getAdjacent(edge, 2, adjF); + int numFNodes = mesh->getShape()->countNodesOn(mesh->TRIANGLE); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFaceX); + ifn.push_back(intFaceX); + //ipFN = getInterpolatingPointOnFace(mesh, adjF[i], P, j); + //itpfn.push_back(ipFN); + } + } +} + +void BoundaryEdgeReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(edge, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +vector BoundaryEdgeReshapeObjFunc :: getParamCoords() +{ + apf::Vector3 xi; + apf::Vector3 param; + std::vector xp; + + int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < numENodes; i++) { + getBezierNodeXi(mesh->getType(edge), P, i, xi); + transferParametricOnEdgeSplit(mesh, edge, 0.5*(xi[0]+1.0), param); + for (int j = 0; j < 3; j++) { + xp.push_back(param[j]); + } + } + + apf::Vector3 xif; + apf::Vector3 paramf; + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + for (int j = 0; j < numFNodes; j++) { + getBezierNodeXi(mesh->getType(adjF[i]), P, j, xif); + transferParametricOnTriSplit(mesh, adjF[i], xif, paramf); + for (int k = 0; k < 3; k++) { + xp.push_back(paramf[k]); + } + } + } + else { + apf::Vector3 intFN; + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(adjF[i], j, intFN); + for (int k = 0; k < 3; k++) + xp.push_back(intFN[k]); + } + } + } + return xp; +} + +vector BoundaryEdgeReshapeObjFunc :: convertParamCoordsToNodeVector( + const vector &x) +{ + apf::ModelEntity* me = mesh->toModel(edge); + std::vector edn; + std::vector vn = convertXtoNodeVector(x); + int nENodes = mesh->getShape()->countNodesOn(mesh->EDGE); + for (int i = 0; i < nENodes; i++) { + apf::Vector3 coorde; + mesh->snapToModel(me, vn[i], coorde); + edn.push_back(coorde); + } + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + int numFNTotal = 0; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int nFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + apf::ModelEntity* mef = mesh->toModel(adjF[i]); + for (int j = 0; j < nFNodes; j++) { + apf::Vector3 coordf; + mesh->snapToModel(mef, vn[nENodes+numFNTotal], coordf); + edn.push_back(coordf); + numFNTotal++; + } + } + else { + for (int j = 0; j < nFNodes; j++) { + edn.push_back(vn[nENodes+numFNTotal]); + numFNTotal++; + } + } + } + return edn; +} + +vector BoundaryEdgeReshapeObjFunc :: convertXtoNodeVector( + const std::vector &x) +{ + std::vector a; + apf::Vector3 v; + + if (d == 3) { + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + } + return a; +} + + + +void BoundaryEdgeReshapeObjFunc :: blendTris( + const vector &egn, + vector &faceNodes) +{ + apf::Vector3 xi; + apf::Adjacent adjF; + apf::Adjacent adjE; + + mesh->getAdjacent(edge, 2, adjF); + + for (std::size_t i = 0; i < adjF.getSize(); i++) { + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + mesh->getAdjacent(adjF[i], 1, adjE); + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + + for (std::size_t j = 0; j < adjE.getSize(); j++) { + if (adjE[j] == edge) { + int jj = 1; + + if ( j == 0) + jj = 2; + else if ( j == 1) + jj = 0; + else + jj = 1; + + for (int k = 0; k < numFNodes; k++) { + getBezierNodeXi(mesh->TRIANGLE, P, k, xi); + for (std::size_t ii = 0; ii < egn.size(); ii++) { + double factor = + 0.5 * (xi[j]/(1-xi[jj])) * binomial(P, ii+1) * intpow(1-xi[jj], ii+1) * intpow(xi[jj], P-ii-1) + + 0.5 * (xi[jj]/(1-xi[j])) * binomial(P, ii+1) * intpow(xi[j], ii+1) * intpow(1-xi[j], P-ii-1); + faceNodes[numFNodes*i+k] = faceNodes[numFNodes*i+k] + (egn[ii] - ien[ii])*factor; + } + } + } + } + } + } +} + + +vector BoundaryEdgeReshapeObjFunc :: getFaceControlPointsFromInterpolatingPoints( + apf::MeshEntity* face, + const vector &faceInterpolatingP) +{ + vector faceControlP; + apf::Vector3 xi; + apf::NewArray allCntrlP; + apf::Element* Fa = apf::createElement(mesh->getCoordinateField(), face); + apf::getVectorNodes(Fa, allCntrlP); + + int n = mesh->getShape()->countNodesOn(mesh->getType(face)); + mth::Matrix A(n, n); + mth::Matrix Ainv(n, n); + apf::NewArray rhs(n); + int j = 0; + + for (int i = 0; i < n; i++) { + getBezierNodeXi(apf::Mesh::TRIANGLE, P, i, xi); + rhs[i].zero(); + for (int ii = 0; ii < P+1; ii++) { + for (int jj = 0; jj < P+1-ii; jj++) { + if (ii == 0 || jj == 0 || (ii+jj == P)) { + double bFactor = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); + rhs[i] += allCntrlP[getTriNodeIndex(P, ii, jj)] * bFactor; + } + else { + j = getTriNodeIndex(P, ii, jj) - 3*P; //3P is the total number of nodes on all edges + A(i, j) = trinomial(P, ii, jj) * Bijk(ii, jj, P-ii-jj, 1.-xi[0]-xi[1], xi[0], xi[1]); + } + } + } + rhs[i] = faceInterpolatingP[i] - rhs[i]; + } + apf::destroyElement(Fa); + + if (n > 1) + invertMatrixWithPLU(n, A, Ainv); + else + Ainv(0,0) = 1./A(0,0); + + for (int i = 0; i < n; i++) { + apf::Vector3 fcp(0., 0., 0.); + for (int j = 0; j < n; j++) + fcp += rhs[j]*Ainv(i, j); + faceControlP.push_back(fcp); + } + return faceControlP; +} + +void BoundaryEdgeReshapeObjFunc :: updateNodes( + const vector &ed, + const vector &fa, + const vector &te, + bool isInitialX) +{ + if (!isInitialX) { + apf::NewArray eIntpCords; + apf::Element* Ed = apf::createElement(mesh->getCoordinateField(), edge); + apf::getVectorNodes(Ed, eIntpCords); + apf::NewArray trsCoff; + + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + apf::NewArray contP(nEN); + + for (int i = 0; i < nEN; i++) { + for (int j = 0; j < 3; j++) + eIntpCords[2+i][j] = ed[i][j]; + } + + getBezierTransformationCoefficients(P, mesh->getType(edge), trsCoff); + crv::convertInterpolationPoints(nEN+2, nEN, eIntpCords, trsCoff, contP); + + for (int i = 0; i < nEN; i++) + mesh->setPoint(edge, i, contP[i]); + + apf::destroyElement(Ed); + } + else { + int nEN = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (int i = 0; i < nEN; i++) + mesh->setPoint(edge, i, ed[i]); + } + + apf::Adjacent adjF; + mesh->getAdjacent(edge, 2, adjF); + std::vector fNd; + + if (!isInitialX) { + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + fNd.clear(); + + for (int j = 0; j < numFNodes; j++) + fNd.push_back(fa[numFNodes*i + j]); + + if (mesh->getModelType(mesh->toModel(adjF[i])) == 2) { + std::vector fCN = getFaceControlPointsFromInterpolatingPoints(adjF[i], fNd); + + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fCN[j]); + } + else { + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i + j]); + } + } + } + else { + for (std::size_t i = 0; i < adjF.getSize(); i++) { + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(adjF[i])); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(adjF[i], j, fa[numFNodes*i+j]); + } + } + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(edge, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } + + apf::synchronize(mesh->getCoordinateField()); +} + +std::vector BoundaryEdgeReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(std::abs(v)); + } + } + if (d == 2) { + apf::Adjacent adjF; + apf::Matrix3x3 m; + mesh->getAdjacent(edge, 2, adjF); + apf::Vector3 point; + for (std::size_t i = 0; i < adjF.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjF[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) { + if (k < 2) m[j][k] = point[k]; + else m[j][2] = 1.0; + } + } + double v = getDeterminant(m); + vol.push_back(v); + } + } + return vol; +} + + +double BoundaryEdgeReshapeObjFunc :: computeFValOfElement( + apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< &x) +{ + setNodes(x); + + double sum = 0.0; + + if (d == 3) { + apf::Adjacent adjT; + apf::NewArray allNodes; + mesh->getAdjacent(face, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); + apf::getVectorNodes(el, allNodes); + sum = sum + computeFValOfElement(allNodes, vol[i]); + apf::destroyElement(el); + } + restoreInitialNodes(); + } + return sum; +} + +vector FaceReshapeObjFunc :: getGrad(const vector &_x) +{ + vector x; + for (int i = 0; i < _x.size(); i++) { + x[i] = _x[i]; + } + + //double fold = getValue(x); + // TODO : Why the following value + double eps = 1.0e-4; + double h = eps; + std::vector g; + double xmx = x[0]; + double xmn = x[0]; + double ymx = x[1]; + double ymn = x[1]; + double zmx = x[2]; + double zmn = x[2]; + double df = 0.0, dff = 0.0, dbb = 0.0; + + for (std::size_t i = 0; i < x.size(); i+=3) { + if (x[i] >= xmx) xmx = x[i]; + if (x[i] <= xmn) xmn = x[i]; + } + + for (std::size_t i = 1; i < x.size(); i+=3) { + if (x[i] >= ymx) ymx = x[i]; + if (x[i] <= ymn) ymn = x[i]; + } + + for (std::size_t i = 2; i < x.size(); i+=3) { + if (x[i] >= zmx) zmx = x[i]; + if (x[i] <= zmn) zmn = x[i]; + } + + double delx = std::abs(xmx - xmn); + double dely = std::abs(ymx - ymn); + double delz = std::abs(zmx - zmn); + double delta = 1.0; + + for (std::size_t i = 0; i < x.size(); i++) { + if (i % 3 == 0) delta = delx; + if (i % 3 == 1) delta = dely; + if (i % 3 == 2) delta = delz; + + if (delta < eps) + h = eps * std::abs(x[i]); + else + h = eps * delta; + + x[i] = x[i] + h; + double ff = getValue(x); + x[i] = x[i] - h; + + x[i] = x[i] - h; + double fb = getValue(x); + x[i] = x[i] + h; + + df = (ff - fb)/(2.0 * h); + g.push_back(df); + } + return g; +} + +vector FaceReshapeObjFunc :: getInitialGuess() +{ + return convertNodeVectorToX(ifn); +} + +void FaceReshapeObjFunc :: setNodes(const vector &x) +{ + vector fn;// (ifn.begin(), ifn.end()); + vector tn;// (itn.begin(), itn.end()); + vector nod = convertXtoNodeVector(x); + //blendTris(en, fn); + //from all internal node vector to distict vector of nodes + + int nFN = mesh->getShape()->countNodesOn(mesh->getType(face)); + for (int i = 0; i 2 && P > 3) { + //int nTN = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = nFN; i getShape()->countNodesOn(mesh->TRIANGLE); + for (int j = 0; j < numFNodes; j++) { + mesh->getPoint(face, j, intFaceX); + ifn.push_back(intFaceX); + } +} + +void FaceReshapeObjFunc :: getInitTetN() +{ + apf::Adjacent adjT; + apf::Vector3 intTetX; + mesh->getAdjacent(face, 3, adjT); + int numTNodes = mesh->getShape()->countNodesOn(mesh->TET); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + for (int j = 0; j < numTNodes; j++) { + mesh->getPoint(adjT[i], j, intTetX); + itn.push_back(intTetX); + } + } +} + +vector FaceReshapeObjFunc :: convertNodeVectorToX(const vector &fn) +{ + vector x0; + + for (std::size_t i = 0; i < fn.size(); i++) + for (int j = 0; j < 3; j++) + x0.push_back(fn[i][j]); + + return x0; +} + +vector FaceReshapeObjFunc :: convertXtoNodeVector(const vector &x) +{ + std::vector a; + apf::Vector3 v; + std::size_t num = x.size()/d; + //int numENodes = mesh->getShape()->countNodesOn(mesh->getType(edge)); + for (std::size_t i = 0; i < num; i++) { + v = {x[d*i], x[d*i + 1], x[d*i + 2]}; + a.push_back(v); + } + return a; +} + +void FaceReshapeObjFunc :: updateNodes( + const vector &fa, + const vector &te) +{ + int numFNodes = mesh->getShape()->countNodesOn(mesh->getType(face)); + for (int j = 0; j < numFNodes; j++) + mesh->setPoint(face, j, fa[j]); + + if (d == 3 && P > 3) { + apf::Adjacent adjT; + mesh->getAdjacent(face, 3, adjT); + for (std::size_t i = 0; i < adjT.getSize(); i++) { + int numTNodes = mesh->getShape()->countNodesOn(mesh->getType(adjT[i])); + for (int j =0; j < numTNodes; j++) + mesh->setPoint(adjT[i], j, te[numTNodes*i + j]); + } + } +} + +vector FaceReshapeObjFunc :: getVolume() +{ + if (d == 3) { + apf::Adjacent adjT; + apf::Matrix3x3 m; + mesh->getAdjacent(face, 3, adjT); + apf::Vector3 point0, point; + for (std::size_t i = 0; i < adjT.getSize(); i++) { + apf::Adjacent adjV; + mesh->getAdjacent(adjT[i], 0, adjV); + for (std::size_t j = 0; j < adjV.getSize(); j++) { + if ( j == 0) + mesh->getPoint(adjV[j], 0, point0); + else { + mesh->getPoint(adjV[j], 0, point); + for (int k = 0; k < 3; k++) + m[j-1][k] = point[k] - point0[k]; + } + } + double v = getDeterminant(m)/6.0; + vol.push_back(v); + } + } + return vol; +} + +double FaceReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) +{ + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 6; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 3; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double fun = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + //std::cout<<"["< +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace crv +{ + +class ObjFunction +{ + public: + ObjFunction(){}; + virtual int getSpaceDim() = 0; + virtual double getValue(const vector &x) = 0; + // TODO :: can we do this once for all the objective functions? + virtual vector getGrad(const vector &_x) = 0; +}; + + +// TODO: can these be reused +/* void getInitEdgeN(); */ +/* void getInitFaceN(); */ +/* void getInitTetN(); */ + +// TODO can this be reused +// computeFValOfElement + +// Internal Edge Objective Functions +class InternalEdgeReshapeObjFunc : public ObjFunction +{ + public: + InternalEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitEdgeN(); + getInitFaceN(); + getInitTetN(); + } + ~InternalEdgeReshapeObjFunc(){} + int getSpaceDim(); + double getValue(const vector &x); + vector getGrad(const vector &x); + vector getInitialGuess(); + void setNodes(const vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + private: + void getInitEdgeN(); + void getInitFaceN(); + void getInitTetN(); + vector convertNodeVectorToX( + const vector &en, + const vector &fn, + const vector &tn); + vector convertXtoNodeVector(const vector &x); + void blendTris( + const vector &edgeNodes, + vector &faceNodes); + /* void blendTets( */ + /* const vector &edgeNodes, */ + /* const vector faceNodes, */ + /* vector &tetNodes); */ + void updateNodes( + const vector &ed, + const vector &fa, + const vector &te); + vector getVolume(); + double computeFValOfElement( + apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + apf::MeshEntity* tet; + vector vol; + vector ien; + vector ifn; + vector itn; +}; + + +// Boundary Edge Objective Function +class BoundaryEdgeReshapeObjFunc : public ObjFunction +{ + public: + BoundaryEdgeReshapeObjFunc( + apf::Mesh2* m, + apf::MeshEntity* e, + apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitEdgeN(); + getInitFaceN(); + getInitTetN(); + } + ~BoundaryEdgeReshapeObjFunc(){} + int getSpaceDim(); + double getValue(const vector &x); + vector getGrad(const vector &x); + vector getInitialGuess(); + void setNodes(const vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + private: + void getInitEdgeN(); + void getInitFaceN(); + void getInitTetN(); + vector getParamCoords(); + vector convertParamCoordsToNodeVector( + const vector &x); + vector convertXtoNodeVector(const vector &x); + void blendTris( + const vector &edgeNodes, + vector &faceNodes); + /* void blendTets( */ + /* const vector &edgeNodes, */ + /* const vector faceNodes, */ + /* vector &tetNodes); */ + vector getFaceControlPointsFromInterpolatingPoints( + apf::MeshEntity* face, + const vector &faceInterpolatingP); + void updateNodes( + const vector &ed, + const vector &fa, + const vector &te, + bool isInitialX); + vector getVolume(); + double computeFValOfElement( + apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + apf::MeshEntity* tet; + vector vol; + vector ien; + vector ifn; + vector itpfn; + vector itn; +}; + +class FaceReshapeObjFunc : public ObjFunction +{ + public: + FaceReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : + mesh(m), face(f), tet(t) + { + P = mesh->getShape()->getOrder(); + d = mesh->getDimension(); + getSpaceDim(); + getVolume(); + getInitFaceN(); + getInitTetN(); + } + ~FaceReshapeObjFunc() {} + int getSpaceDim(); + double getValue(const vector &x); + vector getGrad(const vector &_x); + vector getInitialGuess(); + void setNodes(const vector &x); + void restoreInitialNodes(); + int P; //order + int d; //dimension + private: + void getInitFaceN(); + void getInitTetN(); + vector convertNodeVectorToX(const vector &fn); + vector convertXtoNodeVector(const vector &x); + //void blendTets(const std::vector &edgeNodes, const std::vector faceNodes, std::vector &tetNodes); + void updateNodes( + const vector &fa, + const vector &te); + vector getVolume(); + double computeFValOfElement( + apf::NewArray &nodes, double volm); + protected: + apf::Mesh2* mesh; + apf::MeshEntity* face; + apf::MeshEntity* tet; + vector vol; + vector ifn; + vector itn; +}; + +} + +#endif diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc new file mode 100644 index 000000000..c7ddeca48 --- /dev/null +++ b/crv/crvOptimizations.cc @@ -0,0 +1,408 @@ +/* #include "crvEdgeOptim.h" */ +/* #include "LBFGS.h" */ +#include "crvOptimizations.h" +#include "crv.h" +#include "gmi.h" +#include "apfMDS.h" +#include "apfNumbering.h" +#include "crvQuality.h" +#include "crvBezier.h" +#include "crvMath.h" +#include +#include "apfMatrix.h" +#include +#include + +/* static int global_counter = 0; */ +/* static apf::MeshEntity* tetra[100]; */ +/* static int number = 0; */ + + +using Eigen::VectorXd; +using namespace LBFGSpp; + + +static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) +{ + + return; + apf::Numbering* n = m->findNumbering("debug_num_edge"); + PCU_ALWAYS_ASSERT(n); + int num = apf::getNumber(n, edge, 0, 0); + int tag = m->getModelTag(m->toModel(edge)); + std::cout<<"at edge "<< num <<" tag: "< ai = crv::getAllInvalidities(m, e[i]); + for (std::size_t j = 0; j < ai.size(); j++) { + printf("%d ", ai[j]); + } + printf("\n"); + } +} + +class LBFGSFunctor +{ + private: + int n; + crv::ObjFunction* obj; + public: + LBFGSFunctor(int _n, crv::ObjFunction* _obj) : n(_n), obj(_obj) {} + double operator () (const VectorXd &x, VectorXd &grad) + { + std::vector x_vec; + x_vec.clear(); + for (int i = 0; i < n; i++) + x_vec.push_back(x[i]); + std::vector g_vec; + g_vec = obj->getGrad(x_vec); + for (int i = 0; i < n; i++) + grad[i] = g_vec[i]; + + return obj->getValue(x_vec); + } +}; + +namespace crv{ + + +void CrvInternalEdgeOptim :: setMaxIter(int n) +{ + iter = n; +} + +void CrvInternalEdgeOptim :: setTol(double tolerance) +{ + tol = tolerance; +} + +bool CrvInternalEdgeOptim :: run(int &invaliditySize) +{ + std::vector sizeHolder; + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(edge, 3, adj); + int thisTetSize = 0; + + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + if (adj[i] == tet) thisTetSize = ai.size(); + sizeHolder.push_back(ai.size()); + + } + + //std::vector ai = crv::getAllInvalidities(mesh, tet); + //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + /* printTetNumber(mesh, tet); */ + /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ + InternalEdgeReshapeObjFunc *objF = new InternalEdgeReshapeObjFunc(mesh, edge, tet); + std::vector x0 = objF->getInitialGuess(); + //double f0 = objF->getValue(x0); + //std::cout<< "fval at x0 " << f0< param; + param.epsilon = 1e-6; + param.max_iterations = 100; + LBFGSSolver solver(param); + VectorXd x_init = VectorXd::Zero(x0.size()); + for (int i = 0; i < x0.size(); i++) { + x_init[i] = x0[i]; + finalX.push_back(0); + } + + double fx; + int niter = solver.minimize(fun, x_init, fx); + + printf("niter and fx are %d and %f\n", niter, fx); + + /* LBFGS *l = new LBFGS(tol, iter, x0, objF); */ + + apf::MeshEntity* ed[6]; + int thisTETnum = 0; + + for (std::size_t i = 0; i < adj.getSize(); i++) { + if (adj[i] == tet) thisTETnum = 1; + else thisTETnum = 0; + mesh->getDownward(adj[i], 1, ed); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d edge, TET %d; ", edgeIndex, thisTETnum); + /* printTetNumber(mesh, adj[i]); */ + } + + bool hasDecreased = false; + invaliditySize = 0; + + if (niter <= param.max_iterations && thisTetSize > 0) { + for (int i = 0; i < x0.size(); i++) + finalX[i] = x_init[i]; + fval = fx; + objF->setNodes(finalX); + + + for (int i = 0; i < adj.getSize(); i++) { + std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + } + + if (hasDecreased == false ) { + //invaliditySize = 0; + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ + /* std::cout<<"--------------------------------------"<restoreInitialNodes(); */ + /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ + std::cout<<"Size DID NOT decrease"<currentX; + //objF->setNodes(finalX); + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + if (thisTetSize == 0) { + std::cout<<" No Optimization tried"< sizeHolder; + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(edge, 3, adj); + int cInvT = 0; + int thisTetSize = 0; + + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + if (adj[i] == tet) thisTetSize = ai.size(); + sizeHolder.push_back(ai.size()); + } + + //std::vector ai = crv::getAllInvalidities(mesh,tet); + //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + /* printTetNumber(mesh, tet); */ + /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ + + BoundaryEdgeReshapeObjFunc *objF = new BoundaryEdgeReshapeObjFunc(mesh, edge, tet); + std::vector x0 = objF->getInitialGuess(); + + LBFGSFunctor fun(x0.size(), objF); + LBFGSParam param; + param.epsilon = 1e-6; + param.max_iterations = 100; + LBFGSSolver solver(param); + VectorXd x_init = VectorXd::Zero(x0.size()); + for (int i = 0; i < x0.size(); i++) { + x_init[i] = x0[i]; + finalX.push_back(0); + } + + double fx; + int niter = solver.minimize(fun, x_init, fx); + + printf("niter and fx are %d and %f\n", niter, fx); + + + + //double f0 = objF->getValue(x0); + //std::cout<< "fval at x0 " << f0<getDownward(adj[i], 1, ed); + int edgeIndex = apf::findIn(ed, 6, edge); + printf("reshape tried on %d Medge, TET %d ", edgeIndex, thisTETnum); + /* printTetNumber(mesh, adj[i]); */ + } + + bool hasDecreased = false; + invaliditySize = 0; + + if (niter < param.max_iterations && thisTetSize > 0) { + for (int i = 0; i < x0.size(); i++) + finalX[i] = x_init[i]; + fval = fx; + objF->setNodes(finalX); + + for (int i = 0; i < adj.getSize(); i++) { + std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + } + + if (hasDecreased == false) { + //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"--------------------------------------"<restoreInitialNodes(); + printInvalidities(mesh, adj_array, edge, adj.getSize()); + std::cout<<"size did not decrease"<currentX; + //objF->setNodes(finalX); + if (thisTetSize == 0) { + std::cout<<"No Optimization tried"< sizeHolder; + apf::MeshEntity* adj_array[99]; + apf::Adjacent adj; + mesh->getAdjacent(face, 3, adj); + int thisTetSize = 0; + for (int i = 0; i < adj.getSize(); i++) { + adj_array[i] = adj[i]; + //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); + //if (adj[i] == tet) thisTetSize = ai.size(); + //sizeHolder.push_back(ai.size()); + } + + std::vector ai = crv::getAllInvalidities(mesh, tet); + invaliditySize = ai.size(); + //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); + /* printTetNumber(mesh, tet); */ + printInvalidities(mesh, adj_array, face, adj.getSize()); + FaceReshapeObjFunc *objF = new FaceReshapeObjFunc(mesh, face, tet); + std::vector x0 = objF->getInitialGuess(); + //double f0 = objF->getValue(x0); + //std::cout<< "fval at x0 " << f0< param; + param.epsilon = 1e-6; + param.max_iterations = 100; + LBFGSSolver solver(param); + VectorXd x_init = VectorXd::Zero(x0.size()); + for (int i = 0; i < x0.size(); i++) { + x_init[i] = x0[i]; + finalX.push_back(0); + } + + double fx; + int niter = solver.minimize(fun, x_init, fx); + + printf("niter and fx are %d and %f\n", niter, fx); + + + + apf::MeshEntity* fc[4]; + int thisTETnum = 0; + + for (std::size_t i = 0; i < adj.getSize(); i++) { + if (adj[i] == tet) thisTETnum = 1; + else thisTETnum = 0; + mesh->getDownward(adj[i], 2, fc); + int faceIndex = apf::findIn(fc, 4, face); + printf("reshape tried on %d face, TET %d ",faceIndex, thisTETnum); + /* printTetNumber(mesh, adj[i]); */ + } + + //bool hasDecreased = false; + //invaliditySize = 0; + + //if (l->run() && thisTetSize > 0) { + if (niter < param.max_iterations && invaliditySize > 0) { + for (int i = 0; i < x0.size(); i++) + finalX[i] = x_init[i]; + fval = fx; + objF->setNodes(finalX); + + std::vector aiNew = crv::getAllInvalidities(mesh, tet); + /* + for (int i = 0; i < adj.getSize(); i++) { + std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); + invaliditySize = invaliditySize + aiNew.size(); + hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + } +*/ + // if (hasDecreased == false ) { + if (aiNew.size() <= invaliditySize) { + invaliditySize = aiNew.size(); + //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); + //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); + printInvalidities(mesh, adj_array, face, adj.getSize()); + std::cout<<"----------------------------------------------------"<restoreInitialNodes(); + printInvalidities(mesh, adj_array, face, adj.getSize()); + std::cout<<"Size didNOT decrease"< +#include +#include +#include "apf.h" +#include "apfMesh.h" +#include "apfMesh2.h" +#include "apfShape.h" + +#include "crvObjectiveFunctions.h" + + +/* #include */ +/* #include */ + +/* using Eigen::VectorXd; */ +/* using namespace LBFGSpp; */ + +namespace crv { + +class CrvEntityOptim +{ + public: + CrvEntityOptim() {} + virtual void setMaxIter(int n) = 0; + virtual void setTol(double tolerance) = 0; + virtual bool run(int &invaliditySize) = 0; +}; + +class CrvInternalEdgeOptim : public CrvEntityOptim +{ + public: + CrvInternalEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) {} + ~CrvInternalEdgeOptim(){} + + public: + void setMaxIter(int n); + void setTol(double tolerance); + bool run(int &invaliditySize); + public: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + apf::MeshEntity* tet; + int iter; + double tol; + std::vector finalX; + double fval; +}; + +class CrvBoundaryEdgeOptim : public CrvEntityOptim +{ + public: + CrvBoundaryEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : + mesh(m), edge(e), tet(t) {} + ~CrvBoundaryEdgeOptim(){} + + public: + void setMaxIter(int n); + void setTol(double tolerance); + bool run(int &invaliditySize); + public: + apf::Mesh2* mesh; + apf::MeshEntity* edge; + apf::MeshEntity* tet; + int iter; + double tol; + std::vector finalX; + double fval; +}; + +class CrvFaceOptim : public CrvEntityOptim +{ + public: + CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : + mesh(m), face(f), tet(t) {} + ~CrvFaceOptim(){} + + public: + void setMaxIter(int n); + void setTol(double tolerance); + bool run(int &invaliditySize); + public: + apf::Mesh2* mesh; + apf::MeshEntity* face; + apf::MeshEntity* tet; + int iter; + double tol; + std::vector finalX; + double fval; +}; + +} + +#endif diff --git a/crv/crvShape.cc b/crv/crvShape.cc index dd39cb557..e4b67f766 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -6,12 +6,8 @@ */ #include +#include #include -#include "crv.h" -#include "crvAdapt.h" -#include "crvShape.h" -#include "crvTables.h" -#include "crvShapeFixer.h" #include #include #include @@ -19,11 +15,13 @@ #include #include #include -#include "crvEdgeOptim.h" -#include "crvModelEdgeOptim.h" -#include "crvFaceOptim.h" +#include "crv.h" +#include "crvAdapt.h" #include "crvQuality.h" -#include "apfNumbering.h" +#include "crvShape.h" +#include "crvTables.h" +#include "crvShapeFixer.h" +#include "crvOptimizations.h" /* This is similar to maShape.cc, conceptually, but different enough * that some duplicate code makes sense */ @@ -1139,29 +1137,27 @@ class FaceOptimizer : public ma::Operator //mesh->getDownward(simplex, 2, faces); if (numf == 0) return; for (int i = 0; i < numf; i++ ) { - if (mesh->getModelType(mesh->toModel(faces[i])) == 3) { - CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i], simplex); - cfo->setMaxIter(100); - cfo->setTol(1e-8); - - if (cfo->run(invaliditySize)) { - if (invaliditySize < 1) { - ns++; - break; - } + if (mesh->getModelType(mesh->toModel(faces[i])) != 3) continue; + CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i], simplex); + cfo->setMaxIter(100); + cfo->setTol(1e-8); + if (cfo->run(invaliditySize)) { + if (invaliditySize < 1) { + ns++; + delete cfo; + break; } - else { - if (invaliditySize < 1) { - break; - } - nf++; + } + else { + nf++; + if (invaliditySize < 1) { + delete cfo; + break; } - - delete cfo; } + delete cfo; } } -private: protected: Adapt* adapter; ma::Mesh* mesh; @@ -1191,7 +1187,6 @@ class EdgeOptimizer : public ma::Operator } virtual int getTargetDimension() {return md;} virtual bool shouldApply(ma::Entity* e) { - std::vector ai = crv::getAllInvalidities(mesh, e); mesh->getDownward(e, 1, edges); int niv = ai.size(); @@ -1201,7 +1196,6 @@ class EdgeOptimizer : public ma::Operator simplex = e; } return (ne > 0); - } virtual bool requestLocality(apf::CavityOp* o) @@ -1212,49 +1206,35 @@ class EdgeOptimizer : public ma::Operator virtual void apply() { if (ne == 0) return; for (int i = 0; i < ne; i++ ) { - int invaliditySize = 0; - bool hasDecreased = false; - if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { - CrvEdgeOptim *ceo = new CrvEdgeOptim(mesh, edges[i], simplex); - ceo->setMaxIter(100); - ceo->setTol(1e-8); - - if (ceo->run(invaliditySize)) { - ns++; - if (invaliditySize < 1) - break; - } - else { - if (invaliditySize < 1) { - break; - } - nf++; + int invaliditySize = 0; + bool hasDecreased = false; + CrvEntityOptim* ceo; + + if (mesh->getModelType(mesh->toModel(edges[i])) == 3) + ceo = new CrvInternalEdgeOptim(mesh, edges[i], simplex); + else + ceo = new CrvBoundaryEdgeOptim(mesh, edges[i], simplex); + + ceo->setMaxIter(100); + ceo->setTol(1e-8); + + if (ceo->run(invaliditySize)) { + ns++; + if (invaliditySize < 1) { + break; + delete ceo; } - - delete ceo; } - else if (mesh->getModelType(mesh->toModel(edges[i])) == 2) { - CrvModelEdgeOptim *cmeo = new CrvModelEdgeOptim(mesh, edges[i], simplex); - cmeo->setMaxIter(200); - cmeo->setTol(1e-8); - - if (cmeo->run(invaliditySize)) { - ns++; - if (invaliditySize < 1) - break; - } - else { - if (invaliditySize < 1) { - break; - } - nf++; + else { + nf++; + if (invaliditySize < 1) { + delete ceo; + break; } - - delete cmeo; } + delete ceo; } } -private: protected: Adapt* adapter; ma::Mesh* mesh; @@ -1638,7 +1618,7 @@ int fixInvalidFaces(Adapt* a) } mesh->end(it); - optimizeInvalidFaces(a); + /* optimizeInvalidFaces(a); */ mesh->removeNumbering(edge_num); mesh->removeNumbering(face_num); From be87eedf6fd4d736860b12a4f384906cdb76bcd3 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Wed, 27 Nov 2019 10:39:00 -0500 Subject: [PATCH 33/48] Example of using crvDBG.h --- crv/crvOptimizations.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index c7ddeca48..f4f4374a4 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -8,6 +8,7 @@ #include "crvQuality.h" #include "crvBezier.h" #include "crvMath.h" +#include "crvDBG.h" #include #include "apfMatrix.h" #include @@ -128,7 +129,7 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) mesh->getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); printf("reshape tried on %d edge, TET %d; ", edgeIndex, thisTETnum); - /* printTetNumber(mesh, adj[i]); */ + crv_dbg::printTetNumber(mesh, adj[i], "debug_num_tet"); } bool hasDecreased = false; From 10bc76eb0d0a9ae329250a1dd7d3d9f4e273523c Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Mon, 9 Dec 2019 15:40:57 -0500 Subject: [PATCH 34/48] minor changes --- crv/crvEdgeOptim.cc | 8 ++++---- crv/crvFaceOptim.cc | 6 +++--- crv/crvModelEdgeOptim.cc | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crv/crvEdgeOptim.cc b/crv/crvEdgeOptim.cc index 04c6b40ac..d959dbe51 100644 --- a/crv/crvEdgeOptim.cc +++ b/crv/crvEdgeOptim.cc @@ -45,7 +45,7 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn static void makeMultipleEntityMesh(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, const char* prefix, int nat) { - return; + //return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); @@ -886,7 +886,7 @@ bool CrvEdgeOptim :: run(int &invaliditySize) //std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); printTetNumber(mesh, tet); printInvalidities(mesh, adj_array, edge, adj.getSize()); CrvEdgeReshapeObjFunc *objF = new CrvEdgeReshapeObjFunc(mesh, edge, tet); @@ -925,13 +925,13 @@ bool CrvEdgeOptim :: run(int &invaliditySize) if (hasDecreased == false ) { //invaliditySize = 0; //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); + makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<restoreInitialNodes(); printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"Size DID NOT decrease"<findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -23,7 +23,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* face, int nat) { -// return; + return; apf::Numbering* n = m->findNumbering("debug_num_face"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, face, 0, 0); diff --git a/crv/crvModelEdgeOptim.cc b/crv/crvModelEdgeOptim.cc index 4da5c77d5..d402e1f8a 100644 --- a/crv/crvModelEdgeOptim.cc +++ b/crv/crvModelEdgeOptim.cc @@ -16,8 +16,8 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) { - //printf("\n"); - //return; + printf("\n"); + return; apf::Numbering* n = m->findNumbering("debug_num_tet"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, e, 0, 0); @@ -27,7 +27,7 @@ static void printTetNumber(apf::Mesh2* m, apf::MeshEntity* e) static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { - //return; + return; apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); From 5d480e3c9e7bbad210e685164b5d62cc24faa014 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Wed, 12 Feb 2020 14:22:35 -0500 Subject: [PATCH 35/48] Reverts to internal LBFGS library --- crv/CMakeLists.txt | 8 +- crv/LBFGS.cc | 188 ++++++++++++++++++++++++++++++++++++++++ crv/LBFGS.h | 56 ++++++++++++ crv/crvOptimizations.cc | 104 +++------------------- crv/crvOptimizations.h | 6 -- 5 files changed, 258 insertions(+), 104 deletions(-) create mode 100644 crv/LBFGS.cc create mode 100644 crv/LBFGS.h diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index f58ae61da..4ed162673 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES crvTables.cc crvQuality.cc crvVtk.cc + LBFGS.cc crvOptimizations.cc crvObjectiveFunctions.cc ) @@ -45,13 +46,6 @@ target_include_directories(crv INTERFACE $ ) -# TODO: Add these to the higher lever cmake file in a proper form -target_include_directories(crv PUBLIC - "/lore/hakimm2/opt/eigen/include/eigen3" - ) -target_include_directories(crv PUBLIC - "/lore/hakimm2/opt/LBFGSpp/include" - ) # Link this package to these libraries target_link_libraries(crv PUBLIC diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc new file mode 100644 index 000000000..84f13006f --- /dev/null +++ b/crv/LBFGS.cc @@ -0,0 +1,188 @@ +#include "LBFGS.h" +#include +#include "apfMatrix.h" + +namespace crv{ + +//void LBFGS::setInitialValue(std::vector x) +//{ +// x0 = x; +//} + +std::vector LBFGS::getCurrentX() +{ + return currentX; +} + +static double dotP(const std::vector &v1, const std::vector &v2) +{ + double sum = 0.0; + for (std::size_t i = 0; i < v1.size(); i++) { + sum += v1[i]*v2[i]; + } + return sum; +} + +double LBFGS::getFvalueAfter() +{ + return fValAfter; +} + +double LBFGS::lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax) +{ + double alpha = 1.0e-4, tolOndeltaX = 1.0e-8; + int itrs = 2000; + double a, alam, alam2 = 0.0, alamin, b, disc, f2 = 0.0; + double rhs1, rhs2, slope = 0.0, sum = 0.0, temp, test, tmplam; + int n = xold.size(); + + std::vector xnew(xold.size(), 0.0); + sum = sqrt(dotP(direction,direction)); + if (sum > stpmax) { + for (int i = 0; i < n; i++) { + direction[i] = direction[i]*stpmax/sum; + } + } +// for (int i = 0; i < n; i++) slope += g[i]*p[i]; + slope = dotP(g,direction); +//if (slope >= 0.0) std::cout<<"slope positive"< test) test = temp; + } + alamin = tolOndeltaX/test; + alam = 1.0; + + double fold = objFunc->getValue(xold); + + for (int k = 0; k < itrs; k++) { + for (int i =0; i < n; i++) xnew[i] = xold[i] + alam*direction[i]; + + double fnew = objFunc->getValue(xnew); + if (alam < alamin || fnew <= fold + alpha*alam*slope) { + return alam; + } + else { + if (alam == 1.0) + tmplam = -slope/(2.0* (fnew-fold-slope)); + else { + rhs1 = fnew - fold - alam*slope; + rhs2 = f2 - fold - alam2*slope; + a = (rhs1/(alam*alam) - rhs2/(alam2*alam2))/(alam - alam2); + b = (-alam2*rhs1/(alam*alam) + alam*rhs2/(alam2*alam2))/(alam-alam2); + if (a == 0.0) tmplam = -slope/(2.0*b); + else { + disc = b*b - 3.0*a*slope; + if (disc < 0.0) tmplam = 0.5*alam; + else if (b <= 0.0) tmplam = (-b + sqrt(disc))/(3.0*a); + else tmplam = -slope/(b + sqrt(disc)); + } + if (tmplam > 0.5*alam) tmplam = 0.5*alam; + } + } + alam2 = alam; + alam = std::max(tmplam, 0.1*alam); + } + return alam; +} + +void LBFGS::moveArrayToLeft(std::vector a[], int r) +{ + for (int i = 0; i < r-1; i++) + a[i] = a[i+1]; +} + +bool LBFGS::run() +{ + std::vector p(x0.size(), 0.0); + std::vector xs[r]; + std::vector gs[r]; + std::vector gdiffs[r]; + double gammas[r]; + + for(int i = 0; i < r; ++i) + { + xs[i] = std::vector(x0.size(), 0.0); + gs[i] = std::vector(x0.size(), 0.0); + gdiffs[i] = std::vector(x0.size(), 0.0); + gammas[i] = 0.0; + } + + xs[0] = x0; + gs[0] = objFunc->getGrad(x0); + + for (std::size_t i = 0; i < xs[0].size(); i++) p[i] = -gs[0][i]; + + for (int k = 0; k < iter; k++) { + int I = 0; + int J = 0; + if (k+1 < r) { + I = k+1; + J = k; + } + else { + I = r-1; + J = I-1; + moveArrayToLeft(xs, r); + moveArrayToLeft(gs, r); + } + double stpmax = (std::max(sqrt(dotP(p,p)), double(objFunc->getSpaceDim()))); + double lambda = lineSearch(xs[J], gs[J], p, stpmax); + + for (std::size_t j = 0; j < xs[I].size(); j++) + xs[I][j] = xs[J][j] + lambda * p[j]; + + gs[I] = objFunc->getGrad(xs[I]); + + if ( I > 0) { + for (std::size_t jj = 0; jj < gs[I].size(); jj++) + gdiffs[I-1][jj] = gs[I][jj] - gs[I-1][jj]; + } + + if ((dotP(gs[I],gs[I]) < tol) || (dotP(gdiffs[I-1], gdiffs[I-1]) < tol)) { + currentX = xs[I]; + fValAfter = objFunc->getValue(xs[I]); + //std::cout<<"number of LBFGS iterations: "<= 0; --i) { + std::vector s(xs[I].size(), 0.0); + std::vector y(xs[I].size(), 0.0); + for( std::size_t j = 0; j < xs[i+1].size(); j++) { + s[j] = xs[i+1][j] - xs[i][j]; + y[j] = gs[i+1][j] - gs[i][j]; + } + double rho = 1 / dotP(s, y); + gammas[i] = rho * dotP(s, p); + for(std::size_t j = 0; j < p.size(); j++) + p[j] = p[j] - gammas[i]*y[j]; + } + + for (int i = 0; i <= I-1; i++) { + std::vector s(xs[I].size(), 0.0); + std::vector y(xs[I].size(), 0.0); + for( std::size_t j = 0; j < xs[i+1].size(); j++) { + s[j] = xs[i+1][j] - xs[i][j]; + y[j] = gs[i+1][j] - gs[i][j]; + } + double rho = 1 / dotP(s, y); + double phi = rho* dotP(y, p); + for(std::size_t j = 0; j < p.size(); j++) + p[j] = p[j] + s[j]* (gammas[i] - phi); + } + + if (dotP(p, gs[I]) > 0) + for (std::size_t j = 0; j < p.size(); j++) p[j] = -p[j]; + + } + return false; + +} + +} // end of namespace + diff --git a/crv/LBFGS.h b/crv/LBFGS.h new file mode 100644 index 000000000..cf2ebad23 --- /dev/null +++ b/crv/LBFGS.h @@ -0,0 +1,56 @@ + +#ifndef LBFGS_H +#define LBFGS_H + +#include +#include +#include + +namespace crv{ + +class ObjFunction +{ + public: + ObjFunction(){}; + + public: + virtual double getValue(std::vector &x) = 0; + virtual std::vector getGrad(std::vector &x) = 0; + //virtual int getVectorDim() = 0; + virtual int getSpaceDim() = 0; +}; + +class LBFGS +{ +public: + LBFGS(double inTol, int inIter, const std::vector &x, ObjFunction *inObjFunc): + tol(inTol), iter(inIter), x0(x), objFunc(inObjFunc) + { + //setInitialValue(x0); + } + + ~LBFGS() {} + +public: + //void setInitialValue(std::vector x); + std::vector getCurrentX(); + double getFvalueAfter(); + double lineSearch(std::vector &xold, std::vector &g, std::vector &direction, double stpmax); + void moveArrayToLeft(std::vector a[], int r); + bool run(); + +public: + double tol; + int iter; + std::vector x0; + ObjFunction *objFunc; + std::vector currentX; + double fValAfter; + +private: + int r = 40; +}; + +} + +#endif diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index f4f4374a4..250d38eb9 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -1,5 +1,4 @@ -/* #include "crvEdgeOptim.h" */ -/* #include "LBFGS.h" */ +#include "LBFGS.h" #include "crvOptimizations.h" #include "crv.h" #include "gmi.h" @@ -11,17 +10,12 @@ #include "crvDBG.h" #include #include "apfMatrix.h" -#include -#include /* static int global_counter = 0; */ /* static apf::MeshEntity* tetra[100]; */ /* static int number = 0; */ -using Eigen::VectorXd; -using namespace LBFGSpp; - static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) { @@ -42,27 +36,6 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn } } -class LBFGSFunctor -{ - private: - int n; - crv::ObjFunction* obj; - public: - LBFGSFunctor(int _n, crv::ObjFunction* _obj) : n(_n), obj(_obj) {} - double operator () (const VectorXd &x, VectorXd &grad) - { - std::vector x_vec; - x_vec.clear(); - for (int i = 0; i < n; i++) - x_vec.push_back(x[i]); - std::vector g_vec; - g_vec = obj->getGrad(x_vec); - for (int i = 0; i < n; i++) - grad[i] = g_vec[i]; - - return obj->getValue(x_vec); - } -}; namespace crv{ @@ -102,23 +75,8 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< param; - param.epsilon = 1e-6; - param.max_iterations = 100; - LBFGSSolver solver(param); - VectorXd x_init = VectorXd::Zero(x0.size()); - for (int i = 0; i < x0.size(); i++) { - x_init[i] = x0[i]; - finalX.push_back(0); - } - double fx; - int niter = solver.minimize(fun, x_init, fx); - - printf("niter and fx are %d and %f\n", niter, fx); - - /* LBFGS *l = new LBFGS(tol, iter, x0, objF); */ + LBFGS *l = new LBFGS(tol, iter, x0, objF); apf::MeshEntity* ed[6]; int thisTETnum = 0; @@ -135,10 +93,9 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) bool hasDecreased = false; invaliditySize = 0; - if (niter <= param.max_iterations && thisTetSize > 0) { - for (int i = 0; i < x0.size(); i++) - finalX[i] = x_init[i]; - fval = fx; + if (l->run() && thisTetSize > 1) { + finalX = l->currentX; + fval = l->fValAfter; objF->setNodes(finalX); @@ -215,27 +172,11 @@ bool CrvBoundaryEdgeOptim :: run(int &invaliditySize) BoundaryEdgeReshapeObjFunc *objF = new BoundaryEdgeReshapeObjFunc(mesh, edge, tet); std::vector x0 = objF->getInitialGuess(); - LBFGSFunctor fun(x0.size(), objF); - LBFGSParam param; - param.epsilon = 1e-6; - param.max_iterations = 100; - LBFGSSolver solver(param); - VectorXd x_init = VectorXd::Zero(x0.size()); - for (int i = 0; i < x0.size(); i++) { - x_init[i] = x0[i]; - finalX.push_back(0); - } - - double fx; - int niter = solver.minimize(fun, x_init, fx); - - printf("niter and fx are %d and %f\n", niter, fx); - //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< 0) { - for (int i = 0; i < x0.size(); i++) - finalX[i] = x_init[i]; - fval = fx; + if (l->run() && thisTetSize > 0) { + finalX = l->currentX; + fval = l->fValAfter; objF->setNodes(finalX); for (int i = 0; i < adj.getSize(); i++) { @@ -326,24 +266,7 @@ bool CrvFaceOptim :: run(int &invaliditySize) std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< param; - param.epsilon = 1e-6; - param.max_iterations = 100; - LBFGSSolver solver(param); - VectorXd x_init = VectorXd::Zero(x0.size()); - for (int i = 0; i < x0.size(); i++) { - x_init[i] = x0[i]; - finalX.push_back(0); - } - - double fx; - int niter = solver.minimize(fun, x_init, fx); - - printf("niter and fx are %d and %f\n", niter, fx); - + LBFGS *l = new LBFGS(tol, iter, x0, objF); apf::MeshEntity* fc[4]; @@ -362,10 +285,9 @@ bool CrvFaceOptim :: run(int &invaliditySize) //invaliditySize = 0; //if (l->run() && thisTetSize > 0) { - if (niter < param.max_iterations && invaliditySize > 0) { - for (int i = 0; i < x0.size(); i++) - finalX[i] = x_init[i]; - fval = fx; + if (l->run() && invaliditySize > 0) { + finalX = l->currentX; + fval = l->fValAfter; objF->setNodes(finalX); std::vector aiNew = crv::getAllInvalidities(mesh, tet); diff --git a/crv/crvOptimizations.h b/crv/crvOptimizations.h index ca2982702..481154cde 100644 --- a/crv/crvOptimizations.h +++ b/crv/crvOptimizations.h @@ -12,12 +12,6 @@ #include "crvObjectiveFunctions.h" -/* #include */ -/* #include */ - -/* using Eigen::VectorXd; */ -/* using namespace LBFGSpp; */ - namespace crv { class CrvEntityOptim From 71aa88663673a02af5a92ce5050afeb92b7576c6 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Wed, 12 Feb 2020 14:33:21 -0500 Subject: [PATCH 36/48] Fixes forward decleration issues --- crv/LBFGS.cc | 1 + crv/LBFGS.h | 13 ++----------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/crv/LBFGS.cc b/crv/LBFGS.cc index 84f13006f..9946a339f 100644 --- a/crv/LBFGS.cc +++ b/crv/LBFGS.cc @@ -1,4 +1,5 @@ #include "LBFGS.h" +#include "crvObjectiveFunctions.h" #include #include "apfMatrix.h" diff --git a/crv/LBFGS.h b/crv/LBFGS.h index cf2ebad23..fdf18eb38 100644 --- a/crv/LBFGS.h +++ b/crv/LBFGS.h @@ -8,17 +8,8 @@ namespace crv{ -class ObjFunction -{ - public: - ObjFunction(){}; - - public: - virtual double getValue(std::vector &x) = 0; - virtual std::vector getGrad(std::vector &x) = 0; - //virtual int getVectorDim() = 0; - virtual int getSpaceDim() = 0; -}; +// forward declare ObjFunction so the type is known to the following classes +class ObjFunction; class LBFGS { From 30603e7fe537373632eba445582c0c833a086b57 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Fri, 14 Feb 2020 12:01:52 -0500 Subject: [PATCH 37/48] Re-factors objective functions evaluations --- crv/crvObjectiveFunctions.cc | 379 ++++++++++------------------------- crv/crvObjectiveFunctions.h | 18 -- 2 files changed, 101 insertions(+), 296 deletions(-) diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index 6d1397be7..54cdcb5c0 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -16,6 +16,102 @@ static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) return (area/2.0); } +static double getLinearVolPhys(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::MeshEntity* vs[12]; + int n = m->getDownward(e, 0, vs); + apf::Vector3 coords[12]; + for (int i = 0; i < n; i++) { + m->getPoint(vs[i], 0, coords[i]); + } + + if (m->getType(e) == apf::Mesh::TRIANGLE) + { + return apf::cross(coords[1]-coords[0], coords[2]-coords[0]).getLength()/2.; + } + else if (m->getType(e) == apf::Mesh::TET) + { + apf::Matrix3x3 J; + J[0] = coords[1] - coords[0]; + J[1] = coords[2] - coords[0]; + J[2] = coords[3] - coords[0]; + return apf::getDeterminant(J) / 6.; + } + else + PCU_ALWAYS_ASSERT_VERBOSE(0, + "Not implemented for entities of type other than tri or tet!"); + return 0.; +} + +static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s = 0) +{ + PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); + + apf::NewArray nodes; + apf::Element* el = apf::createElement(m->getCoordinateField(), e); + apf::getVectorNodes(el, nodes); + apf::destroyElement(el); + + double volm = getLinearVolPhys(m, e); + + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + } + + if (d == 2) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + if ((I == J && I == 0) || + (J == K && J == 0) || + (I == K && I == 0)) + weight = 2; + else + weight = 1; + if (I + J + K == d*(P-1)) { + double f = Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + return sumf; +} + +static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s) +{ + // TODO: To be completed + return 0; +} + namespace crv { @@ -34,10 +130,7 @@ double InternalEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 2, adjF); for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); + sum = sum + computeFValNIJKL(mesh, adjF[i]); } restoreInitialNodes(); } @@ -46,10 +139,7 @@ double InternalEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); + sum = sum + computeFValNIJKL(mesh, adjT[i]); } // TODO: In the original code this line is commented. Why? restoreInitialNodes(); @@ -310,106 +400,8 @@ void InternalEdgeReshapeObjFunc :: updateNodes( } } -std::vector InternalEdgeReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(v); - } - } - if (d == 2) { - apf::Adjacent adjF; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 2, adjF); - apf::Vector3 point; - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjF[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) { - if (k < 2) m[j][k] = point[k]; - else m[j][2] = 1.0; - } - } - double v = getDeterminant(m); - vol.push_back(v); - } - } - return vol; -} -double InternalEdgeReshapeObjFunc :: computeFValOfElement( - apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || - (J == K && K == L && J == 0) || - (I == K && K == L && I == 0) || - (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || - (I == K && I == 0) || - (I == L && I == 0) || - (J == K && J == 0) || - (J == L && J == 0) || - (K == L && K == 0)) - weight = 2; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["< &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 2, adjF); for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjF[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); + sum = sum + computeFValNIJKL(mesh, adjF[i]); } restoreInitialNodes(); } @@ -442,10 +431,7 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); + sum = sum + computeFValNIJKL(mesh, adjT[i]); } double ad = 0.0; @@ -922,107 +908,9 @@ void BoundaryEdgeReshapeObjFunc :: updateNodes( apf::synchronize(mesh->getCoordinateField()); } -std::vector BoundaryEdgeReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(std::abs(v)); - } - } - if (d == 2) { - apf::Adjacent adjF; - apf::Matrix3x3 m; - mesh->getAdjacent(edge, 2, adjF); - apf::Vector3 point; - for (std::size_t i = 0; i < adjF.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjF[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) { - if (k < 2) m[j][k] = point[k]; - else m[j][2] = 1.0; - } - } - double v = getDeterminant(m); - vol.push_back(v); - } - } - return vol; -} -double BoundaryEdgeReshapeObjFunc :: computeFValOfElement( - apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || - (J == K && K == L && J == 0) || - (I == K && K == L && I == 0) || - (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || - (I == K && I == 0) || - (I == L && I == 0) || - (J == K && J == 0) || - (J == L && J == 0) || - (K == L && K == 0)) - weight = 2; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["< &x) apf::NewArray allNodes; mesh->getAdjacent(face, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Element* el = apf::createElement(mesh->getCoordinateField(), adjT[i]); - apf::getVectorNodes(el, allNodes); - sum = sum + computeFValOfElement(allNodes, vol[i]); - apf::destroyElement(el); + sum = sum + computeFValNIJKL(mesh, adjT[i]); } restoreInitialNodes(); } @@ -1211,66 +1096,4 @@ void FaceReshapeObjFunc :: updateNodes( } } -vector FaceReshapeObjFunc :: getVolume() -{ - if (d == 3) { - apf::Adjacent adjT; - apf::Matrix3x3 m; - mesh->getAdjacent(face, 3, adjT); - apf::Vector3 point0, point; - for (std::size_t i = 0; i < adjT.getSize(); i++) { - apf::Adjacent adjV; - mesh->getAdjacent(adjT[i], 0, adjV); - for (std::size_t j = 0; j < adjV.getSize(); j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = getDeterminant(m)/6.0; - vol.push_back(v); - } - } - return vol; -} - -double FaceReshapeObjFunc :: computeFValOfElement(apf::NewArray &nodes, double volm) -{ - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || - (J == K && K == L && J == 0) || - (I == K && K == L && I == 0) || - (I == J && J == L && I == 0)) - weight = 6; - else if ((I == J && I == 0) || - (I == K && I == 0) || - (I == L && I == 0) || - (J == K && J == 0) || - (J == L && J == 0) || - (K == L && K == 0)) - weight = 3; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double fun = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - //std::cout<<"["<getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); - getVolume(); getInitEdgeN(); getInitFaceN(); getInitTetN(); @@ -79,14 +75,10 @@ class InternalEdgeReshapeObjFunc : public ObjFunction const vector &ed, const vector &fa, const vector &te); - vector getVolume(); - double computeFValOfElement( - apf::NewArray &nodes, double volm); protected: apf::Mesh2* mesh; apf::MeshEntity* edge; apf::MeshEntity* tet; - vector vol; vector ien; vector ifn; vector itn; @@ -106,7 +98,6 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction P = mesh->getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); - getVolume(); getInitEdgeN(); getInitFaceN(); getInitTetN(); @@ -143,14 +134,10 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction const vector &fa, const vector &te, bool isInitialX); - vector getVolume(); - double computeFValOfElement( - apf::NewArray &nodes, double volm); protected: apf::Mesh2* mesh; apf::MeshEntity* edge; apf::MeshEntity* tet; - vector vol; vector ien; vector ifn; vector itpfn; @@ -166,7 +153,6 @@ class FaceReshapeObjFunc : public ObjFunction P = mesh->getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); - getVolume(); getInitFaceN(); getInitTetN(); } @@ -188,14 +174,10 @@ class FaceReshapeObjFunc : public ObjFunction void updateNodes( const vector &fa, const vector &te); - vector getVolume(); - double computeFValOfElement( - apf::NewArray &nodes, double volm); protected: apf::Mesh2* mesh; apf::MeshEntity* face; apf::MeshEntity* tet; - vector vol; vector ifn; vector itn; }; From 905bb59299869e9a92b60344df608185c2712215 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Fri, 14 Feb 2020 12:48:07 -0500 Subject: [PATCH 38/48] Re-factors getGrad + add tol --- crv/crvObjectiveFunctions.cc | 361 ++++++++++++++++++----------------- crv/crvObjectiveFunctions.h | 66 ++++++- 2 files changed, 244 insertions(+), 183 deletions(-) diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index 54cdcb5c0..afa84aabc 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -16,37 +16,40 @@ static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) return (area/2.0); } -static double getLinearVolPhys(apf::Mesh2* m, apf::MeshEntity* e) -{ - apf::MeshEntity* vs[12]; - int n = m->getDownward(e, 0, vs); - apf::Vector3 coords[12]; - for (int i = 0; i < n; i++) { - m->getPoint(vs[i], 0, coords[i]); - } - - if (m->getType(e) == apf::Mesh::TRIANGLE) - { - return apf::cross(coords[1]-coords[0], coords[2]-coords[0]).getLength()/2.; - } - else if (m->getType(e) == apf::Mesh::TET) - { - apf::Matrix3x3 J; - J[0] = coords[1] - coords[0]; - J[1] = coords[2] - coords[0]; - J[2] = coords[3] - coords[0]; - return apf::getDeterminant(J) / 6.; - } - else - PCU_ALWAYS_ASSERT_VERBOSE(0, - "Not implemented for entities of type other than tri or tet!"); - return 0.; -} +/* static double getLinearVolPhys(apf::Mesh2* m, apf::MeshEntity* e) */ +/* { */ +/* apf::MeshEntity* vs[12]; */ +/* int n = m->getDownward(e, 0, vs); */ +/* apf::Vector3 coords[12]; */ +/* for (int i = 0; i < n; i++) { */ +/* m->getPoint(vs[i], 0, coords[i]); */ +/* } */ + +/* if (m->getType(e) == apf::Mesh::TRIANGLE) */ +/* { */ +/* return apf::cross(coords[1]-coords[0], coords[2]-coords[0]).getLength()/2.; */ +/* } */ +/* else if (m->getType(e) == apf::Mesh::TET) */ +/* { */ +/* apf::Matrix3x3 J; */ +/* J[0] = coords[1] - coords[0]; */ +/* J[1] = coords[2] - coords[0]; */ +/* J[2] = coords[3] - coords[0]; */ +/* return apf::getDeterminant(J) / 6.; */ +/* } */ +/* else */ +/* PCU_ALWAYS_ASSERT_VERBOSE(0, */ +/* "Not implemented for entities of type other than tri or tet!"); */ +/* return 0.; */ +/* } */ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s = 0) { PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); + int d = m->getDimension(); + int P = m->getShape()->getOrder(); + apf::NewArray nodes; apf::Element* el = apf::createElement(m->getCoordinateField(), e); apf::getVectorNodes(el, nodes); @@ -76,7 +79,7 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* else weight = 1; if (I + J + K + L == d*(P-1)) { - double f = Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + double f = crv::Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; sumf = sumf + weight*f*f; } } @@ -96,7 +99,7 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* else weight = 1; if (I + J + K == d*(P-1)) { - double f = Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; + double f = crv::Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; sumf = sumf + weight*f*f; } } @@ -148,65 +151,65 @@ double InternalEdgeReshapeObjFunc :: getValue(const vector &x) } -vector InternalEdgeReshapeObjFunc :: getGrad(const vector &_x) -{ - vector x; - for (int i = 0; i < _x.size(); i++) - x.push_back(_x[i]); - - // TODO: Why these values? - double eps = 1.0e-5; - double delta = 1.0; - double h = eps; - - vector g; - double xmx = x[0]; - double xmn = x[0]; - double ymx = x[1]; - double ymn = x[1]; - double zmx = x[2]; - double zmn = x[2]; - double df = 0.0, dff = 0.0, dbb = 0.0; - - for (std::size_t i = 0; i < x.size(); i+=3) { - if (x[i] >= xmx) xmx = x[i]; - if (x[i] <= xmn) xmn = x[i]; - } - - for (std::size_t i = 1; i < x.size(); i+=3) { - if (x[i] >= ymx) ymx = x[i]; - if (x[i] <= ymn) ymn = x[i]; - } - - for (std::size_t i = 2; i < x.size(); i+=3) { - if (x[i] >= zmx) zmx = x[i]; - if (x[i] <= zmn) zmn = x[i]; - } - - double delx = std::abs(xmx - xmn); - double dely = std::abs(ymx - ymn); - double delz = std::abs(zmx - zmn); - - for (std::size_t i = 0; i < x.size(); i++) { - if (i % 3 == 0) delta = delx; - if (i % 3 == 1) delta = dely; - if (i % 3 == 2) delta = delz; - - h = eps * delta; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; - - df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} +/* vector InternalEdgeReshapeObjFunc :: getGrad(const vector &_x) */ +/* { */ +/* vector x; */ +/* for (int i = 0; i < _x.size(); i++) */ +/* x.push_back(_x[i]); */ + +/* // TODO: Why these values? */ +/* double eps = 1.0e-5; */ +/* double delta = 1.0; */ +/* double h = eps; */ + +/* vector g; */ +/* double xmx = x[0]; */ +/* double xmn = x[0]; */ +/* double ymx = x[1]; */ +/* double ymn = x[1]; */ +/* double zmx = x[2]; */ +/* double zmn = x[2]; */ +/* double df = 0.0, dff = 0.0, dbb = 0.0; */ + +/* for (std::size_t i = 0; i < x.size(); i+=3) { */ +/* if (x[i] >= xmx) xmx = x[i]; */ +/* if (x[i] <= xmn) xmn = x[i]; */ +/* } */ + +/* for (std::size_t i = 1; i < x.size(); i+=3) { */ +/* if (x[i] >= ymx) ymx = x[i]; */ +/* if (x[i] <= ymn) ymn = x[i]; */ +/* } */ + +/* for (std::size_t i = 2; i < x.size(); i+=3) { */ +/* if (x[i] >= zmx) zmx = x[i]; */ +/* if (x[i] <= zmn) zmn = x[i]; */ +/* } */ + +/* double delx = std::abs(xmx - xmn); */ +/* double dely = std::abs(ymx - ymn); */ +/* double delz = std::abs(zmx - zmn); */ + +/* for (std::size_t i = 0; i < x.size(); i++) { */ +/* if (i % 3 == 0) delta = delx; */ +/* if (i % 3 == 1) delta = dely; */ +/* if (i % 3 == 2) delta = delz; */ + +/* h = eps * delta; */ + +/* x[i] = x[i] + h; */ +/* double ff = getValue(x); */ +/* x[i] = x[i] - h; */ + +/* x[i] = x[i] - h; */ +/* double fb = getValue(x); */ +/* x[i] = x[i] + h; */ + +/* df = (ff - fb)/(2.0 * h); */ +/* g.push_back(df); */ +/* } */ +/* return g; */ +/* } */ vector InternalEdgeReshapeObjFunc :: getInitialGuess() { @@ -527,35 +530,35 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) return sum; } -vector BoundaryEdgeReshapeObjFunc :: getGrad(const vector &_x) -{ - vector x; - for (int i = 0; i < _x.size(); i++) { - x[i] = _x[i]; - } - - //double fold = getValue(x); - double eps = 1.0e-5; - double h = eps; - vector g; - for (std::size_t i = 0; i < x.size(); i++) { - if (std::abs(x[i]) > eps) - h = eps * std::abs(x[i]); - else - h = eps; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; - double df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} +/* vector BoundaryEdgeReshapeObjFunc :: getGrad(const vector &_x) */ +/* { */ +/* vector x; */ +/* for (int i = 0; i < _x.size(); i++) { */ +/* x[i] = _x[i]; */ +/* } */ + +/* //double fold = getValue(x); */ +/* double eps = 1.0e-5; */ +/* double h = eps; */ +/* vector g; */ +/* for (std::size_t i = 0; i < x.size(); i++) { */ +/* if (std::abs(x[i]) > eps) */ +/* h = eps * std::abs(x[i]); */ +/* else */ +/* h = eps; */ + +/* x[i] = x[i] + h; */ +/* double ff = getValue(x); */ +/* x[i] = x[i] - h; */ + +/* x[i] = x[i] - h; */ +/* double fb = getValue(x); */ +/* x[i] = x[i] + h; */ +/* double df = (ff - fb)/(2.0 * h); */ +/* g.push_back(df); */ +/* } */ +/* return g; */ +/* } */ vector BoundaryEdgeReshapeObjFunc :: getInitialGuess() { @@ -936,69 +939,69 @@ double FaceReshapeObjFunc :: getValue(const std::vector &x) return sum; } -vector FaceReshapeObjFunc :: getGrad(const vector &_x) -{ - vector x; - for (int i = 0; i < _x.size(); i++) { - x[i] = _x[i]; - } - - //double fold = getValue(x); - // TODO : Why the following value - double eps = 1.0e-4; - double h = eps; - std::vector g; - double xmx = x[0]; - double xmn = x[0]; - double ymx = x[1]; - double ymn = x[1]; - double zmx = x[2]; - double zmn = x[2]; - double df = 0.0, dff = 0.0, dbb = 0.0; - - for (std::size_t i = 0; i < x.size(); i+=3) { - if (x[i] >= xmx) xmx = x[i]; - if (x[i] <= xmn) xmn = x[i]; - } - - for (std::size_t i = 1; i < x.size(); i+=3) { - if (x[i] >= ymx) ymx = x[i]; - if (x[i] <= ymn) ymn = x[i]; - } - - for (std::size_t i = 2; i < x.size(); i+=3) { - if (x[i] >= zmx) zmx = x[i]; - if (x[i] <= zmn) zmn = x[i]; - } - - double delx = std::abs(xmx - xmn); - double dely = std::abs(ymx - ymn); - double delz = std::abs(zmx - zmn); - double delta = 1.0; - - for (std::size_t i = 0; i < x.size(); i++) { - if (i % 3 == 0) delta = delx; - if (i % 3 == 1) delta = dely; - if (i % 3 == 2) delta = delz; - - if (delta < eps) - h = eps * std::abs(x[i]); - else - h = eps * delta; - - x[i] = x[i] + h; - double ff = getValue(x); - x[i] = x[i] - h; - - x[i] = x[i] - h; - double fb = getValue(x); - x[i] = x[i] + h; - - df = (ff - fb)/(2.0 * h); - g.push_back(df); - } - return g; -} +/* vector FaceReshapeObjFunc :: getGrad(const vector &_x) */ +/* { */ +/* vector x; */ +/* for (int i = 0; i < _x.size(); i++) { */ +/* x[i] = _x[i]; */ +/* } */ + +/* //double fold = getValue(x); */ +/* // TODO : Why the following value */ +/* double eps = 1.0e-4; */ +/* double h = eps; */ +/* std::vector g; */ +/* double xmx = x[0]; */ +/* double xmn = x[0]; */ +/* double ymx = x[1]; */ +/* double ymn = x[1]; */ +/* double zmx = x[2]; */ +/* double zmn = x[2]; */ +/* double df = 0.0, dff = 0.0, dbb = 0.0; */ + +/* for (std::size_t i = 0; i < x.size(); i+=3) { */ +/* if (x[i] >= xmx) xmx = x[i]; */ +/* if (x[i] <= xmn) xmn = x[i]; */ +/* } */ + +/* for (std::size_t i = 1; i < x.size(); i+=3) { */ +/* if (x[i] >= ymx) ymx = x[i]; */ +/* if (x[i] <= ymn) ymn = x[i]; */ +/* } */ + +/* for (std::size_t i = 2; i < x.size(); i+=3) { */ +/* if (x[i] >= zmx) zmx = x[i]; */ +/* if (x[i] <= zmn) zmn = x[i]; */ +/* } */ + +/* double delx = std::abs(xmx - xmn); */ +/* double dely = std::abs(ymx - ymn); */ +/* double delz = std::abs(zmx - zmn); */ +/* double delta = 1.0; */ + +/* for (std::size_t i = 0; i < x.size(); i++) { */ +/* if (i % 3 == 0) delta = delx; */ +/* if (i % 3 == 1) delta = dely; */ +/* if (i % 3 == 2) delta = delz; */ + +/* if (delta < eps) */ +/* h = eps * std::abs(x[i]); */ +/* else */ +/* h = eps * delta; */ + +/* x[i] = x[i] + h; */ +/* double ff = getValue(x); */ +/* x[i] = x[i] - h; */ + +/* x[i] = x[i] - h; */ +/* double fb = getValue(x); */ +/* x[i] = x[i] + h; */ + +/* df = (ff - fb)/(2.0 * h); */ +/* g.push_back(df); */ +/* } */ +/* return g; */ +/* } */ vector FaceReshapeObjFunc :: getInitialGuess() { diff --git a/crv/crvObjectiveFunctions.h b/crv/crvObjectiveFunctions.h index e14b3dfa3..c08be0755 100644 --- a/crv/crvObjectiveFunctions.h +++ b/crv/crvObjectiveFunctions.h @@ -13,6 +13,33 @@ using namespace std; +static double getLinearVolPhys(apf::Mesh2* m, apf::MeshEntity* e) +{ + apf::MeshEntity* vs[12]; + int n = m->getDownward(e, 0, vs); + apf::Vector3 coords[12]; + for (int i = 0; i < n; i++) { + m->getPoint(vs[i], 0, coords[i]); + } + + if (m->getType(e) == apf::Mesh::TRIANGLE) + { + return apf::cross(coords[1]-coords[0], coords[2]-coords[0]).getLength()/2.; + } + else if (m->getType(e) == apf::Mesh::TET) + { + apf::Matrix3x3 J; + J[0] = coords[1] - coords[0]; + J[1] = coords[2] - coords[0]; + J[2] = coords[3] - coords[0]; + return apf::getDeterminant(J) / 6.; + } + else + PCU_ALWAYS_ASSERT_VERBOSE(0, + "Not implemented for entities of type other than tri or tet!"); + return 0.; +} + namespace crv { @@ -21,9 +48,31 @@ class ObjFunction public: ObjFunction(){}; virtual int getSpaceDim() = 0; + virtual double getTol() = 0; virtual double getValue(const vector &x) = 0; // TODO :: can we do this once for all the objective functions? - virtual vector getGrad(const vector &_x) = 0; + vector getGrad(const vector &_x) + { + double h; + vector x = _x; + double eps = this->getTol(); + vector g; + for (size_t i = 0; i < x.size(); i++) { + h = abs(x[i]) > eps ? eps * abs(x[i]) : eps; + + // forward diff + x[i] += h; + double ff = this->getValue(x); + x[i] -= h; + + // backward diff + x[i] -= h; + double fb = this->getValue(x); + x[i] += h; + + g.push_back( (ff - fb) / 2./ h ); + } + } }; @@ -45,11 +94,13 @@ class InternalEdgeReshapeObjFunc : public ObjFunction getInitEdgeN(); getInitFaceN(); getInitTetN(); + tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; } ~InternalEdgeReshapeObjFunc(){} int getSpaceDim(); + double getTol() {return tol;} double getValue(const vector &x); - vector getGrad(const vector &x); + /* vector getGrad(const vector &x); */ vector getInitialGuess(); void setNodes(const vector &x); void restoreInitialNodes(); @@ -82,6 +133,7 @@ class InternalEdgeReshapeObjFunc : public ObjFunction vector ien; vector ifn; vector itn; + double tol; }; @@ -101,11 +153,13 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction getInitEdgeN(); getInitFaceN(); getInitTetN(); + tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; } ~BoundaryEdgeReshapeObjFunc(){} int getSpaceDim(); + double getTol() {return tol;} double getValue(const vector &x); - vector getGrad(const vector &x); + /* vector getGrad(const vector &x); */ vector getInitialGuess(); void setNodes(const vector &x); void restoreInitialNodes(); @@ -142,6 +196,7 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction vector ifn; vector itpfn; vector itn; + double tol; }; class FaceReshapeObjFunc : public ObjFunction @@ -155,11 +210,13 @@ class FaceReshapeObjFunc : public ObjFunction getSpaceDim(); getInitFaceN(); getInitTetN(); + tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; } ~FaceReshapeObjFunc() {} int getSpaceDim(); + double getTol() {return tol;} double getValue(const vector &x); - vector getGrad(const vector &_x); + /* vector getGrad(const vector &_x); */ vector getInitialGuess(); void setNodes(const vector &x); void restoreInitialNodes(); @@ -180,6 +237,7 @@ class FaceReshapeObjFunc : public ObjFunction apf::MeshEntity* tet; vector ifn; vector itn; + double tol; }; } From 75534706240196465a7c73ed801bc9db3eb9a091 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 15 Feb 2020 14:35:54 -0500 Subject: [PATCH 39/48] fixed getGrad() + increased r --- crv/LBFGS.h | 2 +- crv/crvObjectiveFunctions.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crv/LBFGS.h b/crv/LBFGS.h index fdf18eb38..198e82964 100644 --- a/crv/LBFGS.h +++ b/crv/LBFGS.h @@ -39,7 +39,7 @@ class LBFGS double fValAfter; private: - int r = 40; + int r = 50; }; } diff --git a/crv/crvObjectiveFunctions.h b/crv/crvObjectiveFunctions.h index c08be0755..2e992601e 100644 --- a/crv/crvObjectiveFunctions.h +++ b/crv/crvObjectiveFunctions.h @@ -72,6 +72,7 @@ class ObjFunction g.push_back( (ff - fb) / 2./ h ); } + return(g); } }; From de1b46dac1213c57c0921569fc04282e79208961 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sun, 16 Feb 2020 12:26:46 -0500 Subject: [PATCH 40/48] Implements the fval computatin based on detJ --- crv/crvObjectiveFunctions.cc | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index afa84aabc..4c0bc2a36 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -5,6 +5,7 @@ #include "crvBezier.h" #include "crvQuality.h" #include "crvMath.h" +#include "apfIntegrate.h" @@ -111,8 +112,27 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s) { - // TODO: To be completed - return 0; + apf::EntityIntegration *eInt = new apf::EntityIntegration(); + apf::Integration *ir = eInt->getIntegration(m->getType(e)); + int nip = eInt->countIntegrations(); + + apf::MeshElement* me = apf::createMeshElement(m, e); + Matrix3x3 J, T, Jm; + + double jDet, sum = 0.; + + for (int i = 0; i < nip; i++) { + IntegrationPoint *ip = ir->getPoint(i); + Vector3 qp = ip->param; + double w = ip->weight; + apf::getJacobian(me, qp, J); + + s->getTransform(me, qp, T); + Jm = J*T; // Jacobian in metric space + determinant(Jm, jDet); + sum += (jDet - 1.) * (jDet - 1); + } + return sum; } From 9dea00cfab87cf3f7f9e43e6f9d9f4ea84f6519a Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Sun, 16 Feb 2020 15:56:22 -0500 Subject: [PATCH 41/48] Brings in the size-field info for the reshape ops --- crv/crv.h | 1 + crv/crvObjectiveFunctions.cc | 131 ++------------------------------ crv/crvObjectiveFunctions.h | 51 +++++++++---- crv/crvOptimizations.cc | 140 +++++++++++++++++++++++++++++++---- crv/crvOptimizations.h | 69 ++++++++++++++--- crv/crvShape.cc | 6 +- 6 files changed, 231 insertions(+), 167 deletions(-) diff --git a/crv/crv.h b/crv/crv.h index c68a11fca..08d08d3bf 100644 --- a/crv/crv.h +++ b/crv/crv.h @@ -21,6 +21,7 @@ /** \namespace crv * \brief the curving functions are contained in this namespace */ namespace crv { +enum {NIJK, DETJ}; /** \brief actually 1 greater than max order */ static unsigned const MAX_ORDER = 19; diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index 4c0bc2a36..e140f422d 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -5,8 +5,6 @@ #include "crvBezier.h" #include "crvQuality.h" #include "crvMath.h" -#include "apfIntegrate.h" - static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) @@ -17,125 +15,6 @@ static double getAr(apf::Vector3 p0, apf::Vector3 p1, apf::Vector3 p2) return (area/2.0); } -/* static double getLinearVolPhys(apf::Mesh2* m, apf::MeshEntity* e) */ -/* { */ -/* apf::MeshEntity* vs[12]; */ -/* int n = m->getDownward(e, 0, vs); */ -/* apf::Vector3 coords[12]; */ -/* for (int i = 0; i < n; i++) { */ -/* m->getPoint(vs[i], 0, coords[i]); */ -/* } */ - -/* if (m->getType(e) == apf::Mesh::TRIANGLE) */ -/* { */ -/* return apf::cross(coords[1]-coords[0], coords[2]-coords[0]).getLength()/2.; */ -/* } */ -/* else if (m->getType(e) == apf::Mesh::TET) */ -/* { */ -/* apf::Matrix3x3 J; */ -/* J[0] = coords[1] - coords[0]; */ -/* J[1] = coords[2] - coords[0]; */ -/* J[2] = coords[3] - coords[0]; */ -/* return apf::getDeterminant(J) / 6.; */ -/* } */ -/* else */ -/* PCU_ALWAYS_ASSERT_VERBOSE(0, */ -/* "Not implemented for entities of type other than tri or tet!"); */ -/* return 0.; */ -/* } */ - -static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s = 0) -{ - PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); - - int d = m->getDimension(); - int P = m->getShape()->getOrder(); - - apf::NewArray nodes; - apf::Element* el = apf::createElement(m->getCoordinateField(), e); - apf::getVectorNodes(el, nodes); - apf::destroyElement(el); - - double volm = getLinearVolPhys(m, e); - - int weight = 1; - double sumf = 0; - if (d == 3) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - for (int L = 0; L <= d*(P-1); L++) { - if ((I == J && J == K && I == 0) || - (J == K && K == L && J == 0) || - (I == K && K == L && I == 0) || - (I == J && J == L && I == 0)) - weight = 4; - else if ((I == J && I == 0) || - (I == K && I == 0) || - (I == L && I == 0) || - (J == K && J == 0) || - (J == L && J == 0) || - (K == L && K == 0)) - weight = 2; - else - weight = 1; - if (I + J + K + L == d*(P-1)) { - double f = crv::Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; - sumf = sumf + weight*f*f; - } - } - } - } - } - } - - if (d == 2) { - for (int I = 0; I <= d*(P-1); I++) { - for (int J = 0; J <= d*(P-1); J++) { - for (int K = 0; K <= d*(P-1); K++) { - if ((I == J && I == 0) || - (J == K && J == 0) || - (I == K && I == 0)) - weight = 2; - else - weight = 1; - if (I + J + K == d*(P-1)) { - double f = crv::Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; - sumf = sumf + weight*f*f; - } - } - } - } - } - return sumf; -} - -static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s) -{ - apf::EntityIntegration *eInt = new apf::EntityIntegration(); - apf::Integration *ir = eInt->getIntegration(m->getType(e)); - int nip = eInt->countIntegrations(); - - apf::MeshElement* me = apf::createMeshElement(m, e); - Matrix3x3 J, T, Jm; - - double jDet, sum = 0.; - - for (int i = 0; i < nip; i++) { - IntegrationPoint *ip = ir->getPoint(i); - Vector3 qp = ip->param; - double w = ip->weight; - apf::getJacobian(me, qp, J); - - s->getTransform(me, qp, T); - Jm = J*T; // Jacobian in metric space - determinant(Jm, jDet); - sum += (jDet - 1.) * (jDet - 1); - } - return sum; -} - - namespace crv { @@ -153,7 +32,7 @@ double InternalEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 2, adjF); for (std::size_t i = 0; i < adjF.getSize(); i++) { - sum = sum + computeFValNIJKL(mesh, adjF[i]); + sum = sum + f(mesh, adjF[i], size); } restoreInitialNodes(); } @@ -162,7 +41,7 @@ double InternalEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - sum = sum + computeFValNIJKL(mesh, adjT[i]); + sum = sum + f(mesh, adjT[i], size); } // TODO: In the original code this line is commented. Why? restoreInitialNodes(); @@ -444,7 +323,7 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 2, adjF); for (std::size_t i = 0; i < adjF.getSize(); i++) { - sum = sum + computeFValNIJKL(mesh, adjF[i]); + sum = sum + f(mesh, adjF[i], size); } restoreInitialNodes(); } @@ -454,7 +333,7 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) apf::NewArray allNodes; mesh->getAdjacent(edge, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - sum = sum + computeFValNIJKL(mesh, adjT[i]); + sum = sum + f(mesh, adjT[i], size); } double ad = 0.0; @@ -952,7 +831,7 @@ double FaceReshapeObjFunc :: getValue(const std::vector &x) apf::NewArray allNodes; mesh->getAdjacent(face, 3, adjT); for (std::size_t i = 0; i < adjT.getSize(); i++) { - sum = sum + computeFValNIJKL(mesh, adjT[i]); + sum = sum + f(mesh, adjT[i], size); } restoreInitialNodes(); } diff --git a/crv/crvObjectiveFunctions.h b/crv/crvObjectiveFunctions.h index 2e992601e..eec215678 100644 --- a/crv/crvObjectiveFunctions.h +++ b/crv/crvObjectiveFunctions.h @@ -10,6 +10,7 @@ #include #include #include +#include "crvAdapt.h" using namespace std; @@ -86,16 +87,22 @@ class ObjFunction class InternalEdgeReshapeObjFunc : public ObjFunction { public: - InternalEdgeReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) + InternalEdgeReshapeObjFunc( + crv::Adapt* a, + apf::MeshEntity* e, + apf::MeshEntity* t, + double (*fPtr)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*)) : + adapt(a), edge(e), tet(t), f(fPtr) { + mesh = adapt->mesh; + size = adapt->sizeField; P = mesh->getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); getInitEdgeN(); getInitFaceN(); getInitTetN(); - tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; + tol = cbrt(getLinearVolPhys(mesh, t)) * 1.e-3; } ~InternalEdgeReshapeObjFunc(){} int getSpaceDim(); @@ -128,9 +135,12 @@ class InternalEdgeReshapeObjFunc : public ObjFunction const vector &fa, const vector &te); protected: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* edge; apf::MeshEntity* tet; + double (*f)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*); + apf::Mesh2* mesh; + ma::SizeField* size; vector ien; vector ifn; vector itn; @@ -143,18 +153,21 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction { public: BoundaryEdgeReshapeObjFunc( - apf::Mesh2* m, + crv::Adapt* a, apf::MeshEntity* e, - apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) + apf::MeshEntity* t, + double (*fPtr)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*)) : + adapt(a), edge(e), tet(t), f(fPtr) { + mesh = adapt->mesh; + size = adapt->sizeField; P = mesh->getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); getInitEdgeN(); getInitFaceN(); getInitTetN(); - tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; + tol = cbrt(getLinearVolPhys(mesh, t)) * 1.e-3; } ~BoundaryEdgeReshapeObjFunc(){} int getSpaceDim(); @@ -190,9 +203,12 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction const vector &te, bool isInitialX); protected: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* edge; apf::MeshEntity* tet; + double (*f)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*); + apf::Mesh2* mesh; + ma::SizeField* size; vector ien; vector ifn; vector itpfn; @@ -203,15 +219,21 @@ class BoundaryEdgeReshapeObjFunc : public ObjFunction class FaceReshapeObjFunc : public ObjFunction { public: - FaceReshapeObjFunc(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : - mesh(m), face(f), tet(t) + FaceReshapeObjFunc( + crv::Adapt* a, + apf::MeshEntity* f, + apf::MeshEntity* t, + double (*fPtr)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*)) : + adapt(a), face(f), tet(t), f(fPtr) { + mesh = adapt->mesh; + size = adapt->sizeField; P = mesh->getShape()->getOrder(); d = mesh->getDimension(); getSpaceDim(); getInitFaceN(); getInitTetN(); - tol = cbrt(getLinearVolPhys(m, t)) * 1.e-3; + tol = cbrt(getLinearVolPhys(mesh, t)) * 1.e-3; } ~FaceReshapeObjFunc() {} int getSpaceDim(); @@ -233,9 +255,12 @@ class FaceReshapeObjFunc : public ObjFunction const vector &fa, const vector &te); protected: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* face; apf::MeshEntity* tet; + double (*f)(apf::Mesh2*, apf::MeshEntity*, ma::SizeField*); + apf::Mesh2* mesh; + ma::SizeField* size; vector ifn; vector itn; double tol; diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index 250d38eb9..10f5176e2 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -1,15 +1,15 @@ -#include "LBFGS.h" +#include +#include +#include +#include +#include #include "crvOptimizations.h" #include "crv.h" -#include "gmi.h" -#include "apfMDS.h" -#include "apfNumbering.h" #include "crvQuality.h" #include "crvBezier.h" #include "crvMath.h" #include "crvDBG.h" #include -#include "apfMatrix.h" /* static int global_counter = 0; */ /* static apf::MeshEntity* tetra[100]; */ @@ -36,9 +36,97 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn } } +static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s = 0) +{ + PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); + + int d = m->getDimension(); + int P = m->getShape()->getOrder(); + + apf::NewArray nodes; + apf::Element* el = apf::createElement(m->getCoordinateField(), e); + apf::getVectorNodes(el, nodes); + apf::destroyElement(el); + + double volm = getLinearVolPhys(m, e); + + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double f = crv::Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + } -namespace crv{ + if (d == 2) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + if ((I == J && I == 0) || + (J == K && J == 0) || + (I == K && I == 0)) + weight = 2; + else + weight = 1; + if (I + J + K == d*(P-1)) { + double f = crv::Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + return sumf; +} +static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s) +{ + int order = m->getShape()->getOrder(); + apf::MeshElement* me = apf::createMeshElement(m, e); + apf::Matrix3x3 J; + apf::Matrix3x3 T; + apf::Matrix3x3 Jm; + + double jDet, sum = 0.; + for (int i = 0; i < apf::countIntPoints(me, order) ; i++) { + apf::Vector3 qp; + double w = apf::getIntWeight(me, order, i); + apf::getIntPoint(me, order, i, qp); + + apf::getJacobian(me, qp, J); + s->getTransform(me, qp, T); + Jm = J*T; // Jacobian in metric space + jDet = apf::getDeterminant(Jm); + sum += w * (jDet - 1.) * (jDet - 1.); + } + return sum; +} + + +namespace crv{ void CrvInternalEdgeOptim :: setMaxIter(int n) { @@ -71,12 +159,21 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); /* printTetNumber(mesh, tet); */ /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ - InternalEdgeReshapeObjFunc *objF = new InternalEdgeReshapeObjFunc(mesh, edge, tet); + switch (mode) { + case NIJK: + objF = new InternalEdgeReshapeObjFunc(adapt, edge, tet, computeFValNIJKL); + break; + case DETJ: + objF = new InternalEdgeReshapeObjFunc(adapt, edge, tet, computeFValDetJ); + break; + default: + break; + } std::vector x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0< x0 = objF->getInitialGuess(); //double f0 = objF->getValue(x0); //std::cout<< "fval at x0 " << f0<mesh; + } + ~CrvInternalEdgeOptim() + { + delete objF; + delete l; + } public: void setMaxIter(int n); void setTol(double tolerance); bool run(int &invaliditySize); public: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* edge; apf::MeshEntity* tet; + int mode; + apf::Mesh2* mesh; + InternalEdgeReshapeObjFunc* objF; int iter; double tol; std::vector finalX; @@ -47,18 +64,32 @@ class CrvInternalEdgeOptim : public CrvEntityOptim class CrvBoundaryEdgeOptim : public CrvEntityOptim { public: - CrvBoundaryEdgeOptim(apf::Mesh2* m, apf::MeshEntity* e, apf::MeshEntity* t) : - mesh(m), edge(e), tet(t) {} - ~CrvBoundaryEdgeOptim(){} + CrvBoundaryEdgeOptim( + crv::Adapt* a, + apf::MeshEntity* e, + apf::MeshEntity* t, + int m) : + adapt(a), edge(e), tet(t), mode(m) + { + mesh = adapt->mesh; + } + ~CrvBoundaryEdgeOptim() + { + delete objF; + delete l; + } public: void setMaxIter(int n); void setTol(double tolerance); bool run(int &invaliditySize); public: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* edge; apf::MeshEntity* tet; + int mode; + apf::Mesh2* mesh; + BoundaryEdgeReshapeObjFunc* objF; int iter; double tol; std::vector finalX; @@ -68,18 +99,32 @@ class CrvBoundaryEdgeOptim : public CrvEntityOptim class CrvFaceOptim : public CrvEntityOptim { public: - CrvFaceOptim(apf::Mesh2* m, apf::MeshEntity* f, apf::MeshEntity* t) : - mesh(m), face(f), tet(t) {} - ~CrvFaceOptim(){} + CrvFaceOptim( + crv::Adapt* a, + apf::MeshEntity* f, + apf::MeshEntity* t, + int m) : + adapt(a), face(f), tet(t), mode(m) + { + mesh = adapt->mesh; + } + ~CrvFaceOptim() + { + delete objF; + delete l; + } public: void setMaxIter(int n); void setTol(double tolerance); bool run(int &invaliditySize); public: - apf::Mesh2* mesh; + crv::Adapt* adapt; apf::MeshEntity* face; apf::MeshEntity* tet; + int mode; + apf::Mesh2* mesh; + FaceReshapeObjFunc* objF; int iter; double tol; std::vector finalX; diff --git a/crv/crvShape.cc b/crv/crvShape.cc index e4b67f766..19f331549 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -1138,7 +1138,7 @@ class FaceOptimizer : public ma::Operator if (numf == 0) return; for (int i = 0; i < numf; i++ ) { if (mesh->getModelType(mesh->toModel(faces[i])) != 3) continue; - CrvFaceOptim *cfo = new CrvFaceOptim(mesh, faces[i], simplex); + CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, DETJ); cfo->setMaxIter(100); cfo->setTol(1e-8); if (cfo->run(invaliditySize)) { @@ -1211,9 +1211,9 @@ class EdgeOptimizer : public ma::Operator CrvEntityOptim* ceo; if (mesh->getModelType(mesh->toModel(edges[i])) == 3) - ceo = new CrvInternalEdgeOptim(mesh, edges[i], simplex); + ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, DETJ); else - ceo = new CrvBoundaryEdgeOptim(mesh, edges[i], simplex); + ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, DETJ); ceo->setMaxIter(100); ceo->setTol(1e-8); From b279d6ee3c63f63d668376ab5fb01a6a1b4cbea1 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 29 Feb 2020 13:47:00 -0500 Subject: [PATCH 42/48] -new Objective function + corresponding modifications --- crv/CMakeLists.txt | 3 + crv/crv.h | 2 +- crv/crvObjectiveFunctions.cc | 4 +- crv/crvOptimizations.cc | 196 +++++++++++++++++++++++++++++++++-- crv/crvShape.cc | 15 ++- ma/CMakeLists.txt | 2 + 6 files changed, 204 insertions(+), 18 deletions(-) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 4ed162673..19aedf493 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -35,6 +35,9 @@ set(HEADERS crvBezier.h crvTables.h crvQuality.h + crvAdapt.h + LBFGS.h + crvMath.h ) # Add the crv library diff --git a/crv/crv.h b/crv/crv.h index 08d08d3bf..f965ff045 100644 --- a/crv/crv.h +++ b/crv/crv.h @@ -21,7 +21,7 @@ /** \namespace crv * \brief the curving functions are contained in this namespace */ namespace crv { -enum {NIJK, DETJ}; +enum {NIJK, DETJ, DETJNIJK}; /** \brief actually 1 greater than max order */ static unsigned const MAX_ORDER = 19; diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index e140f422d..9de9488b6 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -373,7 +373,7 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) } //sum = sum*(1 + beta); - /* apf::destroyElement(Edl); */ + // apf::destroyElement(Edl); apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); @@ -422,7 +422,7 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) } } } - /* double gamma = 0.0; */ + // double gamma = 0.0; sum = sum*(1 + beta + 0.3*gamma); restoreInitialNodes(); } diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index 10f5176e2..62c1c133b 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -8,6 +8,7 @@ #include "crvQuality.h" #include "crvBezier.h" #include "crvMath.h" +#include "crvTables.h" #include "crvDBG.h" #include @@ -38,6 +39,7 @@ static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEn static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s = 0) { + s = 0; PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); int d = m->getDimension(); @@ -61,16 +63,16 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 4; + weight = 1; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 2; + weight = 0; else - weight = 1; + weight = 0; if (I + J + K + L == d*(P-1)) { double f = crv::Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; sumf = sumf + weight*f*f; @@ -102,6 +104,112 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* return sumf; } +static double computeDetW(apf::MeshElement* me, const apf::Vector3 &xi) +{ + apf::Vector3 xyz; + apf::mapLocalToGlobal(me, xi, xyz); + + //Metric size field + //r1 = 0.0325, r2 = 0.025, h = 0.2 + double tsq = 0.0075 * 0.0075; + double hsq = 0.1 * 0.1; + double ssq = 3.141 * 3.141 * 0.02875 * 0.02875/4.0; + + double rsq = (xyz[0] * xyz[0] + xyz[1] * xyz[1]); + + double xsq = xyz[0]*xyz[0]; + double ysq = xyz[1]*xyz[1]; + + double M11 = (xsq/tsq + ysq/ssq)/rsq; + double M12 = (xyz[0]*xyz[1])*(1./tsq - 1./ssq)/rsq; + double M22 = (ysq/tsq + xsq/ssq)/rsq; + double M33 = 1./hsq; + + apf::Matrix3x3 M(M11, M12, 0., M12, M22, 0., 0., 0., M33); + double detM = apf::getDeterminant(M); + + return (sqrt(detM)); + +} + +static double computeFValDetJNIJKL(apf::Mesh2* m, + apf::MeshEntity* e, ma::SizeField* s = 0) +{ + s = 0; + PCU_ALWAYS_ASSERT_VERBOSE(s == 0, "Not implemented for non-zero sizefield!"); + + int d = m->getDimension(); + int P = m->getShape()->getOrder(); + + apf::NewArray nodes; + apf::Element* el = apf::createElement(m->getCoordinateField(), e); + apf::getVectorNodes(el, nodes); + apf::destroyElement(el); + + apf::MeshElement* me = apf::createMeshElement(m, e); + double volm = getLinearVolPhys(m, e); + + int n = crv::getNumControlPoints(apf::Mesh::TET, d*(P-1)); + apf::NewArray xi; + xi.allocate(n); + + crv::collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, d*(P-1), + crv::elem_vert_xi[apf::Mesh::TET], xi); + + int weight = 1; + double sumf = 0; + if (d == 3) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + for (int L = 0; L <= d*(P-1); L++) { + if ((I == J && J == K && I == 0) || + (J == K && K == L && J == 0) || + (I == K && K == L && I == 0) || + (I == J && J == L && I == 0)) + weight = 4; + else if ((I == J && I == 0) || + (I == K && I == 0) || + (I == L && I == 0) || + (J == K && J == 0) || + (J == L && J == 0) || + (K == L && K == 0)) + weight = 2; + else + weight = 1; + if (I + J + K + L == d*(P-1)) { + double detW = computeDetW(me, xi[crv::getTetNodeIndex(d*(P-1),I,J,K)]); + double f = detW * crv::Nijkl(nodes,P,I,J,K)/(6.0) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + + apf::destroyMeshElement(me); + } + + if (d == 2) { + for (int I = 0; I <= d*(P-1); I++) { + for (int J = 0; J <= d*(P-1); J++) { + for (int K = 0; K <= d*(P-1); K++) { + if ((I == J && I == 0) || + (J == K && J == 0) || + (I == K && I == 0)) + weight = 2; + else + weight = 1; + if (I + J + K == d*(P-1)) { + double f = crv::Nijk(nodes,P,I,J)/(4.0*volm) - 1.0; + sumf = sumf + weight*f*f; + } + } + } + } + } + return sumf; +} static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* s) { int order = m->getShape()->getOrder(); @@ -111,17 +219,64 @@ static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* apf::Matrix3x3 Jm; double jDet, sum = 0.; + double jDet1, jDet2; + + double volm = getLinearVolPhys(m, e); + /* for (int i = 0; i < apf::countIntPoints(me, order) ; i++) { apf::Vector3 qp; double w = apf::getIntWeight(me, order, i); apf::getIntPoint(me, order, i, qp); apf::getJacobian(me, qp, J); +*/ + /* s->getTransform(me, qp, T); Jm = J*T; // Jacobian in metric space jDet = apf::getDeterminant(Jm); - sum += w * (jDet - 1.) * (jDet - 1.); + */ + /* + jDet = apf::getDeterminant(J) * computeDetW(me, qp); + + sum += (jDet/6.0 - 1.) * (jDet/6.0 - 1.); + */ + /* + apf::Vector3 xyz; + apf::mapLocalToGlobal(me, qp, xyz); + std::cout<<"Xi: "<< qp <<" XYZ: "<getTransform(me, v[i], T); + //Jm = J*T; + jDet1 = apf::getDeterminant(J); + jDet2 = computeDetW(me, v[i]); + jDet = jDet1 * jDet2; + sum += (jDet1/(6.0*volm) - 1.0) * (jDet1/(6.0*volm) - 1.0); } + apf::destroyMeshElement(me); + return sum; } @@ -154,6 +309,9 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) } + //crv_dbg::visualizeCavityMesh(mesh, edge, "before_cavity_Iedge_NIJK", + // mesh->findNumbering("debug_num_tet"), 15); + //std::vector ai = crv::getAllInvalidities(mesh, tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); @@ -166,6 +324,9 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) case DETJ: objF = new InternalEdgeReshapeObjFunc(adapt, edge, tet, computeFValDetJ); break; + case DETJNIJK: + objF = new InternalEdgeReshapeObjFunc(adapt, edge, tet, computeFValDetJNIJKL); + break; default: break; } @@ -184,7 +345,7 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) mesh->getDownward(adj[i], 1, ed); int edgeIndex = apf::findIn(ed, 6, edge); printf("reshape tried on %d edge, TET %d; ", edgeIndex, thisTETnum); - crv_dbg::printTetNumber(mesh, adj[i], "debug_num_tet"); + //crv_dbg::printTetNumber(mesh, adj[i], "debug_num_tet"); } bool hasDecreased = false; @@ -203,6 +364,8 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) } if (hasDecreased == false ) { + //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_Iedge_NIJK", + // mesh->findNumbering("debug_num_tet"), 15); //invaliditySize = 0; //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); @@ -212,7 +375,7 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) } else { //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - /* objF->restoreInitialNodes(); */ + objF->restoreInitialNodes(); /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ std::cout<<"Size DID NOT decrease"<currentX; - //objF->setNodes(finalX); + //finalX = l->currentX; + //objF->setNodes(finalX); //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); if (thisTetSize == 0) { std::cout<<" No Optimization tried"<findNumbering("debug_num_tet"), 15); //std::vector ai = crv::getAllInvalidities(mesh,tet); //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); @@ -272,6 +437,9 @@ bool CrvBoundaryEdgeOptim :: run(int &invaliditySize) case DETJ: objF = new BoundaryEdgeReshapeObjFunc(adapt, edge, tet, computeFValDetJ); break; + case DETJNIJK: + objF = new BoundaryEdgeReshapeObjFunc(adapt, edge, tet, computeFValDetJNIJKL); + break; default: break; } @@ -308,8 +476,12 @@ bool CrvBoundaryEdgeOptim :: run(int &invaliditySize) hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); } + //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_onlyV_Bedge_NIJK", + // mesh->findNumbering("debug_num_tet"), 15); + if (hasDecreased == false) { - //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); + //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_Bedge_NIJK", + // mesh->findNumbering("debug_num_tet"), 15); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); printInvalidities(mesh, adj_array, edge, adj.getSize()); std::cout<<"--------------------------------------"<currentX; //objF->setNodes(finalX); + if (thisTetSize == 0) { std::cout<<"No Optimization tried"< ai = crv::getAllInvalidities(mesh, adj[i]); //if (adj[i] == tet) thisTetSize = ai.size(); - //sizeHolder.push_back(ai.size()); + //sizeHolder.push_back(ai.size()); } std::vector ai = crv::getAllInvalidities(mesh, tet); @@ -374,6 +547,9 @@ bool CrvFaceOptim :: run(int &invaliditySize) case DETJ: objF = new FaceReshapeObjFunc(adapt, face, tet, computeFValDetJ); break; + case DETJNIJK: + objF = new FaceReshapeObjFunc(adapt, face, tet, computeFValDetJNIJKL); + break; default: break; } diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 19f331549..5594b856d 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -1138,7 +1138,8 @@ class FaceOptimizer : public ma::Operator if (numf == 0) return; for (int i = 0; i < numf; i++ ) { if (mesh->getModelType(mesh->toModel(faces[i])) != 3) continue; - CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, DETJ); + //CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, DETJ); + CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, NIJK); cfo->setMaxIter(100); cfo->setTol(1e-8); if (cfo->run(invaliditySize)) { @@ -1210,10 +1211,14 @@ class EdgeOptimizer : public ma::Operator bool hasDecreased = false; CrvEntityOptim* ceo; - if (mesh->getModelType(mesh->toModel(edges[i])) == 3) - ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, DETJ); - else - ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, DETJ); + if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { + //ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, DETJ); + ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, NIJK); + } + else { + //ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, DETJ); + ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, NIJK); + } ceo->setMaxIter(100); ceo->setTol(1e-8); diff --git a/ma/CMakeLists.txt b/ma/CMakeLists.txt index 68e72d2ea..607a43d20 100644 --- a/ma/CMakeLists.txt +++ b/ma/CMakeLists.txt @@ -63,6 +63,8 @@ set(HEADERS maExtrude.h maDBG.h maStats.h + maAdapt.h + maRefine.h ) # Add the ma library From df542ecd6a9146878316bb7156a33c153482e00d Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Sat, 29 Feb 2020 14:03:07 -0500 Subject: [PATCH 43/48] fixed weights for NIKL optimization funtion --- crv/crvOptimizations.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index 62c1c133b..cefc7df42 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -63,16 +63,16 @@ static double computeFValNIJKL(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* (J == K && K == L && J == 0) || (I == K && K == L && I == 0) || (I == J && J == L && I == 0)) - weight = 1; + weight = 4; else if ((I == J && I == 0) || (I == K && I == 0) || (I == L && I == 0) || (J == K && J == 0) || (J == L && J == 0) || (K == L && K == 0)) - weight = 0; + weight = 2; else - weight = 0; + weight = 1; if (I + J + K + L == d*(P-1)) { double f = crv::Nijkl(nodes,P,I,J,K)/(6.0*volm) - 1.0; sumf = sumf + weight*f*f; From a6b1005a3839d84ea81482844697b17d3a548ea6 Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Mon, 2 Mar 2020 15:48:37 -0500 Subject: [PATCH 44/48] Cleans the code before dev is merged into branch --- crv/CMakeLists.txt | 9 - crv/crv.h | 18 +- crv/crvAdapt.cc | 22 +-- crv/crvCurveMesh.cc | 18 +- crv/crvQuality.cc | 93 +--------- crv/crvQuality.h | 10 +- crv/crvShape.cc | 415 ++------------------------------------------ crv/crvTables.h | 7 +- crv/crvVtk.cc | 51 +----- 9 files changed, 59 insertions(+), 584 deletions(-) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 19aedf493..68ec722dd 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -29,15 +29,6 @@ set(SOURCES # Package headers set(HEADERS crv.h - crvDBG.h - crvOptimizations.h - crvObjectiveFunctions.h - crvBezier.h - crvTables.h - crvQuality.h - crvAdapt.h - LBFGS.h - crvMath.h ) # Add the crv library diff --git a/crv/crv.h b/crv/crv.h index f965ff045..7d0ce1224 100644 --- a/crv/crv.h +++ b/crv/crv.h @@ -21,7 +21,14 @@ /** \namespace crv * \brief the curving functions are contained in this namespace */ namespace crv { -enum {NIJK, DETJ, DETJNIJK}; + + +/** \brief choices of objective function for reshape*/ +enum { + NIJK, // based on Jacobian coefficients + DETJ, // based on Jacobian Determinant Values at Integration Points + DETJNIJK // based on TODO : to be decided +}; /** \brief actually 1 greater than max order */ static unsigned const MAX_ORDER = 19; @@ -48,16 +55,13 @@ class MeshCurver public: MeshCurver(apf::Mesh2* m, int P) : m_mesh(m), m_order(P) {}; virtual ~MeshCurver() {}; - virtual bool run(bool flag) = 0; + virtual bool run() = 0; /** \brief snaps points to interpolating locations */ void snapToInterpolate(int dim); /** \brief wrapper around synchronizeFieldData */ void synchronize(); - - //public: - // bool flag = 1; protected: apf::Mesh2* m_mesh; @@ -92,11 +96,9 @@ class BezierCurver : public MeshCurver /** \brief curves a mesh using bezier curves of chosen order \details finds interpolating points, then converts to control points see crvBezier.cc */ - virtual bool run(bool flag); + virtual bool run(); /** \brief converts interpolating points to bezier control points */ void convertInterpolatingToBezier(); - //public: - // bool flag = true; }; /** \brief this curves a mesh with 4th order G1 Patches diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 4ec595f03..53b893805 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -163,20 +163,11 @@ ma::Input* configureShapeCorrection( static int fixInvalidElements(crv::Adapt* a) { - - crv::fixLargeBoundaryAngles(a); - crv::fixInvalidEdgesCollapseAndSwap(a); - crv::fixInvalidFaces(a); - crv::fixInvalidEdges(a); - - return 0; - - a->input->shouldForceAdaptation = false; int count = crv::fixLargeBoundaryAngles(a) + crv::fixInvalidEdges(a); - //+ crv::fixInvalidFaces(a); - //+ crv::fixInvalidEdges(a); + + crv::fixInvalidFaces(a); + + crv::fixInvalidEdges(a); int originalCount = count; int prev_count; int i = 0; @@ -186,14 +177,14 @@ static int fixInvalidElements(crv::Adapt* a) prev_count = count; count = crv::fixLargeBoundaryAngles(a) + crv::fixInvalidEdges(a); - //+ crv::fixInvalidFaces(a); - //+ crv::fixInvalidEdges(a); + + crv::fixInvalidFaces(a); + + crv::fixInvalidEdges(a); ++i; } while(count < prev_count); crv::fixLargeBoundaryAngles(a); ma::clearFlagFromDimension(a,ma::COLLAPSE | ma::BAD_QUALITY,1); - //ma::clearFlagFromDimension(a, ma::SNAP, 2); + ma::clearFlagFromDimension(a, ma::SNAP, 2); a->input->shouldForceAdaptation = false; return originalCount - count; } @@ -223,8 +214,6 @@ void adapt(ma::Input* in) fixInvalidElements(a); - return; - for (int i=0; i < in->maximumIterations; ++i) { ma::print("iteration %d",i); @@ -236,7 +225,6 @@ void adapt(ma::Input* in) fixCrvElementShapes(a); } - //allowSplitCollapseOutsideLayer(a); if (in->maximumIterations > 0) { fixInvalidElements(a); diff --git a/crv/crvCurveMesh.cc b/crv/crvCurveMesh.cc index bcf212b0b..aa1a9ea0b 100644 --- a/crv/crvCurveMesh.cc +++ b/crv/crvCurveMesh.cc @@ -171,7 +171,7 @@ void BezierCurver::convertInterpolatingToBezier() synchronize(); } -bool BezierCurver::run(bool flag) +bool BezierCurver::run() { std::string name = m_mesh->getShape()->getName(); if(m_order < 1 || m_order > 6){ @@ -186,9 +186,6 @@ bool BezierCurver::run(bool flag) apf::changeMeshShape(m_mesh, getBezier(m_order),true); } - //writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 8, "mesh_after_shape_change"); - //writeCurvedWireFrame(m_mesh, 16, "mesh_after_shape_change"); - if (m_mesh->canSnap()){ for(int d = 1; d <= 2; ++d) snapToInterpolate(d); @@ -197,15 +194,10 @@ bool BezierCurver::run(bool flag) convertInterpolatingToBezier(); - writeCurvedVtuFiles(m_mesh, apf::Mesh::TET, 16, "mesh_after_inflate"); - writeCurvedWireFrame(m_mesh, 16, "mesh_after_inflate"); - - if (flag == 1) { - if(m_mesh->getDimension() >= 2) { - if (m_order == 2 || m_order == 3) { - ma::Input* shapeFixer = configureShapeCorrection(m_mesh); - crv::adapt(shapeFixer); - } + if(m_mesh->getDimension() >= 2) { + if (m_order == 2 || m_order == 3) { + ma::Input* shapeFixer = configureShapeCorrection(m_mesh); + crv::adapt(shapeFixer); } } diff --git a/crv/crvQuality.cc b/crv/crvQuality.cc index be6f57ee9..ce046eed3 100644 --- a/crv/crvQuality.cc +++ b/crv/crvQuality.cc @@ -480,7 +480,7 @@ int Quality3D::checkValidity(apf::MeshEntity* e) int validityTag = computeJacDetNodes(e,nodes,true); if (validityTag > 1) return validityTag; - else return 1; + else return 1; // TODO: Make sure this is actually needed here! // check verts apf::Downward verts; mesh->getDownward(e,0,verts); @@ -489,7 +489,6 @@ int Quality3D::checkValidity(apf::MeshEntity* e) return 2+i; } } - // std::cout<<"reached here"<getDownward(e,1,edges); @@ -628,8 +627,6 @@ std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorit int order = mesh->getShape()->getOrder(); int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); apf::NewArray subdivisionCoeffs[4]; - // apf::NewArray xi; - // xi.allocate(n); if (algorithm == 0 || algorithm == 2){ for (int d = 1; d <= 3; ++d) getBezierJacobianDetSubdivisionCoefficients( @@ -639,7 +636,7 @@ std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorit apf::NewArray nodes(n); std::vector ai = getAllInvaliditiesWNodes(mesh, e, nodes); - + std::vector ainvA; if (ai.size()==0) { @@ -665,13 +662,13 @@ std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorit apf::MeshEntity* edges[6]; mesh->getDownward(e,1,edges); // Vertices will already be flagged in the first check - + for (int edge = 0; edge < 6; ++edge){ for (int i = 0; i < 3*(order-1)-1; ++i){ if (nodes[4+edge*(3*(order-1)-1)+i] < minAcceptable){ minJ = -1e10; apf::NewArray edgeNodes(3*(order-1)+1); - + if(algorithm < 2){ edgeNodes[0] = nodes[apf::tet_edge_verts[edge][0]]; edgeNodes[3*(order-1)] = nodes[apf::tet_edge_verts[edge][1]]; @@ -691,7 +688,7 @@ std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorit edgeNodes[1] = nodes[apf::tet_edge_verts[edge][1]]; for (int j = 0; j < 3*(order-1)-1; ++j) edgeNodes[j+2] = nodes[4+edge*(3*(order-1)-1)+j]; - + bool done = false; bool quality = false; getJacDetBySubdivisionMatrices(apf::Mesh::EDGE,3*(order-1), @@ -760,82 +757,6 @@ std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorit return ainvA; } -std::vector getAllInvaliditiesWNodes(apf::Mesh* mesh,apf::MeshEntity* e, apf::NewArray& nodes) -{ - int order = mesh->getShape()->getOrder(); - int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); - - apf::NewArray xi; - xi.allocate(n); - - collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), - elem_vert_xi[apf::Mesh::TET], xi); - std::vector ai; - apf::NewArray interNodes(n); - apf::MeshElement* me = apf::createMeshElement(mesh,e); - - for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ - int index = 18*order*order-36*order+20+i; - interNodes[index] = apf::getDV(me,xi[index]); - if(interNodes[index] < 1e-10){ - ai.push_back(20); - } - } - - for (int face = 0; face < 4; ++face){ - for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ - int index = 18*order-20+face*(3*order-4)*(3*order-5)/2+i; - interNodes[index] = apf::getDV(me,xi[index]); - if(interNodes[index] < 1e-10){ - ai.push_back(face+14); - break; - } - } - } - - for (int edge = 0; edge < 6; ++edge){ - for (int i = 0; i < 3*(order-1)-1; ++i){ - int index = 4+edge*(3*(order-1)-1)+i; - interNodes[index] = apf::getDV(me,xi[index]); - if(interNodes[index] < 1e-10){ - ai.push_back(edge+8); - break; - } - } - } - - for (int i = 0; i < 4; ++i){ - interNodes[i] = apf::getDV(me,xi[i]); - if(interNodes[i] < 1e-10){ - ai.push_back(i+2); - } - } - apf::destroyMeshElement(me); - - //collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), - // elem_vert_xi[apf::Mesh::TET], xi); - //for (int i = 0; i < n; i++) { - // std::cout<<"Determinant value at "<< xi[i] <<" "<< interNodes[i]< transformationMatrix; - mth::Matrix A(n,n); - transformationMatrix.resize(n,n); - //collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), - // elem_vert_xi[apf::Mesh::TET], xi); - getBezierTransformationMatrix(apf::Mesh::TET, 3*(order-1), A, - elem_vert_xi[apf::Mesh::TET]); - invertMatrixWithPLU(n, A, transformationMatrix); - - for (int i = 0; i < n; i++) { - nodes[i] = 0; - for (int j = 0; j < n; j++) - nodes[i] += interNodes[j]*transformationMatrix(i,j); - } - - return ai; -} - std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) { int order = mesh->getShape()->getOrder(); @@ -844,12 +765,12 @@ std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) apf::NewArray xi; xi.allocate(n); - collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), + collectNodeXi(apf::Mesh::TET, apf::Mesh::TET, 3*(order-1), elem_vert_xi[apf::Mesh::TET], xi); std::vector ai; apf::NewArray interNodes(n); apf::MeshElement* me = apf::createMeshElement(mesh,e); - + for (int i = 0; i < 4; ++i){ interNodes[i] = apf::getDV(me,xi[i]); if(interNodes[i] < 1e-10){ diff --git a/crv/crvQuality.h b/crv/crvQuality.h index fcc54e07b..1b02b6c63 100644 --- a/crv/crvQuality.h +++ b/crv/crvQuality.h @@ -42,9 +42,13 @@ void elevateBezierJacobianDet(int type, int P, int r, double Nijk(apf::NewArray& nodes, int d, int I, int J); double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K); -std::vector getAllInvalidities(apf::Mesh* mesh, apf::MeshEntity* e); -std::vector getAllInvaliditiesWNodes(apf::Mesh* mesh, apf::MeshEntity* e, apf::NewArray& nodes); -std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorithm); +std::vector getAllInvalidities( + apf::Mesh* mesh, + apf::MeshEntity* e); +std::vector validityByAlgo( + apf::Mesh* mesh, + apf::MeshEntity* e, + int algorithm); } #endif diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 5594b856d..a59c3a970 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -60,7 +60,7 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent { apf::MeshEntity* edges[6]; int ne = mesh->getDownward(e, 1, edges); - + apf::MeshEntity* f[4]; int nf = mesh->getDownward(e, 2, f); apf::MeshEntity* vf[3]; @@ -69,7 +69,7 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent std::vector a; std::vector b; - + // get the vertex local number for face from the invalid vertex for (int i = 0; i < nf; i++) { mesh->getDownward(f[i], 0, vf); @@ -119,9 +119,9 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent std::vector aa; //std::vector bb; - // need to flag all adjacent edges + // need to flag all adjacent edges // hence only 2 faces would do - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { int nef = mesh->getDownward(f[a[cc[i]]], 1, ef); for (int j = 0; j < nef; j++) { mesh->getDownward(ef[j], 0, ve); @@ -143,36 +143,14 @@ static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Ent } } } -/* - if (bb[0] < bb[1] ) { - int k = aa[0]; - int kk = bb[0]; - aa[0] = aa[1]; - aa[1] = k; - bb[0] = bb[1]; - bb[1] = kk; - } - */ - // aa has the index of the edges ordered + + // aa has the index of the edges ordered // min to max of adj face jacobian return aa; } -/* -static void sortDes(std::vector &a) -{ - for (std::size_t i = 0; i < a.size(); i++) { - for (int j = i-1; j >= 0; j--) { - int ko = a[j+1]; - if (ko > a[j]) { - a[j+1] = a[j]; - a[j] = ko; - } - } - } -} -*/ + static void sortDesWrtFreqVector(std::vector &f, std::vector &a) { for (std::size_t i = 0; i < f.size(); i++) { @@ -215,145 +193,6 @@ static std::vector sortEdgeIndexByFrequency(std::vector &all) return unqEntries; } -/* -static std::vector sortEdgeIndexByType(ma::Mesh* mesh, ma::Entity* e, std::vector all) -{ - apf::MeshEntity* ed[6]; - mesh->getDownward(e, 1, ed); - //int n = all.size(); - - // sort all edges - // aim is to erase duplicate edges - for (size_t i = 0; i < all.size(); i++) { - for (int j = i-1; j >= 0; --j) { - int ko = all[j+1]; - if ( ko < all[j]) { - all[j+1] = all[j]; - all[j] = ko; - } - } - } - - std::vector b; - b.push_back(all[0]); - for (size_t i = 1; i < all.size(); i++) { - if (all[i] != all[i-1]) - b.push_back(all[i]); - } - - return b; - - std::vector bb; - //int nn = b.size(); - //get type of each edge - for (size_t j = 0; j < b.size(); j++) { - bb.push_back(mesh->getModelType(mesh->toModel(ed[b[j]]))); - } - - //sort type from 3-1 - for (size_t i = 0; i < bb.size(); i++) { - for (int j = i-1; j >= 0; --j) { - int k = bb[j+1]; - int kk = b[j+1]; - if ( k > bb[j]) { - bb[j+1] = bb[j]; - bb[j] = k; - b[j+1] = b[j]; - b[j] = kk; - } - } - } - - return b; -} -*/ -/* -static int getCommonEdgeIndexToFaces(int a, int b) -{ - int tb[4][4] = {{-1, 0, 1, 2}, - {0, -1, 4, 3}, - {1, 4, -1, 5}, - {2, 3, 5, -1}}; - return tb[a][b] + 2; -} -*/ -// doess not account for TET(20) invalidity - -/* -static std::vector numOfUniqueFaces(std::vector &ai) -{ - std::vector aiEdgeNVtx; - std::vector aiOnlyFace; - std::vector aiOnlyEdge; - std::vector aiOnlyVtx; - std::vector aiOnlyTet; - - for (size_t i = 0; i < ai.size(); i++) { - if (ai[i] < 8) aiOnlyVtx.push_back(ai[i]); - else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); - else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); - else aiOnlyTet.push_back(ai[i]); - } - - int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, - {0, -1, 4, 3}, - {1, 4, -1, 5}, - {2, 3, 5, -1}}; - - int edgeToFaceInd[6][2] = {{0, 1}, - {0, 2}, - {0, 3}, - {1, 3}, - {1, 2}, - {2, 3}}; - - int edgeToVtx[6][2] = {{0, 1}, - {1, 2}, - {0, 2}, - {0, 3}, - {1, 3}, - {2, 3}}; - - bool hasDownVtx, alreadyIn; - - for (size_t j = 0; j < aiOnlyEdge.size(); j++) { - hasDownVtx = false; - for (int jj = 0; jj < 2; jj++) { - //hasDownVtx = false; - for (size_t ii = 0; ii < aiOnlyVtx.size(); ii++) { - hasDownVtx = hasDownVtx || (edgeToVtx[aiOnlyEdge[j]-8][jj] == aiOnlyVtx[ii] - 2); - } - } - - if (hasDownVtx == false) { - for (int i = 0; i < 2; i++) { - aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); - } - } - } - - - for (size_t j = 0; j < aiOnlyEdge.size(); j++) { - for (int i = 0; i < 2; i++) { - aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); - } - } - - - for (size_t j = 0; j < aiOnlyTet.size(); j++) { - for (int jj = 0; jj < 4; jj++) { - aiOnlyFace.push_back(jj+14); - } - } - - std::vector allinvFaces; - - if (aiOnlyFace.size() > 0) - allinvFaces = sortEdgeIndexByFrequency(aiOnlyFace); - - return allinvFaces; -} -*/ static std::vector numOfUniqueFaces(std::vector &ai) { @@ -408,24 +247,6 @@ static std::vector numOfUniqueFaces(std::vector &ai) } } } -///////// -/* - for (size_t j = 0; j < aiOnlyFace.size(); j++) { - bool isUnique = false; - for (int i = 0; i < 4; i++) { - for (size_t k = 0; k < aiOnlyEdge.size(); k++) { - if (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiOnlyEdge[k]) - aiUniqueFace.push_back(i+14); - isUnique = isUnique || (faceToEdgeInd[aiOnlyFace[j]-14][i] + 8 == aiOnlyEdge[k]); - } - } - if (isUnique == false) { - aiUniqueFace.push_back(aiOnlyFace[j]); - aiOnlyFace.erase(aiOnlyFace.begin()+j); - } - } -////////// -*/ bool hasDownVtx, alreadyIn; @@ -467,7 +288,8 @@ static std::vector numOfUniqueFaces(std::vector &ai) ai.clear(); std::vector forFaceMarking; - //// + + // TODO: to be cleaned up //[number of unique faces, {unique face index}, {pairs of face face coomon edge invalids}] if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { @@ -484,7 +306,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) forFaceMarking.push_back(aiUniqueFace[i]); } for (std::size_t i = 0; i < FFE.size(); i++) - forFaceMarking.push_back(FFE[i]); + forFaceMarking.push_back(FFE[i]); } else if (aiUniqueFace.size() == 0) { @@ -503,27 +325,6 @@ static std::vector numOfUniqueFaces(std::vector &ai) return forFaceMarking; } -/* -static std::vector inspectInvalidies(std::vector ai) -{ - std::vector aimod; - std::vector a; - - for (size_t i = 0; i < ai.size(); i++) { - if (ai[i] > 13) - a.push_back(ai[i]); - else - aimod.push_back(ai[i]); - } - if (a.size() == 2) { - //aimod.push_back(getCommonEdgeIndexToFaces(a[0]-14,a[1]-14)); - return aimod; - } - else - return ai; -} -*/ - static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* edges[6]) { @@ -548,11 +349,11 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, case 0: { //ma::Downward ed; - //m->getDownward(e,1,ed); + //m->getDownward(e,1,ed); std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); PCU_ALWAYS_ASSERT(index < 4); - for (size_t i = 0; i < aa.size(); i++) + for (size_t i = 0; i < aa.size(); i++) bb.push_back(aa[i]); break; @@ -617,7 +418,6 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, int index = (tag-2) % 6; int n = 0; int md = m->getDimension(); - switch (dim) { case 0: { @@ -631,16 +431,12 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, edges[1] = ed[(index+2) % 3]; } else { PCU_ALWAYS_ASSERT(index < 4); - //edges[0] = ed[aa[0]]; - //edges[1] = ed[aa[1]]; - //edges[2] = ed[aa[2]]; - edges[0] = ed[vertEdges[index][0]]; - edges[1] = ed[vertEdges[index][1]]; - edges[2] = ed[vertEdges[index][2]]; + edges[0] = ed[tetVertEdges[index][0]]; + edges[1] = ed[tetVertEdges[index][1]]; + edges[2] = ed[tetVertEdges[index][2]]; } break; } - //break; case 1: { // if we have a single invalid edge, operate on it @@ -650,7 +446,6 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, n = 1; break; } - //break; case 2: { // if we have an invalid face, operate on its edges @@ -663,7 +458,6 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, edges[2] = ed[2]; break; } - //break; case 3: { m->getDownward(e,1,edges); @@ -678,63 +472,11 @@ static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, return n; } -/* -static std::vector faceIndexAdjInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) -{ - apf::MeshEntity* f[4]; - int nf = mesh->getDownward(e, 2, f); - apf::MeshEntity* vf[3]; - apf::MeshEntity* vt[4]; - mesh->getDownward(e, 0, vt); - - std::vector a; - - for (int i = 0; i < nf; i++) { - if (mesh->getModelType(mesh->toModel(f[i])) == 3) { - mesh->getDownward(f[i], 0, vf); - int j = apf::findIn(vf, 3, vt[index]); - - if (j != -1) - a.push_back(i); - } - } - return a; -} - -static std::vector faceIndexAdjInvalidEdge(ma::Mesh* mesh, ma::Entity* e, int index) -{ - apf::MeshEntity* f[4]; - int nf = mesh->getDownward(e, 2, f); - apf::MeshEntity* ef[3]; - apf::MeshEntity* et[6]; - mesh->getDownward(e, 1, et); - - std::vector a; - - for (int i = 0; i < nf; i++) { - if (mesh->getModelType(mesh->toModel(f[i])) == 3) { - mesh->getDownward(f[i], 1, ef); - int j = apf::findIn(ef, 3, et[index]); - - if (j != -1) - a.push_back(i); - } - } - return a; -} -*/ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Entity* faces[4]) { if (ai.size() == 0) return 0; -/* - for (int i = 0; i < ai.size(); i++) { - if (ai[i] == 20) - int j = 0; - } - */ - std::vector faceInvalid = numOfUniqueFaces(ai); int n = 0; @@ -742,18 +484,6 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, m->getDownward(e, 2, fc); ma::Downward ed; m->getDownward(e, 1, ed); -/* - for (std::size_t i = 0; i < faceInvalid.size();i++) { - int index = (faceInvalid[i] - 2) % 6; - int md = m->getDimension(); - - if (m->getModelType(m->toModel(fc[index])) == 3) { - faces[n] = fc[index]; - n++; - } - } -*/ - if (faceInvalid[0] > 0) { for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { int index = (faceInvalid[i] -2) % 6; @@ -765,123 +495,8 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, } } } - -/* - if (faceInvalid.size() > 1+faceInvalid[0]) { - int kkk = faceInvalid.size()-faceInvalid[0]-1; - int kk = kkk/3; - for (int k = 1; k <= kk; k++) { - int EdgeInd = (faceInvalid[faceInvalid[0] + 3*(k-1) + 1] - 2) % 6; - int FaceInd1 = (faceInvalid[faceInvalid[0] + 3*(k-1) + 2] - 2) % 6; - int FaceInd2 = (faceInvalid[faceInvalid[0] + 3*(k-1) + 3] - 2) % 6; - int edgeType = m->getModelType(m->toModel(ed[EdgeInd])); - - if (edgeType == 1 || edgeType == 2) { - int jf1 = m->getModelType(m->toModel(fc[FaceInd1])); - int jf2 = m->getModelType(m->toModel(fc[FaceInd2])); - - if (jf1 == 2 && jf2 != 2) { - faces[n] = fc[FaceInd2]; - n++; - } - else if (jf2 == 2 && jf1 != 2) { - faces[n] = fc[FaceInd1]; - n++; - } - else if (jf1 == 3 && jf2 == 3) { - faces[n] = fc[FaceInd1]; - n++; - faces[n] = fc[FaceInd2]; - n++; - } - } - else { - faces[n] = fc[FaceInd1]; - n++; - faces[n] = fc[FaceInd2]; - n++; - } - } - } -*/ - return n; - -} -/* -static int markFaces(ma::Mesh* m, ma::Entity* e, int tag, - ma::Entity* faces[4]) -{ - if ( tag <= 1 ) // if its valid, or not checked, don't worry about it - return 0; - int dim = (tag-2)/6; - int index = (tag-2) % 6; - int n = 0; - int md = m->getDimension(); - - switch (dim) { - case 0: - { - // if we have an invalid vertex, operate on adj faces - ma::Downward fc; - m->getDownward(e, 2, fc); - - std::vector a = faceIndexAdjInvalidVertex(m, e, index); - n = a.size(); - - if(md == 3){ - PCU_ALWAYS_ASSERT(index < 4); - for (int i = 0; i < n; i++) - faces[i] = fc[a[i]]; - } - break; - } - //break; - case 1: - { - ma::Downward fc; - m->getDownward(e,2,fc); - - std::vector a = faceIndexAdjInvalidEdge(m, e, index); - n = a.size(); - for (int i = 0; i < n; i++) - faces[i] = fc[a[i]]; - - break; - } - //break; - case 2: - { - // if we have an invalid face, operate on it - ma::Downward fc; - m->getDownward(e,2,fc); - if (m->getModelType(m->toModel(fc[index])) == 3) { - faces[n] = fc[index]; - n++; - } - break; - } - //break; - case 3: - { - ma::Downward fc; - m->getDownward(e,2,fc); - for (int i = 0; i < 4; i++) { - if (m->getModelType(m->toModel(fc[i])) == 3) { - faces[i] = fc[i]; - n++; - } - } - break; - } - //break; - default: - fail("invalid quality tag in markFaces\n"); - break; - } - return n; } -*/ class EdgeSwapper : public ma::Operator { diff --git a/crv/crvTables.h b/crv/crvTables.h index 03c80f06f..7267d05c5 100644 --- a/crv/crvTables.h +++ b/crv/crvTables.h @@ -48,7 +48,12 @@ static bool const flip_tet_tri_edges[4][3] = /** \brief edge indices connected to a vertex of a tet, this does not comment on their orientation wrt to the vertex \details ordered as XJ Luo's thesis */ -static int const vertEdges[4][3] = {{3,0,2},{0,4,1},{1,5,2},{3,5,4}}; +static int const tetVertEdges[4][3] = {{3,0,2},{0,4,1},{1,5,2},{3,5,4}}; + +/** \brief edge indices connected to a vertex of a tri, this does not + comment on their orientation wrt to the vertex + \details [refer to the comment for tets] */ +static int const triVertEdges[3][2] = {{2,0},{0,1},{1,2}}; /** \brief indices of opposite edges of an edge to a tet */ static int const oppEdges[6] = {5,3,4,1,2,0}; diff --git a/crv/crvVtk.cc b/crv/crvVtk.cc index c2ca9b8fb..0964b2e6f 100644 --- a/crv/crvVtk.cc +++ b/crv/crvVtk.cc @@ -311,46 +311,6 @@ static void writeEdgeJacobianDet(std::ostream& file, apf::Mesh* m, int n) file << "\n"; } -static double getVolume(apf::Mesh* mesh, apf::MeshEntity* e) -{ - apf::MeshEntity* adjV[4]; - mesh->getDownward(e, 0, adjV); - apf::Matrix3x3 m; - apf::Vector3 point0, point; - - for (std::size_t j = 0; j < 4; j++) { - if ( j == 0) - mesh->getPoint(adjV[j], 0, point0); - else { - mesh->getPoint(adjV[j], 0, point); - for (int k = 0; k < 3; k++) - m[j-1][k] = point[k] - point0[k]; - } - } - double v = apf::getDeterminant(m)/6.0; - - return v; - -} - -static double getArea(apf::Mesh* mesh, apf::MeshEntity* e) -{ - apf::MeshEntity* ver[3]; - mesh->getDownward(e, 0, ver); - apf::Vector3 point0, point1, point2; - - mesh->getPoint(ver[0], 0, point0); - mesh->getPoint(ver[1], 0, point1); - mesh->getPoint(ver[2], 0, point2); - - point1 = point1 - point0; - point2 = point2 - point0; - - double area = (apf::cross(point1, point2)).getLength(); - - return (area/2.0); - -} static void writeTriJacobianDet(std::ostream& file, apf::Mesh* m, int n) { @@ -393,12 +353,10 @@ static void writeTriJacobianDet(std::ostream& file, apf::Mesh* m, int n) ++count; } } - double area = getArea(m, e); - if(std::fabs(maxJ) < 1e-10) maxJ = 1e-10; for (int i = 0; i < (n+1)*(n+2)/2; ++i){ - //if(detJ[i] > 0) detJ[i] /= maxJ; - file << detJ[i]/area << '\n'; + if(detJ[i] > 0) detJ[i] /= maxJ; + file << detJ[i] << '\n'; } apf::destroyMeshElement(me); } @@ -479,11 +437,10 @@ static void writeTetJacobianDet(std::ostream& file, apf::Mesh* m, int n) } } } - double vol = getVolume(m, e); if(maxJ < 1e-10) maxJ = 1e-10; for (int i = 0; i < 4*(n+1)*(n+1)*(n+1); ++i){ - //if(detJ[i] > 0) detJ[i] /= maxJ; - file << detJ[i]/vol << '\n'; + if(detJ[i] > 0) detJ[i] /= maxJ; + file << detJ[i] << '\n'; } apf::destroyMeshElement(me); From 206b826c203842ccaeb46dbf9170acda94210b1a Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Mon, 2 Mar 2020 17:21:16 -0500 Subject: [PATCH 45/48] Fixes problems with warning--error compile mode --- crv/crvAdapt.cc | 10 +- crv/crvDBG.cc | 8 +- crv/crvObjectiveFunctions.cc | 5 +- crv/crvObjectiveFunctions.h | 4 + crv/crvOptimizations.cc | 119 +-- crv/crvOptimizations.h | 12 +- crv/crvQuality.cc | 141 --- crv/crvQuality.h | 5 +- crv/crvShape.cc | 206 ++--- crv/crvShape.cc.orig | 1575 ++++++++++++++++++++++++++++++++++ crv/crvShape.h | 1 - 11 files changed, 1696 insertions(+), 390 deletions(-) create mode 100644 crv/crvShape.cc.orig diff --git a/crv/crvAdapt.cc b/crv/crvAdapt.cc index 53b893805..c3128169f 100644 --- a/crv/crvAdapt.cc +++ b/crv/crvAdapt.cc @@ -164,9 +164,8 @@ ma::Input* configureShapeCorrection( static int fixInvalidElements(crv::Adapt* a) { a->input->shouldForceAdaptation = false; - int count = crv::fixLargeBoundaryAngles(a) - + crv::fixInvalidEdges(a); - + crv::fixInvalidFaces(a); + int count = crv::fixLargeBoundaryAngles(a) + + crv::fixInvalidFaces(a) + crv::fixInvalidEdges(a); int originalCount = count; int prev_count; @@ -175,9 +174,8 @@ static int fixInvalidElements(crv::Adapt* a) if ( ! count) break; prev_count = count; - count = crv::fixLargeBoundaryAngles(a) - + crv::fixInvalidEdges(a); - + crv::fixInvalidFaces(a); + count = crv::fixLargeBoundaryAngles(a) + + crv::fixInvalidFaces(a) + crv::fixInvalidEdges(a); ++i; } while(count < prev_count); diff --git a/crv/crvDBG.cc b/crv/crvDBG.cc index 040824dc3..5a6ed8a10 100644 --- a/crv/crvDBG.cc +++ b/crv/crvDBG.cc @@ -49,7 +49,7 @@ void visualizeCavityMesh(apf::Mesh2* m, apf::MeshEntity* ent, apf::MeshEntity* newEnt[99]; - for (int ii = 0; ii < e.getSize(); ii++) { + for (std::size_t ii = 0; ii < e.getSize(); ii++) { // Verts apf::MeshEntity* vs[12]; apf::MeshEntity* newVs[12]; @@ -94,7 +94,7 @@ void visualizeCavityMesh(apf::Mesh2* m, apf::MeshEntity* ent, } // Regions - apf::MeshEntity* tet; + apf::MeshEntity* tet = 0; if (dim == 3) { tet = outMesh->createEntity(apf::Mesh::TET, 0, newFs); } @@ -107,7 +107,7 @@ void visualizeCavityMesh(apf::Mesh2* m, apf::MeshEntity* ent, apf::changeMeshShape(outMesh, crv::getBezier(3), true); outMesh->acceptChanges(); - for (int ii = 0; ii < e.getSize(); ii++) { + for (std::size_t ii = 1; ii < e.getSize(); ii++) { for (int d = 1; d <= dim; d++) { if (!m->getShape()->hasNodesIn(d)) continue; @@ -204,7 +204,7 @@ void visualizeIndividualCavityEntities(apf::Mesh2* m, apf::MeshEntity* ent, } // Regions - apf::MeshEntity* tet; + apf::MeshEntity* tet = 0; if (dim == 3) { tet = outMesh[ii]->createEntity(apf::Mesh::TET, 0, newFs); } diff --git a/crv/crvObjectiveFunctions.cc b/crv/crvObjectiveFunctions.cc index 9de9488b6..61ea410be 100644 --- a/crv/crvObjectiveFunctions.cc +++ b/crv/crvObjectiveFunctions.cc @@ -354,14 +354,14 @@ double BoundaryEdgeReshapeObjFunc :: getValue(const vector &x) xis.push_back(apf::Vector3(+1.0, 0.0, 0.0)); apf::MeshElement* me = apf::createMeshElement(mesh, edge); - for (int i = 0; i < xis.size(); i++) { + for (std::size_t i = 0; i < xis.size(); i++) { apf::Vector3 scord; apf::mapLocalToGlobal(me, xis[i], scord); xs.push_back(scord); } apf::destroyMeshElement(me); - for (int i = 1; i < xs.size()-1; i++) { + for (std::size_t i = 1; i < xs.size()-1; i++) { xr = (xs[i] - xs[0]).getLength() / (xs[xs.size()-1] - xs[0]).getLength(); @@ -477,7 +477,6 @@ void BoundaryEdgeReshapeObjFunc :: setNodes(const vector &x) apf::Adjacent adjF; mesh->getAdjacent(edge, 2, adjF); - int kk = 0; int nFN = mesh->getShape()->countNodesOn(mesh->TRIANGLE); for (std::size_t i = 0; i < adjF.getSize(); i++) { diff --git a/crv/crvObjectiveFunctions.h b/crv/crvObjectiveFunctions.h index eec215678..86a551d11 100644 --- a/crv/crvObjectiveFunctions.h +++ b/crv/crvObjectiveFunctions.h @@ -48,9 +48,13 @@ class ObjFunction { public: ObjFunction(){}; + virtual ~ObjFunction(){}; virtual int getSpaceDim() = 0; virtual double getTol() = 0; virtual double getValue(const vector &x) = 0; + /* virtual std::vector getInitialGuess() = 0; */ + /* virtual void setNodes(const vector &x) = 0; */ + /* virtual void restoreInitialNodes() = 0; */ // TODO :: can we do this once for all the objective functions? vector getGrad(const vector &_x) { diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index cefc7df42..85f895945 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -18,10 +18,9 @@ -static void printInvalidities(apf::Mesh2* m, apf::MeshEntity* e[99], apf::MeshEntity* edge, int nat) +static void printInvalidities(apf::Mesh2* m, apf::Adjacent e, apf::MeshEntity* edge) { - - return; + int nat = e.getSize(); apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); int num = apf::getNumber(n, edge, 0, 0); @@ -222,33 +221,25 @@ static double computeFValDetJ(apf::Mesh2* m, apf::MeshEntity* e, ma::SizeField* double jDet1, jDet2; double volm = getLinearVolPhys(m, e); - /* for (int i = 0; i < apf::countIntPoints(me, order) ; i++) { apf::Vector3 qp; double w = apf::getIntWeight(me, order, i); apf::getIntPoint(me, order, i, qp); apf::getJacobian(me, qp, J); -*/ - /* s->getTransform(me, qp, T); Jm = J*T; // Jacobian in metric space jDet = apf::getDeterminant(Jm); - */ - /* jDet = apf::getDeterminant(J) * computeDetW(me, qp); - sum += (jDet/6.0 - 1.) * (jDet/6.0 - 1.); - */ - /* + sum += w * (jDet/6.0 - 1.) * (jDet/6.0 - 1.); apf::Vector3 xyz; apf::mapLocalToGlobal(me, qp, xyz); std::cout<<"Xi: "<< qp <<" XYZ: "< sizeHolder; - apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(edge, 3, adj); int thisTetSize = 0; + InternalEdgeReshapeObjFunc* objF = 0; + LBFGS* l; - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; + for (std::size_t i = 0; i < adj.getSize(); i++) { std::vector ai = crv::getAllInvalidities(mesh, adj[i]); if (adj[i] == tet) thisTetSize = ai.size(); sizeHolder.push_back(ai.size()); } - //crv_dbg::visualizeCavityMesh(mesh, edge, "before_cavity_Iedge_NIJK", - // mesh->findNumbering("debug_num_tet"), 15); - - //std::vector ai = crv::getAllInvalidities(mesh, tet); - //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - /* printTetNumber(mesh, tet); */ - /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ switch (mode) { case NIJK: objF = new InternalEdgeReshapeObjFunc(adapt, edge, tet, computeFValNIJKL); @@ -357,21 +341,14 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) objF->setNodes(finalX); - for (int i = 0; i < adj.getSize(); i++) { + for (std::size_t i = 0; i < adj.getSize(); i++) { std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + hasDecreased = hasDecreased || (aiNew.size() > (std::size_t)sizeHolder[i]); } if (hasDecreased == false ) { - //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_Iedge_NIJK", - // mesh->findNumbering("debug_num_tet"), 15); - //invaliditySize = 0; - //makeMultipleEntityMesh(mesh, adj_array, edge, "after_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ - /* std::cout<<"--------------------------------------"< sizeHolder; - apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(edge, 3, adj); - int cInvT = 0; int thisTetSize = 0; + BoundaryEdgeReshapeObjFunc* objF = 0; + LBFGS* l; - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; + for (std::size_t i = 0; i < adj.getSize(); i++) { std::vector ai = crv::getAllInvalidities(mesh, adj[i]); if (adj[i] == tet) thisTetSize = ai.size(); sizeHolder.push_back(ai.size()); } - //crv_dbg::visualizeCavityMesh(mesh, edge, "before_cavity_onlyV_Bedge_NIJK", - // mesh->findNumbering("debug_num_tet"), 15); - //std::vector ai = crv::getAllInvalidities(mesh,tet); - //makeMultipleEntityMesh(mesh, adj_array, edge, "before_cavity_of_edge_", adj.getSize()); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "before_cavity_indv_tet_of_edge_", adj.getSize()); - /* printTetNumber(mesh, tet); */ - /* printInvalidities(mesh, adj_array, edge, adj.getSize()); */ switch (mode) { case NIJK: objF = new BoundaryEdgeReshapeObjFunc(adapt, edge, tet, computeFValNIJKL); @@ -470,29 +443,24 @@ bool CrvBoundaryEdgeOptim :: run(int &invaliditySize) fval = l->fValAfter; objF->setNodes(finalX); - for (int i = 0; i < adj.getSize(); i++) { + for (std::size_t i = 0; i < adj.getSize(); i++) { std::vector aiNew = crv::getAllInvalidities(mesh, adj[i]); invaliditySize = invaliditySize + aiNew.size(); - hasDecreased = hasDecreased || (aiNew.size() > sizeHolder[i]); + hasDecreased = hasDecreased || (aiNew.size() > (std::size_t) sizeHolder[i]); } - //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_onlyV_Bedge_NIJK", - // mesh->findNumbering("debug_num_tet"), 15); if (hasDecreased == false) { - //crv_dbg::visualizeCavityMesh(mesh, edge, "after_cavity_Bedge_NIJK", - // mesh->findNumbering("debug_num_tet"), 15); - //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, edge, "after_cavity_indv_tet_of_edge_", adj.getSize()); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj, edge); std::cout<<"--------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, edge, adj.getSize()); + printInvalidities(mesh, adj, edge); std::cout<<"size did not decrease"< sizeHolder; - apf::MeshEntity* adj_array[99]; apf::Adjacent adj; mesh->getAdjacent(face, 3, adj); int thisTetSize = 0; - for (int i = 0; i < adj.getSize(); i++) { - adj_array[i] = adj[i]; + FaceReshapeObjFunc* objF = 0; + LBFGS* l; + for (std::size_t i = 0; i < adj.getSize(); i++) { //std::vector ai = crv::getAllInvalidities(mesh, adj[i]); //if (adj[i] == tet) thisTetSize = ai.size(); //sizeHolder.push_back(ai.size()); @@ -539,7 +511,7 @@ bool CrvFaceOptim :: run(int &invaliditySize) //makeMultipleEntityMesh(mesh, adj_array, face, "before_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "before_cavity_indv_tet_of_face_", adj.getSize()); /* printTetNumber(mesh, tet); */ - printInvalidities(mesh, adj_array, face, adj.getSize()); + printInvalidities(mesh, adj, face); switch (mode) { case NIJK: objF = new FaceReshapeObjFunc(adapt, face, tet, computeFValNIJKL); @@ -589,32 +561,35 @@ bool CrvFaceOptim :: run(int &invaliditySize) } */ // if (hasDecreased == false ) { - if (aiNew.size() <= invaliditySize) { + if (aiNew.size() <= (std::size_t) invaliditySize) { invaliditySize = aiNew.size(); //makeMultipleEntityMesh(mesh, adj_array, face, "after_cavity_of_face_", adj.getSize()); //makeIndividualTetsFromFacesOrEdges(mesh, adj_array, face, "after_cavity_indv_tet_of_face_", adj.getSize()); - printInvalidities(mesh, adj_array, face, adj.getSize()); + printInvalidities(mesh, adj, face); std::cout<<"----------------------------------------------------"<restoreInitialNodes(); - printInvalidities(mesh, adj_array, face, adj.getSize()); + printInvalidities(mesh, adj, face); std::cout<<"Size didNOT decrease"< finalX; @@ -75,8 +71,6 @@ class CrvBoundaryEdgeOptim : public CrvEntityOptim } ~CrvBoundaryEdgeOptim() { - delete objF; - delete l; } public: @@ -89,7 +83,6 @@ class CrvBoundaryEdgeOptim : public CrvEntityOptim apf::MeshEntity* tet; int mode; apf::Mesh2* mesh; - BoundaryEdgeReshapeObjFunc* objF; int iter; double tol; std::vector finalX; @@ -110,8 +103,6 @@ class CrvFaceOptim : public CrvEntityOptim } ~CrvFaceOptim() { - delete objF; - delete l; } public: @@ -124,7 +115,6 @@ class CrvFaceOptim : public CrvEntityOptim apf::MeshEntity* tet; int mode; apf::Mesh2* mesh; - FaceReshapeObjFunc* objF; int iter; double tol; std::vector finalX; diff --git a/crv/crvQuality.cc b/crv/crvQuality.cc index ce046eed3..2eefda236 100644 --- a/crv/crvQuality.cc +++ b/crv/crvQuality.cc @@ -43,7 +43,6 @@ class Quality2D : public Quality virtual ~Quality2D() {}; double getQuality(apf::MeshEntity* e); int checkValidity(apf::MeshEntity* e); - std::vector getAllInvalidities(apf::MeshEntity* e); int blendingOrder; int n; apf::NewArray blendingCoeffs; @@ -73,7 +72,6 @@ class Quality3D : public Quality virtual ~Quality3D() {}; double getQuality(apf::MeshEntity* e); int checkValidity(apf::MeshEntity* e); - std::vector getAllInvalidities(apf::MeshEntity* e); // 3D uses an alternate method of computing these // returns a validity tag so both quality and validity can // quit early if this function thinks they should @@ -377,9 +375,6 @@ static void getJacDetBySubdivisionMatrices(int type, int P, } } -std::vector Quality2D::getAllInvalidities(apf::MeshEntity* e) -{} - int Quality2D::checkValidity(apf::MeshEntity* e) { @@ -621,142 +616,6 @@ double computeTetJacobianDetFromBezierFormulation(apf::Mesh* m, return detJ; } -std::vector validityByAlgo(apf::Mesh* mesh, apf::MeshEntity* e, int algorithm) -{ - - int order = mesh->getShape()->getOrder(); - int n = getNumControlPoints(apf::Mesh::TET, 3*(order-1)); - apf::NewArray subdivisionCoeffs[4]; - if (algorithm == 0 || algorithm == 2){ - for (int d = 1; d <= 3; ++d) - getBezierJacobianDetSubdivisionCoefficients( - 3*(order-1),apf::Mesh::simplexTypes[d],subdivisionCoeffs[d]); - } - - apf::NewArray nodes(n); - - std::vector ai = getAllInvaliditiesWNodes(mesh, e, nodes); - - std::vector ainvA; - - if (ai.size()==0) { - ainvA.push_back(-1); - return ainvA; - } - - int flag = 3; - if (ai[0] == 20) flag = 0; - else if (ai[0] > 13 && ai[0] < 18) flag = 1; - else if (ai[0] > 7 && ai[0] < 14) flag = 2; - - apf::Downward verts; - mesh->getDownward(e,0,verts); - for (int i = 0; i < 4; ++i){ - if(nodes[i] < minAcceptable){ - ainvA.push_back(2+i); - } - } - - double minJ = 0, maxJ = 0; - if (flag == 0 || flag == 1 || flag == 2) { - apf::MeshEntity* edges[6]; - mesh->getDownward(e,1,edges); - // Vertices will already be flagged in the first check - - for (int edge = 0; edge < 6; ++edge){ - for (int i = 0; i < 3*(order-1)-1; ++i){ - if (nodes[4+edge*(3*(order-1)-1)+i] < minAcceptable){ - minJ = -1e10; - apf::NewArray edgeNodes(3*(order-1)+1); - - if(algorithm < 2){ - edgeNodes[0] = nodes[apf::tet_edge_verts[edge][0]]; - edgeNodes[3*(order-1)] = nodes[apf::tet_edge_verts[edge][1]]; - for (int j = 0; j < 3*(order-1)-1; ++j) - edgeNodes[j+1] = nodes[4+edge*(3*(order-1)-1)+j]; - // allows recursion stop on first "conclusive" invalidity - if(algorithm == 1) - getJacDetByElevation(apf::Mesh::EDGE,3*(order-1), - edgeNodes,minJ,maxJ); - else { - bool done = false; - getJacDetBySubdivision(apf::Mesh::EDGE,3*(order-1), - 0,edgeNodes,minJ,maxJ,done); - } - } else { - edgeNodes[0] = nodes[apf::tet_edge_verts[edge][0]]; - edgeNodes[1] = nodes[apf::tet_edge_verts[edge][1]]; - for (int j = 0; j < 3*(order-1)-1; ++j) - edgeNodes[j+2] = nodes[4+edge*(3*(order-1)-1)+j]; - - bool done = false; - bool quality = false; - getJacDetBySubdivisionMatrices(apf::Mesh::EDGE,3*(order-1), - 0,subdivisionCoeffs[1],edgeNodes,minJ,maxJ,done,quality); - } - if(minJ < minAcceptable){ - ainvA.push_back(8+edge); - break; - } - } - } - } - } - - if (flag == 0 || flag == 1) { - apf::MeshEntity* faces[4]; - mesh->getDownward(e,2,faces); - for (int face = 0; face < 4; ++face){ - double minJ = -1e10; - for (int i = 0; i < (3*order-4)*(3*order-5)/2; ++i){ - if (nodes[18*order-20+face*(3*order-4)*(3*order-5)/2+i] < minAcceptable){ - minJ = -1e10; - apf::NewArray triNodes((3*order-2)*(3*order-1)/2); - getTriDetJacNodesFromTetDetJacNodes(face,3*(order-1),nodes,triNodes); - if(algorithm == 2){ - bool done = false; - bool quality = false; - getJacDetBySubdivisionMatrices(apf::Mesh::TRIANGLE,3*(order-1), - 0,subdivisionCoeffs[2],triNodes,minJ,maxJ,done,quality); - } else if(algorithm == 1) - getJacDetByElevation(apf::Mesh::TRIANGLE,3*(order-1), - triNodes,minJ,maxJ); - else { - bool done = false; - getJacDetBySubdivision(apf::Mesh::TRIANGLE,3*(order-1), - 0,triNodes,minJ,maxJ,done); - } - if(minJ < minAcceptable){ - ainvA.push_back(14+face); - break; - } - } - } - } - } - - if (flag == 0) { - for (int i = 0; i < (3*order-4)*(3*order-5)*(3*order-6)/6; ++i){ - if (nodes[18*order*order-36*order+20+i] < minAcceptable){ - minJ = -1e10; - if(algorithm == 1){ - getJacDetByElevation(apf::Mesh::TET,3*(order-1),nodes,minJ,maxJ); - } else { - bool done = false; - bool quality = false; - getJacDetBySubdivisionMatrices(apf::Mesh::TET,3*(order-1), - 0,subdivisionCoeffs[3],nodes,minJ,maxJ,done,quality); - } - if(minJ < minAcceptable){ - ainvA.push_back(20); - break; - } - } - } - } - return ainvA; -} - std::vector getAllInvalidities(apf::Mesh* mesh,apf::MeshEntity* e) { int order = mesh->getShape()->getOrder(); diff --git a/crv/crvQuality.h b/crv/crvQuality.h index 1b02b6c63..7e6f78731 100644 --- a/crv/crvQuality.h +++ b/crv/crvQuality.h @@ -45,10 +45,7 @@ double Nijkl(apf::NewArray& nodes, int d, int I, int J, int K); std::vector getAllInvalidities( apf::Mesh* mesh, apf::MeshEntity* e); -std::vector validityByAlgo( - apf::Mesh* mesh, - apf::MeshEntity* e, - int algorithm); + } #endif diff --git a/crv/crvShape.cc b/crv/crvShape.cc index 0090fb366..4f6d2a9f4 100644 --- a/crv/crvShape.cc +++ b/crv/crvShape.cc @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -59,7 +58,7 @@ static bool hasTwoEntitiesOnBoundary(apf::Mesh* m, apf::MeshEntity* e, int dimen static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) { apf::MeshEntity* edges[6]; - int ne = mesh->getDownward(e, 1, edges); + mesh->getDownward(e, 1, edges); apf::MeshEntity* f[4]; int nf = mesh->getDownward(e, 2, f); @@ -292,7 +291,7 @@ static std::vector numOfUniqueFaces(std::vector &ai) // TODO: to be cleaned up //[number of unique faces, {unique face index}, {pairs of face face coomon edge invalids}] - if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { + if (aiUniqueFace.size() > 0) { forFaceMarking.push_back(aiUniqueFace.size()); for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) ai.push_back(aiOnlyVtx[i]); @@ -338,7 +337,7 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, std::vector faceInvalid = numOfUniqueFaces(ai); if (ai.size() == 0) return 0; - if (ai.size() == faceInvalid[0]) return 0; + if (ai.size() == (std::size_t) faceInvalid[0]) return 0; for (size_t ii = 0; ii < ai.size(); ii++) { @@ -375,8 +374,10 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, m->getDownward(e,2,faces); m->getDownward(faces[index],1,edf); + // TODO : This loop seems to be doing nothing for (int i = 0; i < 3; i++) { int j = apf::findIn(ed, 6, edf[i]); + j++; //if (j != -1) //bb.push_back(j); } @@ -397,7 +398,6 @@ static int markAllEdges(ma::Mesh* m, ma::Entity* e, int n = 0; //std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); std::vector allinvEdges = sortEdgeIndexByFrequency(bb); - int k = 0; for (size_t i = 0; i < allinvEdges.size(); i++) { if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { @@ -485,9 +485,8 @@ static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, ma::Downward ed; m->getDownward(e, 1, ed); if (faceInvalid[0] > 0) { - for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { + for (int i = 1; i < faceInvalid[0]+1; i++) { int index = (faceInvalid[i] -2) % 6; - int md = m->getDimension(); if (m->getModelType(m->toModel(fc[index])) == 3) { faces[n] = fc[index]; @@ -996,7 +995,6 @@ class EdgeOptimizer : public ma::Operator if (ne == 0) return; for (int i = 0; i < ne; i++ ) { int invaliditySize = 0; - bool hasDecreased = false; CrvEntityOptim* ceo; if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { @@ -1224,47 +1222,47 @@ static int markEdgesOppLargeAnglesTet(Adapt* a) * fixing */ -static int markEdgesToFix(Adapt* a, int flag) -{ - // do a invalidity check first - int invalid = markInvalidEntities(a); - if ( !invalid ) - return 0; - int count = 0; +/* static int markEdgesToFix(Adapt* a, int flag) */ +/* { */ +/* // do a invalidity check first */ +/* int invalid = markInvalidEntities(a); */ +/* if ( !invalid ) */ +/* return 0; */ +/* int count = 0; */ - ma::Mesh* m = a->mesh; - ma::Entity* e; +/* ma::Mesh* m = a->mesh; */ +/* ma::Entity* e; */ - // markEdges could have upto 6 edges marked!!! - ma::Entity* edges[6]; - ma::Iterator* it = m->begin(m->getDimension()); +/* // markEdges could have upto 6 edges marked!!! */ +/* ma::Entity* edges[6]; */ +/* ma::Iterator* it = m->begin(m->getDimension()); */ - while ((e = m->iterate(it))) - { - //int tag = crv::getTag(a,e); - //int n = markEdges(m,e,tag,edges); +/* while ((e = m->iterate(it))) */ +/* { */ +/* //int tag = crv::getTag(a,e); */ +/* //int n = markEdges(m,e,tag,edges); */ - std::vector ai = crv::getAllInvalidities(m, e); - int niv = ai.size(); - - if (niv != 0) { - int n = markAllEdges(m, e, ai, edges); - for (int i = 0; i < n; ++i){ - ma::Entity* edge = edges[i]; - PCU_ALWAYS_ASSERT(edge); - - if (edge && !ma::getFlag(a,edge,flag)) { - ma::setFlag(a,edge,flag); - if (a->mesh->isOwned(edge)) - ++count; - } - } - } - } - m->end(it); - - return PCU_Add_Long(count); -} +/* std::vector ai = crv::getAllInvalidities(m, e); */ +/* int niv = ai.size(); */ + +/* if (niv != 0) { */ +/* int n = markAllEdges(m, e, ai, edges); */ +/* for (int i = 0; i < n; ++i){ */ +/* ma::Entity* edge = edges[i]; */ +/* PCU_ALWAYS_ASSERT(edge); */ + +/* if (edge && !ma::getFlag(a,edge,flag)) { */ +/* ma::setFlag(a,edge,flag); */ +/* if (a->mesh->isOwned(edge)) */ +/* ++count; */ +/* } */ +/* } */ +/* } */ +/* } */ +/* m->end(it); */ + +/* return PCU_Add_Long(count); */ +/* } */ /* static int markFacesToFix(Adapt* a, int flag) @@ -1317,7 +1315,7 @@ int fixLargeBoundaryAngles(Adapt* a) return 0; } -static void collapseInvalidEdges(Adapt* a) +static int collapseInvalidEdges(Adapt* a) { double t0 = PCU_Time(); ma::Mesh* m = a->mesh; @@ -1334,9 +1332,10 @@ static void collapseInvalidEdges(Adapt* a) double t1 = PCU_Time(); ma::print("Collapsed %d bad edges " "in %f seconds",successCount, t1-t0); + return successCount; } -static void swapInvalidEdges(Adapt* a) +static int swapInvalidEdges(Adapt* a) { double t0 = PCU_Time(); EdgeSwapper es(a); @@ -1344,9 +1343,10 @@ static void swapInvalidEdges(Adapt* a) double t1 = PCU_Time(); ma::print("Swapped %d bad edges " "in %f seconds",es.ns, t1-t0); + return es.ns; } -static void repositionInvalidEdges(Adapt* a) +static int repositionInvalidEdges(Adapt* a) { double t0 = PCU_Time(); EdgeReshaper es(a); @@ -1354,9 +1354,10 @@ static void repositionInvalidEdges(Adapt* a) double t1 = PCU_Time(); ma::print("Repositioned %d bad edges " "in %f seconds",es.nr, t1-t0); + return es.nr; } -static void optimizeInvalidEdges(Adapt* a) +static int optimizeInvalidEdges(Adapt* a) { double t0 = PCU_Time(); EdgeOptimizer eo(a); @@ -1364,9 +1365,10 @@ static void optimizeInvalidEdges(Adapt* a) double t1 = PCU_Time(); ma::print("Optimized %d bad edges, failed %d edges " "in %f seconds",eo.ns, eo.nf, t1-t0); + return eo.ns; } -static void optimizeInvalidFaces(Adapt* a) +static int optimizeInvalidFaces(Adapt* a) { double t0 = PCU_Time(); FaceOptimizer fo(a); @@ -1374,117 +1376,25 @@ static void optimizeInvalidFaces(Adapt* a) double t1 = PCU_Time(); ma::print("Optimized %d bad faces, failed %d faces " "in %f seconds", fo.ns, fo.nf, t1-t0); + return fo.ns; } int fixInvalidFaces(Adapt* a) { - - ma::Mesh* mesh = a->mesh; - apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); - apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); - apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); - - apf::MeshEntity* ent; - apf::MeshIterator* it; - - it = mesh->begin(1); - int count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(edge_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(2); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(face_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(3); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(tet_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - /* optimizeInvalidFaces(a); */ - - mesh->removeNumbering(edge_num); - mesh->removeNumbering(face_num); - mesh->removeNumbering(tet_num); - - return 0; + return optimizeInvalidFaces(a); } int fixInvalidEdges(Adapt* a) { - - ma::Mesh* mesh = a->mesh; - apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); - apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); - apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); - - apf::MeshEntity* ent; - apf::MeshIterator* it; - - it = mesh->begin(1); int count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(edge_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(2); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(face_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(3); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(tet_num, ent, 0, 0, count); - count++; - } - mesh->end(it); if(a->mesh->getShape()->getOrder() == 2) - repositionInvalidEdges(a); + count += repositionInvalidEdges(a); else - optimizeInvalidEdges(a); - - mesh->removeNumbering(edge_num); - mesh->removeNumbering(face_num); - mesh->removeNumbering(tet_num); -/* - int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - if (! count){ - return 0; - } - - collapseInvalidEdges(a); - swapInvalidEdges(a); -*/ - return 0; -} - -int fixInvalidEdgesCollapseAndSwap(Adapt* a) -{ - int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - if (! count){ - return 0; - } - - collapseInvalidEdges(a); - swapInvalidEdges(a); + count += optimizeInvalidEdges(a); + count += collapseInvalidEdges(a); + count += swapInvalidEdges(a); return count; } diff --git a/crv/crvShape.cc.orig b/crv/crvShape.cc.orig new file mode 100644 index 000000000..decec3834 --- /dev/null +++ b/crv/crvShape.cc.orig @@ -0,0 +1,1575 @@ +/* + * Copyright 2015 Scientific Computation Research Center + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crv.h" +#include "crvAdapt.h" +#include "crvQuality.h" +#include "crvShape.h" +#include "crvTables.h" +#include "crvShapeFixer.h" +#include "crvOptimizations.h" + +/* This is similar to maShape.cc, conceptually, but different enough + * that some duplicate code makes sense */ + +namespace crv { + +bool isBoundaryEntity(apf::Mesh* m, apf::MeshEntity* e) +{ + return m->getModelType(m->toModel(e)) < m->getDimension(); +} +/** \brief checks if any entity has two entities of + * dimension on the boundary + * \details this is useful for some shape correction assessments, + * and in general, curved elements with multiple entities on the boundary + * are at risk for poor quality, since this strongly constrains + * their shape */ +static bool hasTwoEntitiesOnBoundary(apf::Mesh* m, apf::MeshEntity* e, int dimension) +{ + apf::Downward down; + int count = 0; + int nd = m->getDownward(e,dimension,down); + for (int i = 0; i < nd; ++i){ + if(isBoundaryEntity(m,down[i])) + ++count; + if(count == 2) + return true; + } + return false; +} + +/* Mark Edges based on the invalidity code the element has been + * tagged with. + */ + +static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) +{ + apf::MeshEntity* edges[6]; + int ne = mesh->getDownward(e, 1, edges); + + apf::MeshEntity* f[4]; + int nf = mesh->getDownward(e, 2, f); + apf::MeshEntity* vf[3]; + apf::MeshEntity* vt[4]; + mesh->getDownward(e, 0, vt); + + std::vector a; + std::vector b; + + // get the vertex local number for face from the invalid vertex + for (int i = 0; i < nf; i++) { + mesh->getDownward(f[i], 0, vf); + int j = apf::findIn(vf, 3, vt[index]); + + if (j != -1) { + a.push_back(i); + b.push_back(j); + } + } + + //getJacobianDeterminant on each face at + double c[3]; //contains jacobian value + int cc[3]; //face index + apf::Vector3 xi; + apf::Matrix3x3 Jac; + for(size_t k = 0; k < a.size(); k++) { + if (b[k] == 0) xi = {0, 0, 0}; + else if (b[k] == 1) xi = {1, 0, 0}; + else xi = {0, 1, 0}; + + cc[k] = k; + + apf::MeshElement* me = apf::createMeshElement(mesh, f[a[k]]); + apf::getJacobian(me, xi, Jac); + c[k] = apf::getJacobianDeterminant(Jac, 2); + + apf::destroyMeshElement(me); + } + + // sort min to max jacobian determinant + for (int i = 0; i < 3; i++) { + for (int j = i-1; j >= 0; --j) { + double k = c[j+1]; + int kk = cc[j+1]; + if ( k < c[j]) { + c[j+1] = c[j]; + c[j] = k; + cc[j+1] = cc[j]; + cc[j] = kk; + } + } + } + + apf::MeshEntity* ef[3]; + apf::MeshEntity* ve[2]; + std::vector aa; + //std::vector bb; + + // need to flag all adjacent edges + // hence only 2 faces would do + for (int i = 0; i < 2; i++) { + int nef = mesh->getDownward(f[a[cc[i]]], 1, ef); + for (int j = 0; j < nef; j++) { + mesh->getDownward(ef[j], 0, ve); + if (apf::findIn(ve, 2, vt[index]) != -1) { + int k = apf::findIn(edges, 6, ef[j]); + if (k != -1) { + if (aa.size() >= 2) { + bool contains = false; + for (std::size_t ii = 0; ii < aa.size(); ii++) + contains = contains || (k == aa[ii]); + if (contains == false) + aa.push_back(k); + } + else { + aa.push_back(k); + //bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); + } + } + } + } + } + + // aa has the index of the edges ordered + // min to max of adj face jacobian + + return aa; + +} + +static void sortDesWrtFreqVector(std::vector &f, std::vector &a) +{ + for (std::size_t i = 0; i < f.size(); i++) { + for (int j = i-1; j >= 0; j--) { + int ko = f[j+1]; + int ke = a[j+1]; + if (ko > f[j]) { + f[j+1] = f[j]; + a[j+1] = a[j]; + f[j] = ko; + a[j] = ke; + } + } + } +} + +static std::vector sortEdgeIndexByFrequency(std::vector &all) +{ + std::vector freq, unqEntries; + freq.push_back(1); + unqEntries.push_back(all[0]); + + for (std::size_t i = 1; i < all.size(); i++) { + bool milila = false; + + for (std::size_t j = 0; j < unqEntries.size(); j++) { + milila = milila || (all[i] == unqEntries[j]); + + if (all[i] == unqEntries[j]) { + freq[j] = freq[j] + 1; + } + } + if (milila == false) { + unqEntries.push_back(all[i]); + freq.push_back(1); + } + } + + sortDesWrtFreqVector(freq, unqEntries); + + return unqEntries; +} + +static std::vector numOfUniqueFaces(std::vector &ai) +{ + std::vector aiEdgeNVtx; + std::vector aiOnlyFace; + std::vector aiOnlyEdge; + std::vector aiOnlyVtx; + std::vector aiOnlyTet; + + std::vector aiUniqueFace; + std::vector FFE; + + for (size_t i = 0; i < ai.size(); i++) { + if (ai[i] < 8) aiOnlyVtx.push_back(ai[i]); + else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); + else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); + else aiOnlyTet.push_back(ai[i]); + + } + + int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, + {0, -1, 4, 3}, + {1, 4, -1, 5}, + {2, 3, 5, -1}}; + + int edgeToFaceInd[6][2] = {{0, 1}, + {0, 2}, + {0, 3}, + {1, 3}, + {1, 2}, + {2, 3}}; + + int edgeToVtx[6][2] = {{0, 1}, + {1, 2}, + {0, 2}, + {0, 3}, + {1, 3}, + {2, 3}}; + + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) { + for (std::size_t j = 0; j < aiOnlyFace.size(); j++) { + if ((i != j) && (j > i)) { + for (std::size_t k = 0; k < aiOnlyEdge.size(); k++) { + if (faceToEdgeInd[aiOnlyFace[i]-14][aiOnlyFace[j]-14] + 8 == aiOnlyEdge[k]) { + FFE.push_back(aiOnlyEdge[k]); + FFE.push_back(aiOnlyFace[j]); + FFE.push_back(aiOnlyFace[i]); + break; + } + } + break; + } + } + } + + bool hasDownVtx, alreadyIn; + + for (size_t j = 0; j < aiOnlyEdge.size(); j++) { + hasDownVtx = false; + for (int jj = 0; jj < 2; jj++) { + //hasDownVtx = false; + for (size_t ii = 0; ii < aiOnlyVtx.size(); ii++) { + hasDownVtx = hasDownVtx || (edgeToVtx[aiOnlyEdge[j]-8][jj] == aiOnlyVtx[ii] - 2); + } + } + + if (hasDownVtx == false) { + for (int i = 0; i < 2; i++) { + alreadyIn = false; + for (size_t k = 0; k < aiOnlyFace.size(); k++) { + alreadyIn = alreadyIn || (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14); + } + if (alreadyIn == false) { + aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); + } + } + } + else { + for (int i = 0; i < 2; i++) { + for (size_t k = 0; k < aiOnlyFace.size(); k++) { + if (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14) { + //aiOnlyFace.erase(aiOnlyFace.begin()+k); + } + } + } + } + } + + for (size_t j = 0; j < aiOnlyFace.size(); j++) { + aiUniqueFace.push_back(aiOnlyFace[j]); + } + + ai.clear(); + + std::vector forFaceMarking; + + // TODO: to be cleaned up + //[number of unique faces, {unique face index}, {pairs of face face coomon edge invalids}] + + if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { + forFaceMarking.push_back(aiUniqueFace.size()); + for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) + ai.push_back(aiOnlyVtx[i]); + for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) + ai.push_back(aiOnlyEdge[i]); + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + ai.push_back(aiOnlyFace[i]); + for (std::size_t i = 0; i < aiOnlyTet.size(); i++) + ai.push_back(aiOnlyTet[i]); + for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { + forFaceMarking.push_back(aiUniqueFace[i]); + } + for (std::size_t i = 0; i < FFE.size(); i++) + forFaceMarking.push_back(FFE[i]); + + } + else if (aiUniqueFace.size() == 0) { + forFaceMarking.push_back(0); + if (FFE.size() > 0) { + for (std::size_t i = 0; i < FFE.size(); i++) + forFaceMarking.push_back(FFE[i]); + } + for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) + ai.push_back(aiOnlyVtx[i]); + for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) + ai.push_back(aiOnlyEdge[i]); + for (std::size_t i = 0; i < aiOnlyFace.size(); i++) + ai.push_back(aiOnlyFace[i]); + } + return forFaceMarking; +} + +static int markAllEdges(ma::Mesh* m, ma::Entity* e, + std::vector ai, ma::Entity* edges[6]) +{ + std::vector bb; + apf::MeshEntity* edf[3]; + apf::MeshEntity* faces[4]; + ma::Downward ed; + m->getDownward(e,1,ed); + + //std::vector ai = inspectInvalidies(aiall); + std::vector faceInvalid = numOfUniqueFaces(ai); + + if (ai.size() == 0) return 0; + if (ai.size() == faceInvalid[0]) return 0; + + for (size_t ii = 0; ii < ai.size(); ii++) { + + int dim = (ai[ii]-2)/6; + int index = (ai[ii]-2) % 6; + + switch (dim) { + case 0: + { + //ma::Downward ed; + //m->getDownward(e,1,ed); + + std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); + PCU_ALWAYS_ASSERT(index < 4); + for (size_t i = 0; i < aa.size(); i++) + bb.push_back(aa[i]); + + break; + } + + case 1: + { + //ma::Downward ed; + //m->getDownward(e,1,ed); + bb.push_back(index); + bb.push_back(index); + break; + } + //break; + case 2: + { + // if we have an invalid face, operate on its edges + //ma::Downward edf, faces; + m->getDownward(e,2,faces); + m->getDownward(faces[index],1,edf); + + for (int i = 0; i < 3; i++) { + int j = apf::findIn(ed, 6, edf[i]); + //if (j != -1) + //bb.push_back(j); + } + break; + } + //break; + case 3: + { + m->getDownward(e,1,edges); + return 6; + } + default: + fail("invalid quality tag in markEdges\n"); + break; + } + } + + int n = 0; + //std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); + std::vector allinvEdges = sortEdgeIndexByFrequency(bb); + int k = 0; + + for (size_t i = 0; i < allinvEdges.size(); i++) { + if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { + n++; + edges[n-1] = ed[allinvEdges[i]]; + } + } + + return n; +} + +static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, + ma::Entity* edges[6]) +{ + if ( tag <= 1 ) // if its valid, or not checked, don't worry about it + return 0; + int dim = (tag-2)/6; + int index = (tag-2) % 6; + int n = 0; + int md = m->getDimension(); + switch (dim) { + case 0: + { + // if we have an invalid vertex, operate on its edges + ma::Downward ed; + m->getDownward(e,1,ed); + n = md; + + if(md == 2){ + edges[0] = ed[index]; + edges[1] = ed[(index+2) % 3]; + } else { + PCU_ALWAYS_ASSERT(index < 4); + edges[0] = ed[tetVertEdges[index][0]]; + edges[1] = ed[tetVertEdges[index][1]]; + edges[2] = ed[tetVertEdges[index][2]]; + } + break; + } + case 1: + { + // if we have a single invalid edge, operate on it + ma::Downward ed; + m->getDownward(e,1,ed); + edges[0] = ed[index]; + n = 1; + break; + } + case 2: + { + // if we have an invalid face, operate on its edges + ma::Downward ed, faces; + m->getDownward(e,2,faces); + m->getDownward(faces[index],1,ed); + n = 3; + edges[0] = ed[0]; + edges[1] = ed[1]; + edges[2] = ed[2]; + break; + } + case 3: + { + m->getDownward(e,1,edges); + n = 6; + break; + } + default: + fail("invalid quality tag in markEdges\n"); + break; + } + + return n; +} + +<<<<<<< HEAD +static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, + ma::Entity* faces[4]) +{ + + if (ai.size() == 0) return 0; + std::vector faceInvalid = numOfUniqueFaces(ai); + int n = 0; + + ma::Downward fc; + m->getDownward(e, 2, fc); + ma::Downward ed; + m->getDownward(e, 1, ed); + if (faceInvalid[0] > 0) { + for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { + int index = (faceInvalid[i] -2) % 6; + int md = m->getDimension(); + + if (m->getModelType(m->toModel(fc[index])) == 3) { + faces[n] = fc[index]; + n++; + } + } + } + return n; +======= +static apf::Vector3 getTriOrientation(apf::Mesh2* m, apf::MeshEntity* tri) +{ + PCU_ALWAYS_ASSERT(m->getType(tri) == apf::Mesh::TRIANGLE); + + apf::MeshEntity* vs[3]; + m->getDownward(tri, 0, vs); + apf::Vector3 ps[3]; + for (int i = 0; i < 3; i++) { + m->getPoint(vs[i], 0, ps[i]); + } + apf::Vector3 e0 = ps[1] - ps[0]; + apf::Vector3 e1 = ps[2] - ps[1]; + apf::Vector3 n0 = apf::cross(e0, e1); + return n0/n0.getLength(); +} + +static int getEdgeIdInSimplex(apf::Mesh2* m, apf::MeshEntity* tri, apf::MeshEntity* edge) +{ + PCU_ALWAYS_ASSERT(m->getType(tri) == apf::Mesh::TRIANGLE); + PCU_ALWAYS_ASSERT(m->getType(edge) == apf::Mesh::EDGE); + apf::MeshEntity* es[3]; + m->getDownward(tri, 1, es); + return apf::findIn(es, 3, edge); +>>>>>>> develop +} + +class EdgeSwapper : public ma::Operator +{ +public: + EdgeSwapper(Adapt* a) + { + adapter = a; + mesh = a->mesh; + edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; + simplex = 0; + edgeSwap = ma::makeEdgeSwap(a); + md = mesh->getDimension(); + ne = ns = 0; + } + virtual ~EdgeSwapper() + { + delete edgeSwap; + } + virtual int getTargetDimension() {return md;} + virtual bool shouldApply(ma::Entity* e) + { + std::vector ai = crv::getAllInvalidities(mesh, e); + mesh->getDownward(e, 1, edges); + int niv = ai.size(); + ne = 0; + if (niv != 0) { + ne = markAllEdges(mesh, e, ai, edges); + simplex = e; + } + return (ne > 0); + /* + int tag = crv::getTag(adapter,e); + ne = markEdges(mesh,e,tag,edges); + + simplex = e; + return (ne > 0); + */ + } + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(edges,ne); + } + virtual void apply() + { + for (int i = 0; i < ne; ++i){ + if (edgeSwap->run(edges[i])){ + ns++; + // crv::clearTag(adapter,simplex); + ma::clearFlag(adapter,edges[i],ma::COLLAPSE | ma::BAD_QUALITY); + break; + } + } + } +private: + Adapt* adapter; + ma::Mesh* mesh; + ma::Entity* simplex; + ma::Entity* edges[6]; + ma::EdgeSwap* edgeSwap; + int md; + int ne; +public: + int ns; +}; + +class EdgeReshaper : public ma::Operator +{ +public: + EdgeReshaper(Adapt* a) + { + adapter = a; + mesh = a->mesh; + edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; + simplex = 0; + md = mesh->getDimension(); + ne = nr = 0; + qual = makeQuality(mesh,2); + } + virtual ~EdgeReshaper() + { + delete qual; + } + virtual int getTargetDimension() {return md;} + virtual bool shouldApply(ma::Entity* e) + { + int tag = crv::getTag(adapter,e); + + ne = markEdges(mesh,e,tag,edges); + simplex = e; + return (ne > 0); + } + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(edges,ne); + } + virtual void apply() + { + for (int i = 0; i < ne; ++i){ + if (!isBoundaryEntity(mesh,edges[i]) && + repositionEdge(edges[i])){ + nr++; + crv::clearTag(adapter,simplex); + ma::clearFlag(adapter,edges[i],ma::COLLAPSE | ma::BAD_QUALITY); + break; + } + } + } +private: + /** \brief reposition second order edge control point based on XJ Luo's + thesis and bezier.tex in SCOREC/docs repo, only works for second order */ + bool repositionEdge(ma::Entity* edge) + { + // lets assume we have an edge we want to fix + // only support second order for now + int P = mesh->getShape()->getOrder(); + if (P != 2) return false; + + ma::Entity* verts[4]; + ma::Entity* edges[6]; + + ma::Vector pivotPoint; + ma::Vector edgeVectors[3]; + mesh->getDownward(simplex,0,verts); + mesh->getDownward(simplex,1,edges); + + // pick a pivotVert, the vertex with the worse jacobian determinant + ma::Entity* pivotVert; + int pivotIndex; + { + apf::MeshElement* me = apf::createMeshElement(mesh,simplex); + + ma::Entity* edgeVerts[2]; + mesh->getDownward(edge,0,edgeVerts); + apf::Matrix3x3 J; + pivotIndex = apf::findIn(verts,4,edgeVerts[0]); + PCU_ALWAYS_ASSERT(pivotIndex >= 0); + + ma::Vector xi; + if (md == 3) + xi = crv::elem_vert_xi[apf::Mesh::TET][pivotIndex]; + else if (md == 2) + xi = crv::elem_vert_xi[apf::Mesh::TRIANGLE][pivotIndex]; + else + PCU_ALWAYS_ASSERT(0); + + apf::getJacobian(me,xi,J); + + double j; + if (md == 3) + j = apf::getJacobianDeterminant(J,3); + else if (md == 2) + j = apf::getJacobianDeterminant(J,2); + else + PCU_ALWAYS_ASSERT(0); + + pivotVert = edgeVerts[0]; + + int index = apf::findIn(verts,4,edgeVerts[1]); + PCU_ALWAYS_ASSERT(index >= 0); + if (md == 3) + xi = crv::elem_vert_xi[apf::Mesh::TET][index]; + else if (md == 2) + xi = crv::elem_vert_xi[apf::Mesh::TRIANGLE][index]; + else + PCU_ALWAYS_ASSERT(0); + + + apf::getJacobian(me,xi,J); + + if ((md == 3 && apf::getJacobianDeterminant(J,3) < j) || + (md == 2 && apf::getJacobianDeterminant(J,2) < j)){ + pivotVert = edgeVerts[1]; + pivotIndex = index; + } + apf::destroyMeshElement(me); + } + + mesh->getPoint(pivotVert,0,pivotPoint); + + // local, of edges around vert, [0,2] + int edgeIndex = 0; + + for (int i = 0; i < md; ++i){ + // theres only one point, so reuse this... + if (md == 3) + edgeVectors[i] = ma::getPosition(mesh,edges[tetVertEdges[pivotIndex][i]]) + - pivotPoint; + else if (md == 2) + edgeVectors[i] = ma::getPosition(mesh,edges[triVertEdges[pivotIndex][i]]) + - pivotPoint; + else + PCU_ALWAYS_ASSERT(0); + + if ((md == 3 && edges[tetVertEdges[pivotIndex][i]] == edge) || + (md == 2 && edges[triVertEdges[pivotIndex][i]] == edge)) + edgeIndex = i; + } + + PCU_ALWAYS_ASSERT(edgeIndex >= 0); + + ma::Entity* edge1; + ma::Entity* edge2; + // For 3D meshes get the other 2 edges to form a reflection plane + // Note that the order does not matter + if (md == 3) { + edge1 = edges[tetVertEdges[pivotIndex][(edgeIndex+1)%3]]; + edge2 = edges[tetVertEdges[pivotIndex][(edgeIndex+2)%3]]; + } + // For 2D meshes the invalid edge has to be reflected wrt the + // other edge connected to the pivot vertex + // So let: + // edge1 = edge + // edge2 = other edge + else if (md == 2) { + edge1 = edge; + edge2 = edges[triVertEdges[pivotIndex][(edgeIndex+1)%2]]; + } + + + if (md == 3) { + // Find the normal to the plane of edge1 and edge2 by first computing the edge + // tangents at the pivotVert + ma::Vector t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + ma::Vector t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + ma::Vector normal = apf::cross(t1, t2); + double length = normal.getLength(); + double validity = edgeVectors[edgeIndex]*normal; + + if(validity > 1e-10) + return false; + ma::Vector oldPoint = ma::getPosition(mesh,edge); + apf::Adjacent adjacent; + mesh->getAdjacent(edge,3,adjacent); + + /* mirror the vector edgeVectors[edgeIndex] with respect to the plane + * perpendicular to the normal. The parameter alpha scales the normal + * (to the plane) component of the mirrored vector. + */ + double alpha = 0.5; + + ma::Vector newPoint = pivotPoint + edgeVectors[edgeIndex] - + normal * (normal * edgeVectors[edgeIndex]) * (1 + alpha) / length / length; + + mesh->setPoint(edge,0,newPoint); + + for (std::size_t i = 0; i < adjacent.getSize(); ++i){ + if (qual->checkValidity(adjacent[i]) < 0){ + mesh->setPoint(edge,0,oldPoint); + return false; + } + } + } + else if (md == 2) { + // edge1 which should be the same as edge needs to be modified + PCU_ALWAYS_ASSERT(edge1 == edge); + // get the orientation of the simplex using its vertex coordinates + apf::Vector3 normal = getTriOrientation(mesh, simplex); + int edge1Idx, edge2Idx; + edge1Idx = getEdgeIdInSimplex(mesh, simplex, edge1); + PCU_ALWAYS_ASSERT(edge1Idx > -1); + edge2Idx = getEdgeIdInSimplex(mesh, simplex, edge2); + PCU_ALWAYS_ASSERT(edge2Idx > -1); + ma::Vector t1 = ma::Vector(0.0, 0.0, 0.0); + ma::Vector t2 = ma::Vector(0.0, 0.0, 0.0); + switch(pivotIndex) { + case 0: + if (edge1Idx == 0 && edge2Idx == 2) { + t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else if (edge1Idx == 2 && edge2Idx == 0) { + t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else + PCU_ALWAYS_ASSERT(0); + break; + case 1: + if (edge1Idx == 1 && edge2Idx == 0) { + t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else if (edge1Idx == 0 && edge2Idx == 1) { + t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else + PCU_ALWAYS_ASSERT(0); + break; + case 2: + if (edge1Idx == 2 && edge2Idx == 1) { + t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else if (edge1Idx == 1 && edge2Idx == 2) { + t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); + } + else + PCU_ALWAYS_ASSERT(0); + break; + default: + break; + } + + // At this point if t1xt2 is in the same direction as the normal the triangle is valid + apf::Vector3 normal2 = apf::cross(t1, t2); + if (normal * normal2 > 0) + return false; + + ma::Vector oldPoint = ma::getPosition(mesh,edge); + apf::Adjacent adjacent; + mesh->getAdjacent(edge,md,adjacent); + + /* mirror the vector edgeVectors[edgeIndex] with respect the other edge2 */ + double alpha = 0.5; + + apf::MeshEntity* edge1OppV = 0; + apf::MeshEntity* edge2OppV = 0; + apf::MeshEntity* vs[2]; + + mesh->getDownward(edge1, 0, vs); + edge1OppV = (vs[0] == pivotVert) ? vs[1] : vs[0]; + PCU_ALWAYS_ASSERT(edge1OppV); + + mesh->getDownward(edge2, 0, vs); + edge2OppV = (vs[0] == pivotVert) ? vs[1] : vs[0]; + PCU_ALWAYS_ASSERT(edge2OppV); + + apf::Vector3 L = ma::getPosition(mesh, edge1OppV) - ma::getPosition(mesh, pivotVert); + apf::Vector3 refL = ma::getPosition(mesh, edge2OppV) - ma::getPosition(mesh, pivotVert); + refL = refL/refL.getLength(); // refL is unit + + // get the part of L that is perpendicular to refL + apf::Vector3 x = L - refL * (refL * L); + // make sure x is in the plane of edge1 and edge2 + x = x - normal * (normal * x); + apf::Vector3 deltaX = L - x * alpha * 2; + ma::Vector newPoint = pivotPoint + deltaX; + + mesh->setPoint(edge,0,newPoint); + for (std::size_t i = 0; i < adjacent.getSize(); ++i){ + if (qual->checkValidity(adjacent[i]) < 0){ + mesh->setPoint(edge,0,oldPoint); + return false; + } + } + } + else + PCU_ALWAYS_ASSERT(0); + + return true; + } + Adapt* adapter; + ma::Mesh* mesh; + Quality* qual; + ma::Entity* simplex; + ma::Entity* edges[6]; + int md; + int ne; +public: + int nr; +}; + +class FaceOptimizer : public ma::Operator +{ +public: + FaceOptimizer(Adapt* a) { + adapter = a; + mesh = a->mesh; + faces[0] = faces[1] = faces[2] = faces[3] = 0; + simplex = 0; + md = mesh->getDimension(); + numf = 0; + ns = 0; + nf = 0; + } + ~FaceOptimizer() { + } + virtual int getTargetDimension() {return md;} + virtual bool shouldApply(ma::Entity* e) { + + std::vector ai = crv::getAllInvalidities(mesh, e); + int niv = ai.size(); + mesh->getDownward(e, 2, faces); + numf = 0; + if (niv != 0) { + numf = markUniqueFaces(mesh, e, ai, faces); + simplex = e; + } + return (numf > 0); + } + + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(faces, numf); + } + + virtual void apply(){ + int invaliditySize = 0; + //mesh->getDownward(simplex, 2, faces); + if (numf == 0) return; + for (int i = 0; i < numf; i++ ) { + if (mesh->getModelType(mesh->toModel(faces[i])) != 3) continue; + //CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, DETJ); + CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, NIJK); + cfo->setMaxIter(100); + cfo->setTol(1e-8); + if (cfo->run(invaliditySize)) { + if (invaliditySize < 1) { + ns++; + delete cfo; + break; + } + } + else { + nf++; + if (invaliditySize < 1) { + delete cfo; + break; + } + } + delete cfo; + } + } +protected: + Adapt* adapter; + ma::Mesh* mesh; +public: + ma::Entity* faces[4]; + ma::Entity* simplex; + int numf; + int md; + int ns; + int nf; +}; + +class EdgeOptimizer : public ma::Operator +{ +public: + EdgeOptimizer(Adapt* a) { + adapter = a; + mesh = a->mesh; + edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; + simplex = 0; + md = mesh->getDimension(); + ns = 0; + nf = 0; + ne = 0; + } + ~EdgeOptimizer() { + } + virtual int getTargetDimension() {return md;} + virtual bool shouldApply(ma::Entity* e) { + std::vector ai = crv::getAllInvalidities(mesh, e); + mesh->getDownward(e, 1, edges); + int niv = ai.size(); + ne = 0; + if (niv != 0) { + ne = markAllEdges(mesh, e, ai, edges); + simplex = e; + } + return (ne > 0); + } + + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(edges, ne); + } + + virtual void apply() { + if (ne == 0) return; + for (int i = 0; i < ne; i++ ) { + int invaliditySize = 0; + bool hasDecreased = false; + CrvEntityOptim* ceo; + + if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { + //ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, DETJ); + ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, NIJK); + } + else { + //ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, DETJ); + ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, NIJK); + } + + ceo->setMaxIter(100); + ceo->setTol(1e-8); + + if (ceo->run(invaliditySize)) { + ns++; + if (invaliditySize < 1) { + break; + delete ceo; + } + } + else { + nf++; + if (invaliditySize < 1) { + delete ceo; + break; + } + } + delete ceo; + } + } +protected: + Adapt* adapter; + ma::Mesh* mesh; + ma::Entity* edge; +public: + int ne; + int md; + ma::Entity* edges[6]; + ma::Entity* simplex; + int ns; + int nf; +}; + +static bool isCornerTriAngleLargeMetric(crv::Adapt *a, + ma::Entity* tri, int index) +{ + ma::Mesh* m = a->mesh; + // get downward vertexes + ma::Entity* down[3]; + m->getDownward(tri, 0, down); + // first get the size field at the center of the tri + ma::SizeField* sf = a->sizeField; + apf::Matrix3x3 Q; + apf::MeshElement* element = apf::createMeshElement(m, tri); + sf->getTransform(element, apf::Vector3(1./3.,1./3.,1./3.), Q); + ma::Vector cornerNormal = computeFaceNormalAtVertex(m, tri, down[index], Q); + apf::destroyMeshElement(element); + + ma::Vector normal = ma::getTriNormal(m,tri); + + // this statement is not exactly a fair comparison, but at least gives + // some level of control over what is considered an invalid angle + // an angle is "too large" if the dot product between the corner triangle + // and the triangle formed by its vertices is negative + if (cornerNormal*normal < a->input->validQuality) + return true; + + return false; +} + +/* Checks if an angle of a triangle is large (>= 180 degrees) + * which can be caused by two edges on the boundary curved to it + * + */ +static ma::Entity* isLargeAngleTriMetric(crv::Adapt* a, ma::Entity* e) +{ + ma::Mesh* m = a->mesh; + ma::Entity* edges[3]; + m->getDownward(e,1,edges); + for (int i = 0; i < 3; ++i) + { + ma::Entity* e0 = edges[i]; + ma::Entity* e1 = edges[(i+1) % 3]; + if(isBoundaryEntity(m,e0) && isBoundaryEntity(m,e1)) + { + // TODO: This conditions seems problematic. Think + // about a better version. My intuition is that the + // following to edges has to be marked + // (i+1)%3 and i%3 + if(isCornerTriAngleLargeMetric(a,e,(i+1) % 3)){ + ma::Entity* edge = edges[(i+2) % 3]; + if(!ma::getFlag(a,edge,ma::SPLIT) && !isBoundaryEntity(m,edge)){ + return edge; + } + } + } + } + return 0; +} + +/* Checks if an angle of a tet is large (>= 180 degrees) + * which can be caused by two edges on the boundary curved to it + * + * An analytic approach, looking at the control point net of points + * by comparing surface normals of each pair of control net points + * adjacent to the triangle is an incredibly complex ordering exercise + * Rather than attempt to do the ordering, sampling the Jacobian at + * P+1 points is used. A validity check on this edge could also be used + */ + +static ma::Entity* isLargeAngleTetMetric(crv::Adapt* a, ma::Entity* e) +{ + ma::Mesh* m = a->mesh; + // first get the size field at the center of the entity e + ma::SizeField* sf = a->sizeField; + apf::Matrix3x3 Q; + apf::MeshElement* element = apf::createMeshElement(m, e); + + sf->getTransform(element, apf::Vector3(0.25,0.25,0.25), Q); + + apf::destroyMeshElement(element); + + ma::Entity* edges[6]; + ma::Entity* faces[4]; + m->getDownward(e,1,edges); + m->getDownward(e,2,faces); + + + // find edge that matters + int index = -1; + for (int i = 0; i < 6; ++i){ + if(isBoundaryEntity(m,faces[edgeFaces[i][0]]) && + isBoundaryEntity(m,faces[edgeFaces[i][1]])){ + index = i; + break; + } + } + if(index < 0) return 0; + + if(!isBoundaryEntity(m,edges[index])) return 0; + + + ma::Entity* leftFace = faces[edgeFaces[index][0]]; + ma::Entity* rightFace = faces[edgeFaces[index][1]]; + double cosAngle = apf::computeCosAngleInTet(m, e, leftFace, rightFace, Q); + + ma::Entity* edge = 0; + if (cosAngle < -0.9) + edge = edges[oppEdges[index]]; + + return edge; +} + + +// BAD_QUALITY flag is used on edges to identify them +// as splits for quality, rather than for size refinement +// These two functions handle two seperate situations + +// First, triangles are looked at to see if they have an angle > 180 degrees +// There is also a check for the weird situation described above +// Second, tets are looked at to see if they have two faces on the boundary +// where the jacobian determinant is negative along the shared edge, +// indicative of a large angle (curving around a cylinder or sphere). + +static int markEdgesOppLargeAnglesTri(Adapt* a) +{ + int count = 0; + int prev_count; + + ma::Mesh* m = a->mesh; + ma::Entity* e; + + do { + ma::Iterator* it = m->begin(2); + prev_count = count; + while ((e = m->iterate(it))) + { + if(!hasTwoEntitiesOnBoundary(m,e,1)) continue; + ma::Entity* edge = isLargeAngleTriMetric(a,e); + if (edge) + { + PCU_ALWAYS_ASSERT(m->getType(edge) == 1); + ma::setFlag(a,edge,ma::SPLIT); + ma::setFlag(a,edge,ma::BAD_QUALITY); + if (a->mesh->isOwned(edge)) + ++count; + } + } + m->end(it); + } while(count > prev_count); + return PCU_Add_Long(count); +} + +static int markEdgesOppLargeAnglesTet(Adapt* a) +{ + int count = 0; + int prev_count; + + ma::Mesh* m = a->mesh; + ma::Entity* e; + + do { + ma::Iterator* it = m->begin(3); + prev_count = count; + while ((e = m->iterate(it))) + { + ma::Entity* edge = isLargeAngleTetMetric(a,e); + if (edge && !ma::getFlag(a,edge,ma::SPLIT)) + { + PCU_ALWAYS_ASSERT(m->getType(edge) == 1); + ma::setFlag(a,edge,ma::SPLIT); + ma::setFlag(a,edge,ma::BAD_QUALITY); + if (a->mesh->isOwned(edge)) + ++count; + } + } + m->end(it); + } while(count > prev_count); + return PCU_Add_Long(count); +} + +/* The whole idea is to do the quality check once, + * and then use the results to mark edges, etc for + * fixing + */ + +static int markEdgesToFix(Adapt* a, int flag) +{ + // do a invalidity check first + int invalid = markInvalidEntities(a); + if ( !invalid ) + return 0; + int count = 0; + + ma::Mesh* m = a->mesh; + ma::Entity* e; + + // markEdges could have upto 6 edges marked!!! + ma::Entity* edges[6]; + ma::Iterator* it = m->begin(m->getDimension()); + + while ((e = m->iterate(it))) + { + //int tag = crv::getTag(a,e); + //int n = markEdges(m,e,tag,edges); + + std::vector ai = crv::getAllInvalidities(m, e); + int niv = ai.size(); + + if (niv != 0) { + int n = markAllEdges(m, e, ai, edges); + for (int i = 0; i < n; ++i){ + ma::Entity* edge = edges[i]; + PCU_ALWAYS_ASSERT(edge); + + if (edge && !ma::getFlag(a,edge,flag)) { + ma::setFlag(a,edge,flag); + if (a->mesh->isOwned(edge)) + ++count; + } + } + } + } + m->end(it); + + return PCU_Add_Long(count); +} + +/* +static int markFacesToFix(Adapt* a, int flag) +{ + int invalid = markInvalidEntities(a); + if (!invalid) + return 0; + int count = 0; + + ma::Mesh* m = a->mesh; + ma::Entity* e; + + ma::Entity* faces[4]; + ma::Iterator* it = m->begin(m->getDimension()); + while ((e = m->iterate(it))) + { + std::vector ai = crv::getAllInvalidities(m, e); +// int tag = crv::getTag(a, e); +// int n = markFaces(m, e, tag, faces); + int n = markUniqueFaces(m, e, ai, faces); + for (int i = 0; i < n; i++) { + ma::Entity* face = faces[i]; + PCU_ALWAYS_ASSERT(face); + if (face && !ma::getFlag(a, face, flag)) { + if (m->getModelType(m->toModel(face)) != 2) + ma::setFlag(a, face, flag); + if (a->mesh->isOwned(face)) + count++; + } + } + } + m->end(it); + + return PCU_Add_Long(count); +} +*/ +int fixLargeBoundaryAngles(Adapt* a) +{ + double t0 = PCU_Time(); + int count = markEdgesOppLargeAnglesTet(a); + count += markEdgesOppLargeAnglesTri(a); + + if ( ! count){ + return 0; + } + splitEdges(a); + double t1 = PCU_Time(); + ma::print("split %d boundary edges with " + "large angles in %f seconds",count,t1-t0); + return 0; +} + +static void collapseInvalidEdges(Adapt* a) +{ + double t0 = PCU_Time(); + ma::Mesh* m = a->mesh; + int maxDimension = m->getDimension(); + PCU_ALWAYS_ASSERT(checkFlagConsistency(a,1,ma::COLLAPSE)); + int successCount = 0; + for (int modelDimension=1; modelDimension <= maxDimension; ++modelDimension) + { + checkAllEdgeCollapses(a,modelDimension); + findIndependentSet(a); + successCount += ma::collapseAllEdges(a, modelDimension); + } + successCount = PCU_Add_Long(successCount); + double t1 = PCU_Time(); + ma::print("Collapsed %d bad edges " + "in %f seconds",successCount, t1-t0); +} + +static void swapInvalidEdges(Adapt* a) +{ + double t0 = PCU_Time(); + EdgeSwapper es(a); + ma::applyOperator(a,&es); + double t1 = PCU_Time(); + ma::print("Swapped %d bad edges " + "in %f seconds",es.ns, t1-t0); +} + +static void repositionInvalidEdges(Adapt* a) +{ + double t0 = PCU_Time(); + EdgeReshaper es(a); + ma::applyOperator(a,&es); + double t1 = PCU_Time(); + ma::print("Repositioned %d bad edges " + "in %f seconds",es.nr, t1-t0); +} + +static void optimizeInvalidEdges(Adapt* a) +{ + double t0 = PCU_Time(); + EdgeOptimizer eo(a); + ma::applyOperator(a,&eo); + double t1 = PCU_Time(); + ma::print("Optimized %d bad edges, failed %d edges " + "in %f seconds",eo.ns, eo.nf, t1-t0); +} + +static void optimizeInvalidFaces(Adapt* a) +{ + double t0 = PCU_Time(); + FaceOptimizer fo(a); + ma::applyOperator(a, &fo); + double t1 = PCU_Time(); + ma::print("Optimized %d bad faces, failed %d faces " + "in %f seconds", fo.ns, fo.nf, t1-t0); +} + +int fixInvalidFaces(Adapt* a) +{ + + ma::Mesh* mesh = a->mesh; + apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); + apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); + apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); + + apf::MeshEntity* ent; + apf::MeshIterator* it; + + it = mesh->begin(1); + int count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(edge_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(2); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(face_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(3); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(tet_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + /* optimizeInvalidFaces(a); */ + + mesh->removeNumbering(edge_num); + mesh->removeNumbering(face_num); + mesh->removeNumbering(tet_num); + + return 0; +} + +int fixInvalidEdges(Adapt* a) +{ + + ma::Mesh* mesh = a->mesh; + apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); + apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); + apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); + + apf::MeshEntity* ent; + apf::MeshIterator* it; + + it = mesh->begin(1); + int count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(edge_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(2); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(face_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + it = mesh->begin(3); + count = 0; + while( (ent = mesh->iterate(it)) ) { + apf::number(tet_num, ent, 0, 0, count); + count++; + } + mesh->end(it); + + if(a->mesh->getShape()->getOrder() == 2) + repositionInvalidEdges(a); + else + optimizeInvalidEdges(a); + + mesh->removeNumbering(edge_num); + mesh->removeNumbering(face_num); + mesh->removeNumbering(tet_num); +/* + int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); + if (! count){ + return 0; + } + + collapseInvalidEdges(a); + swapInvalidEdges(a); +*/ + return 0; +} + +int fixInvalidEdgesCollapseAndSwap(Adapt* a) +{ + int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); + if (! count){ + return 0; + } + + collapseInvalidEdges(a); + swapInvalidEdges(a); + + return count; +} + +struct IsBadCrvQuality : public ma::Predicate +{ + IsBadCrvQuality(Adapt* a_):a(a_) + { + sh = crv::getShapeHandler(a); + } + ~IsBadCrvQuality() + { + delete sh; + } + bool operator()(apf::MeshEntity* e) + { + return sh->getQuality(e) < a->input->goodQuality; + } + Adapt* a; + ma::ShapeHandler* sh; +}; + +int markCrvBadQuality(Adapt* a) +{ + IsBadCrvQuality p(a); + return ma::markEntities(a, a->mesh->getDimension(), p, + ma::BAD_QUALITY, ma::OK_QUALITY); +} + + +int fixLargeAngles(Adapt *a) +{ + if (a->mesh->getDimension() == 3) { + CrvLargeAngleTetFixer tetFixer(a); + applyOperator(a, &tetFixer); + /* return tetFixer.getSuccessCount(); */ + } + else { + CrvLargeAngleTriFixer triFixer(a); + applyOperator(a, &triFixer); + /* return triFixer.getSuccessCount(); */ + } + return 0; +} + +static int fixShortEdgeElements(Adapt* a) +{ + CrvShortEdgeFixer fixer(a); + applyOperator(a,&fixer); + return fixer.nr; +} + +void fixCrvElementShapes(Adapt* a) +{ + if ( ! a->input->shouldFixShape) + return; + a->input->shouldForceAdaptation = true; + double t0 = PCU_Time(); + int count = markCrvBadQuality(a); + int originalCount = count; + int prev_count; + int i = 0; + do { + if ( ! count) + break; + prev_count = count; + fixLargeAngles(a); // update this + /* int numOpSuccess = fixLargeAngles(a); // update this */ + /* PCU_Add_Ints(&numOpSuccess,1); */ + /* if (PCU_Comm_Self() == 0) */ + /* lion_oprint(1,"==> %d large angle fix operations succeeded.\n", numOpSuccess); */ + markCrvBadQuality(a); + fixShortEdgeElements(a); // update this + /* int numEdgeRemoved = fixShortEdgeElements(a); // update this */ + /* PCU_Add_Ints(&numEdgeRemoved,1); */ + /* if (PCU_Comm_Self() == 0) */ + /* lion_oprint(1,"==> %d edges removal operations succeeded.\n", numEdgeRemoved); */ + //fixInvalidFaces(a); + count = markCrvBadQuality(a); + ++i; + } while(count < prev_count && i < 6); // the second conditions is to make sure this does not take long + double t1 = PCU_Time(); + ma::print("bad shapes down from %d to %d in %f seconds", + originalCount,count,t1-t0); + a->input->shouldForceAdaptation = false; +} + +} diff --git a/crv/crvShape.h b/crv/crvShape.h index 7fe8876ee..2536a13a5 100644 --- a/crv/crvShape.h +++ b/crv/crvShape.h @@ -58,7 +58,6 @@ int fixLargeBoundaryAngles(Adapt* a); /** \brief If an edge is flagged as invalid, try and collapse or swap it away */ int fixInvalidEdges(Adapt* a); -int fixInvalidEdgesCollapseAndSwap(Adapt* a); /** \brief If a face is flagged as invalid optimize the face nodes */ From 0f186dd623e115ede47509d82af3f3b582476bfb Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Fri, 6 Mar 2020 11:30:53 -0500 Subject: [PATCH 46/48] fixed acceptance criteria for internal edge reshape. --- crv/crvOptimizations.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crv/crvOptimizations.cc b/crv/crvOptimizations.cc index 85f895945..cc0a93287 100644 --- a/crv/crvOptimizations.cc +++ b/crv/crvOptimizations.cc @@ -20,6 +20,7 @@ static void printInvalidities(apf::Mesh2* m, apf::Adjacent e, apf::MeshEntity* edge) { + return; int nat = e.getSize(); apf::Numbering* n = m->findNumbering("debug_num_edge"); PCU_ALWAYS_ASSERT(n); @@ -335,7 +336,7 @@ bool CrvInternalEdgeOptim :: run(int &invaliditySize) bool hasDecreased = false; invaliditySize = 0; - if (l->run() && thisTetSize > 1) { + if (l->run() && thisTetSize > 0) { finalX = l->currentX; fval = l->fValAfter; objF->setNodes(finalX); From 0ef2a9e8f35fd0ee12209175c8b13d368f3dea89 Mon Sep 17 00:00:00 2001 From: Avinash Moharana Date: Fri, 6 Mar 2020 12:24:21 -0500 Subject: [PATCH 47/48] includes some crv header files public. --- crv/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crv/CMakeLists.txt b/crv/CMakeLists.txt index 68ec722dd..80ffb6ecc 100644 --- a/crv/CMakeLists.txt +++ b/crv/CMakeLists.txt @@ -29,6 +29,12 @@ set(SOURCES # Package headers set(HEADERS crv.h + crvAdapt.h + crvBezier.h + crvQuality.h + crvOptimizations.h + crvObjectiveFunctions.h + LBFGS.h ) # Add the crv library From 3cc56251a3be33bc98db6696e65158aa0a4e4ebb Mon Sep 17 00:00:00 2001 From: "Morteza H. Siboni" Date: Tue, 26 May 2020 12:01:55 -0400 Subject: [PATCH 48/48] Removes unnecessary file from the repo --- crv/crvShape.cc.orig | 1575 ------------------------------------------ 1 file changed, 1575 deletions(-) delete mode 100644 crv/crvShape.cc.orig diff --git a/crv/crvShape.cc.orig b/crv/crvShape.cc.orig deleted file mode 100644 index decec3834..000000000 --- a/crv/crvShape.cc.orig +++ /dev/null @@ -1,1575 +0,0 @@ -/* - * Copyright 2015 Scientific Computation Research Center - * - * This work is open source software, licensed under the terms of the - * BSD license as described in the LICENSE file in the top-level directory. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "crv.h" -#include "crvAdapt.h" -#include "crvQuality.h" -#include "crvShape.h" -#include "crvTables.h" -#include "crvShapeFixer.h" -#include "crvOptimizations.h" - -/* This is similar to maShape.cc, conceptually, but different enough - * that some duplicate code makes sense */ - -namespace crv { - -bool isBoundaryEntity(apf::Mesh* m, apf::MeshEntity* e) -{ - return m->getModelType(m->toModel(e)) < m->getDimension(); -} -/** \brief checks if any entity has two entities of - * dimension on the boundary - * \details this is useful for some shape correction assessments, - * and in general, curved elements with multiple entities on the boundary - * are at risk for poor quality, since this strongly constrains - * their shape */ -static bool hasTwoEntitiesOnBoundary(apf::Mesh* m, apf::MeshEntity* e, int dimension) -{ - apf::Downward down; - int count = 0; - int nd = m->getDownward(e,dimension,down); - for (int i = 0; i < nd; ++i){ - if(isBoundaryEntity(m,down[i])) - ++count; - if(count == 2) - return true; - } - return false; -} - -/* Mark Edges based on the invalidity code the element has been - * tagged with. - */ - -static std::vector getEdgeSequenceFromInvalidVertex(ma::Mesh* mesh, ma::Entity* e, int index) -{ - apf::MeshEntity* edges[6]; - int ne = mesh->getDownward(e, 1, edges); - - apf::MeshEntity* f[4]; - int nf = mesh->getDownward(e, 2, f); - apf::MeshEntity* vf[3]; - apf::MeshEntity* vt[4]; - mesh->getDownward(e, 0, vt); - - std::vector a; - std::vector b; - - // get the vertex local number for face from the invalid vertex - for (int i = 0; i < nf; i++) { - mesh->getDownward(f[i], 0, vf); - int j = apf::findIn(vf, 3, vt[index]); - - if (j != -1) { - a.push_back(i); - b.push_back(j); - } - } - - //getJacobianDeterminant on each face at - double c[3]; //contains jacobian value - int cc[3]; //face index - apf::Vector3 xi; - apf::Matrix3x3 Jac; - for(size_t k = 0; k < a.size(); k++) { - if (b[k] == 0) xi = {0, 0, 0}; - else if (b[k] == 1) xi = {1, 0, 0}; - else xi = {0, 1, 0}; - - cc[k] = k; - - apf::MeshElement* me = apf::createMeshElement(mesh, f[a[k]]); - apf::getJacobian(me, xi, Jac); - c[k] = apf::getJacobianDeterminant(Jac, 2); - - apf::destroyMeshElement(me); - } - - // sort min to max jacobian determinant - for (int i = 0; i < 3; i++) { - for (int j = i-1; j >= 0; --j) { - double k = c[j+1]; - int kk = cc[j+1]; - if ( k < c[j]) { - c[j+1] = c[j]; - c[j] = k; - cc[j+1] = cc[j]; - cc[j] = kk; - } - } - } - - apf::MeshEntity* ef[3]; - apf::MeshEntity* ve[2]; - std::vector aa; - //std::vector bb; - - // need to flag all adjacent edges - // hence only 2 faces would do - for (int i = 0; i < 2; i++) { - int nef = mesh->getDownward(f[a[cc[i]]], 1, ef); - for (int j = 0; j < nef; j++) { - mesh->getDownward(ef[j], 0, ve); - if (apf::findIn(ve, 2, vt[index]) != -1) { - int k = apf::findIn(edges, 6, ef[j]); - if (k != -1) { - if (aa.size() >= 2) { - bool contains = false; - for (std::size_t ii = 0; ii < aa.size(); ii++) - contains = contains || (k == aa[ii]); - if (contains == false) - aa.push_back(k); - } - else { - aa.push_back(k); - //bb.push_back(mesh->getModelType(mesh->toModel(ef[j]))); - } - } - } - } - } - - // aa has the index of the edges ordered - // min to max of adj face jacobian - - return aa; - -} - -static void sortDesWrtFreqVector(std::vector &f, std::vector &a) -{ - for (std::size_t i = 0; i < f.size(); i++) { - for (int j = i-1; j >= 0; j--) { - int ko = f[j+1]; - int ke = a[j+1]; - if (ko > f[j]) { - f[j+1] = f[j]; - a[j+1] = a[j]; - f[j] = ko; - a[j] = ke; - } - } - } -} - -static std::vector sortEdgeIndexByFrequency(std::vector &all) -{ - std::vector freq, unqEntries; - freq.push_back(1); - unqEntries.push_back(all[0]); - - for (std::size_t i = 1; i < all.size(); i++) { - bool milila = false; - - for (std::size_t j = 0; j < unqEntries.size(); j++) { - milila = milila || (all[i] == unqEntries[j]); - - if (all[i] == unqEntries[j]) { - freq[j] = freq[j] + 1; - } - } - if (milila == false) { - unqEntries.push_back(all[i]); - freq.push_back(1); - } - } - - sortDesWrtFreqVector(freq, unqEntries); - - return unqEntries; -} - -static std::vector numOfUniqueFaces(std::vector &ai) -{ - std::vector aiEdgeNVtx; - std::vector aiOnlyFace; - std::vector aiOnlyEdge; - std::vector aiOnlyVtx; - std::vector aiOnlyTet; - - std::vector aiUniqueFace; - std::vector FFE; - - for (size_t i = 0; i < ai.size(); i++) { - if (ai[i] < 8) aiOnlyVtx.push_back(ai[i]); - else if (ai[i] > 7 && ai[i] < 14) aiOnlyEdge.push_back(ai[i]); - else if (ai[i] > 13 && ai[i] < 20) aiOnlyFace.push_back(ai[i]); - else aiOnlyTet.push_back(ai[i]); - - } - - int faceToEdgeInd[4][4] = {{-1, 0, 1, 2}, - {0, -1, 4, 3}, - {1, 4, -1, 5}, - {2, 3, 5, -1}}; - - int edgeToFaceInd[6][2] = {{0, 1}, - {0, 2}, - {0, 3}, - {1, 3}, - {1, 2}, - {2, 3}}; - - int edgeToVtx[6][2] = {{0, 1}, - {1, 2}, - {0, 2}, - {0, 3}, - {1, 3}, - {2, 3}}; - - for (std::size_t i = 0; i < aiOnlyFace.size(); i++) { - for (std::size_t j = 0; j < aiOnlyFace.size(); j++) { - if ((i != j) && (j > i)) { - for (std::size_t k = 0; k < aiOnlyEdge.size(); k++) { - if (faceToEdgeInd[aiOnlyFace[i]-14][aiOnlyFace[j]-14] + 8 == aiOnlyEdge[k]) { - FFE.push_back(aiOnlyEdge[k]); - FFE.push_back(aiOnlyFace[j]); - FFE.push_back(aiOnlyFace[i]); - break; - } - } - break; - } - } - } - - bool hasDownVtx, alreadyIn; - - for (size_t j = 0; j < aiOnlyEdge.size(); j++) { - hasDownVtx = false; - for (int jj = 0; jj < 2; jj++) { - //hasDownVtx = false; - for (size_t ii = 0; ii < aiOnlyVtx.size(); ii++) { - hasDownVtx = hasDownVtx || (edgeToVtx[aiOnlyEdge[j]-8][jj] == aiOnlyVtx[ii] - 2); - } - } - - if (hasDownVtx == false) { - for (int i = 0; i < 2; i++) { - alreadyIn = false; - for (size_t k = 0; k < aiOnlyFace.size(); k++) { - alreadyIn = alreadyIn || (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14); - } - if (alreadyIn == false) { - aiOnlyFace.push_back(edgeToFaceInd[aiOnlyEdge[j]-8][i] + 14); - } - } - } - else { - for (int i = 0; i < 2; i++) { - for (size_t k = 0; k < aiOnlyFace.size(); k++) { - if (edgeToFaceInd[aiOnlyEdge[j]-8][i] == aiOnlyFace[k]-14) { - //aiOnlyFace.erase(aiOnlyFace.begin()+k); - } - } - } - } - } - - for (size_t j = 0; j < aiOnlyFace.size(); j++) { - aiUniqueFace.push_back(aiOnlyFace[j]); - } - - ai.clear(); - - std::vector forFaceMarking; - - // TODO: to be cleaned up - //[number of unique faces, {unique face index}, {pairs of face face coomon edge invalids}] - - if (aiUniqueFace.size() > 0 && FFE.size() >= 0) { - forFaceMarking.push_back(aiUniqueFace.size()); - for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) - ai.push_back(aiOnlyVtx[i]); - for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) - ai.push_back(aiOnlyEdge[i]); - for (std::size_t i = 0; i < aiOnlyFace.size(); i++) - ai.push_back(aiOnlyFace[i]); - for (std::size_t i = 0; i < aiOnlyTet.size(); i++) - ai.push_back(aiOnlyTet[i]); - for (std::size_t i = 0; i < aiUniqueFace.size(); i++) { - forFaceMarking.push_back(aiUniqueFace[i]); - } - for (std::size_t i = 0; i < FFE.size(); i++) - forFaceMarking.push_back(FFE[i]); - - } - else if (aiUniqueFace.size() == 0) { - forFaceMarking.push_back(0); - if (FFE.size() > 0) { - for (std::size_t i = 0; i < FFE.size(); i++) - forFaceMarking.push_back(FFE[i]); - } - for (std::size_t i = 0; i < aiOnlyVtx.size(); i++) - ai.push_back(aiOnlyVtx[i]); - for (std::size_t i = 0; i < aiOnlyEdge.size(); i++) - ai.push_back(aiOnlyEdge[i]); - for (std::size_t i = 0; i < aiOnlyFace.size(); i++) - ai.push_back(aiOnlyFace[i]); - } - return forFaceMarking; -} - -static int markAllEdges(ma::Mesh* m, ma::Entity* e, - std::vector ai, ma::Entity* edges[6]) -{ - std::vector bb; - apf::MeshEntity* edf[3]; - apf::MeshEntity* faces[4]; - ma::Downward ed; - m->getDownward(e,1,ed); - - //std::vector ai = inspectInvalidies(aiall); - std::vector faceInvalid = numOfUniqueFaces(ai); - - if (ai.size() == 0) return 0; - if (ai.size() == faceInvalid[0]) return 0; - - for (size_t ii = 0; ii < ai.size(); ii++) { - - int dim = (ai[ii]-2)/6; - int index = (ai[ii]-2) % 6; - - switch (dim) { - case 0: - { - //ma::Downward ed; - //m->getDownward(e,1,ed); - - std::vector aa = getEdgeSequenceFromInvalidVertex(m, e, index); - PCU_ALWAYS_ASSERT(index < 4); - for (size_t i = 0; i < aa.size(); i++) - bb.push_back(aa[i]); - - break; - } - - case 1: - { - //ma::Downward ed; - //m->getDownward(e,1,ed); - bb.push_back(index); - bb.push_back(index); - break; - } - //break; - case 2: - { - // if we have an invalid face, operate on its edges - //ma::Downward edf, faces; - m->getDownward(e,2,faces); - m->getDownward(faces[index],1,edf); - - for (int i = 0; i < 3; i++) { - int j = apf::findIn(ed, 6, edf[i]); - //if (j != -1) - //bb.push_back(j); - } - break; - } - //break; - case 3: - { - m->getDownward(e,1,edges); - return 6; - } - default: - fail("invalid quality tag in markEdges\n"); - break; - } - } - - int n = 0; - //std::vector allinvEdges = sortEdgeIndexByType(m, e, bb); - std::vector allinvEdges = sortEdgeIndexByFrequency(bb); - int k = 0; - - for (size_t i = 0; i < allinvEdges.size(); i++) { - if (m->getModelType(m->toModel(ed[allinvEdges[i]])) != 1) { - n++; - edges[n-1] = ed[allinvEdges[i]]; - } - } - - return n; -} - -static int markEdges(ma::Mesh* m, ma::Entity* e, int tag, - ma::Entity* edges[6]) -{ - if ( tag <= 1 ) // if its valid, or not checked, don't worry about it - return 0; - int dim = (tag-2)/6; - int index = (tag-2) % 6; - int n = 0; - int md = m->getDimension(); - switch (dim) { - case 0: - { - // if we have an invalid vertex, operate on its edges - ma::Downward ed; - m->getDownward(e,1,ed); - n = md; - - if(md == 2){ - edges[0] = ed[index]; - edges[1] = ed[(index+2) % 3]; - } else { - PCU_ALWAYS_ASSERT(index < 4); - edges[0] = ed[tetVertEdges[index][0]]; - edges[1] = ed[tetVertEdges[index][1]]; - edges[2] = ed[tetVertEdges[index][2]]; - } - break; - } - case 1: - { - // if we have a single invalid edge, operate on it - ma::Downward ed; - m->getDownward(e,1,ed); - edges[0] = ed[index]; - n = 1; - break; - } - case 2: - { - // if we have an invalid face, operate on its edges - ma::Downward ed, faces; - m->getDownward(e,2,faces); - m->getDownward(faces[index],1,ed); - n = 3; - edges[0] = ed[0]; - edges[1] = ed[1]; - edges[2] = ed[2]; - break; - } - case 3: - { - m->getDownward(e,1,edges); - n = 6; - break; - } - default: - fail("invalid quality tag in markEdges\n"); - break; - } - - return n; -} - -<<<<<<< HEAD -static int markUniqueFaces(ma::Mesh* m, ma::Entity* e, std::vector ai, - ma::Entity* faces[4]) -{ - - if (ai.size() == 0) return 0; - std::vector faceInvalid = numOfUniqueFaces(ai); - int n = 0; - - ma::Downward fc; - m->getDownward(e, 2, fc); - ma::Downward ed; - m->getDownward(e, 1, ed); - if (faceInvalid[0] > 0) { - for (std::size_t i = 1; i < faceInvalid[0]+1; i++) { - int index = (faceInvalid[i] -2) % 6; - int md = m->getDimension(); - - if (m->getModelType(m->toModel(fc[index])) == 3) { - faces[n] = fc[index]; - n++; - } - } - } - return n; -======= -static apf::Vector3 getTriOrientation(apf::Mesh2* m, apf::MeshEntity* tri) -{ - PCU_ALWAYS_ASSERT(m->getType(tri) == apf::Mesh::TRIANGLE); - - apf::MeshEntity* vs[3]; - m->getDownward(tri, 0, vs); - apf::Vector3 ps[3]; - for (int i = 0; i < 3; i++) { - m->getPoint(vs[i], 0, ps[i]); - } - apf::Vector3 e0 = ps[1] - ps[0]; - apf::Vector3 e1 = ps[2] - ps[1]; - apf::Vector3 n0 = apf::cross(e0, e1); - return n0/n0.getLength(); -} - -static int getEdgeIdInSimplex(apf::Mesh2* m, apf::MeshEntity* tri, apf::MeshEntity* edge) -{ - PCU_ALWAYS_ASSERT(m->getType(tri) == apf::Mesh::TRIANGLE); - PCU_ALWAYS_ASSERT(m->getType(edge) == apf::Mesh::EDGE); - apf::MeshEntity* es[3]; - m->getDownward(tri, 1, es); - return apf::findIn(es, 3, edge); ->>>>>>> develop -} - -class EdgeSwapper : public ma::Operator -{ -public: - EdgeSwapper(Adapt* a) - { - adapter = a; - mesh = a->mesh; - edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; - simplex = 0; - edgeSwap = ma::makeEdgeSwap(a); - md = mesh->getDimension(); - ne = ns = 0; - } - virtual ~EdgeSwapper() - { - delete edgeSwap; - } - virtual int getTargetDimension() {return md;} - virtual bool shouldApply(ma::Entity* e) - { - std::vector ai = crv::getAllInvalidities(mesh, e); - mesh->getDownward(e, 1, edges); - int niv = ai.size(); - ne = 0; - if (niv != 0) { - ne = markAllEdges(mesh, e, ai, edges); - simplex = e; - } - return (ne > 0); - /* - int tag = crv::getTag(adapter,e); - ne = markEdges(mesh,e,tag,edges); - - simplex = e; - return (ne > 0); - */ - } - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(edges,ne); - } - virtual void apply() - { - for (int i = 0; i < ne; ++i){ - if (edgeSwap->run(edges[i])){ - ns++; - // crv::clearTag(adapter,simplex); - ma::clearFlag(adapter,edges[i],ma::COLLAPSE | ma::BAD_QUALITY); - break; - } - } - } -private: - Adapt* adapter; - ma::Mesh* mesh; - ma::Entity* simplex; - ma::Entity* edges[6]; - ma::EdgeSwap* edgeSwap; - int md; - int ne; -public: - int ns; -}; - -class EdgeReshaper : public ma::Operator -{ -public: - EdgeReshaper(Adapt* a) - { - adapter = a; - mesh = a->mesh; - edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; - simplex = 0; - md = mesh->getDimension(); - ne = nr = 0; - qual = makeQuality(mesh,2); - } - virtual ~EdgeReshaper() - { - delete qual; - } - virtual int getTargetDimension() {return md;} - virtual bool shouldApply(ma::Entity* e) - { - int tag = crv::getTag(adapter,e); - - ne = markEdges(mesh,e,tag,edges); - simplex = e; - return (ne > 0); - } - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(edges,ne); - } - virtual void apply() - { - for (int i = 0; i < ne; ++i){ - if (!isBoundaryEntity(mesh,edges[i]) && - repositionEdge(edges[i])){ - nr++; - crv::clearTag(adapter,simplex); - ma::clearFlag(adapter,edges[i],ma::COLLAPSE | ma::BAD_QUALITY); - break; - } - } - } -private: - /** \brief reposition second order edge control point based on XJ Luo's - thesis and bezier.tex in SCOREC/docs repo, only works for second order */ - bool repositionEdge(ma::Entity* edge) - { - // lets assume we have an edge we want to fix - // only support second order for now - int P = mesh->getShape()->getOrder(); - if (P != 2) return false; - - ma::Entity* verts[4]; - ma::Entity* edges[6]; - - ma::Vector pivotPoint; - ma::Vector edgeVectors[3]; - mesh->getDownward(simplex,0,verts); - mesh->getDownward(simplex,1,edges); - - // pick a pivotVert, the vertex with the worse jacobian determinant - ma::Entity* pivotVert; - int pivotIndex; - { - apf::MeshElement* me = apf::createMeshElement(mesh,simplex); - - ma::Entity* edgeVerts[2]; - mesh->getDownward(edge,0,edgeVerts); - apf::Matrix3x3 J; - pivotIndex = apf::findIn(verts,4,edgeVerts[0]); - PCU_ALWAYS_ASSERT(pivotIndex >= 0); - - ma::Vector xi; - if (md == 3) - xi = crv::elem_vert_xi[apf::Mesh::TET][pivotIndex]; - else if (md == 2) - xi = crv::elem_vert_xi[apf::Mesh::TRIANGLE][pivotIndex]; - else - PCU_ALWAYS_ASSERT(0); - - apf::getJacobian(me,xi,J); - - double j; - if (md == 3) - j = apf::getJacobianDeterminant(J,3); - else if (md == 2) - j = apf::getJacobianDeterminant(J,2); - else - PCU_ALWAYS_ASSERT(0); - - pivotVert = edgeVerts[0]; - - int index = apf::findIn(verts,4,edgeVerts[1]); - PCU_ALWAYS_ASSERT(index >= 0); - if (md == 3) - xi = crv::elem_vert_xi[apf::Mesh::TET][index]; - else if (md == 2) - xi = crv::elem_vert_xi[apf::Mesh::TRIANGLE][index]; - else - PCU_ALWAYS_ASSERT(0); - - - apf::getJacobian(me,xi,J); - - if ((md == 3 && apf::getJacobianDeterminant(J,3) < j) || - (md == 2 && apf::getJacobianDeterminant(J,2) < j)){ - pivotVert = edgeVerts[1]; - pivotIndex = index; - } - apf::destroyMeshElement(me); - } - - mesh->getPoint(pivotVert,0,pivotPoint); - - // local, of edges around vert, [0,2] - int edgeIndex = 0; - - for (int i = 0; i < md; ++i){ - // theres only one point, so reuse this... - if (md == 3) - edgeVectors[i] = ma::getPosition(mesh,edges[tetVertEdges[pivotIndex][i]]) - - pivotPoint; - else if (md == 2) - edgeVectors[i] = ma::getPosition(mesh,edges[triVertEdges[pivotIndex][i]]) - - pivotPoint; - else - PCU_ALWAYS_ASSERT(0); - - if ((md == 3 && edges[tetVertEdges[pivotIndex][i]] == edge) || - (md == 2 && edges[triVertEdges[pivotIndex][i]] == edge)) - edgeIndex = i; - } - - PCU_ALWAYS_ASSERT(edgeIndex >= 0); - - ma::Entity* edge1; - ma::Entity* edge2; - // For 3D meshes get the other 2 edges to form a reflection plane - // Note that the order does not matter - if (md == 3) { - edge1 = edges[tetVertEdges[pivotIndex][(edgeIndex+1)%3]]; - edge2 = edges[tetVertEdges[pivotIndex][(edgeIndex+2)%3]]; - } - // For 2D meshes the invalid edge has to be reflected wrt the - // other edge connected to the pivot vertex - // So let: - // edge1 = edge - // edge2 = other edge - else if (md == 2) { - edge1 = edge; - edge2 = edges[triVertEdges[pivotIndex][(edgeIndex+1)%2]]; - } - - - if (md == 3) { - // Find the normal to the plane of edge1 and edge2 by first computing the edge - // tangents at the pivotVert - ma::Vector t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - ma::Vector t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - ma::Vector normal = apf::cross(t1, t2); - double length = normal.getLength(); - double validity = edgeVectors[edgeIndex]*normal; - - if(validity > 1e-10) - return false; - ma::Vector oldPoint = ma::getPosition(mesh,edge); - apf::Adjacent adjacent; - mesh->getAdjacent(edge,3,adjacent); - - /* mirror the vector edgeVectors[edgeIndex] with respect to the plane - * perpendicular to the normal. The parameter alpha scales the normal - * (to the plane) component of the mirrored vector. - */ - double alpha = 0.5; - - ma::Vector newPoint = pivotPoint + edgeVectors[edgeIndex] - - normal * (normal * edgeVectors[edgeIndex]) * (1 + alpha) / length / length; - - mesh->setPoint(edge,0,newPoint); - - for (std::size_t i = 0; i < adjacent.getSize(); ++i){ - if (qual->checkValidity(adjacent[i]) < 0){ - mesh->setPoint(edge,0,oldPoint); - return false; - } - } - } - else if (md == 2) { - // edge1 which should be the same as edge needs to be modified - PCU_ALWAYS_ASSERT(edge1 == edge); - // get the orientation of the simplex using its vertex coordinates - apf::Vector3 normal = getTriOrientation(mesh, simplex); - int edge1Idx, edge2Idx; - edge1Idx = getEdgeIdInSimplex(mesh, simplex, edge1); - PCU_ALWAYS_ASSERT(edge1Idx > -1); - edge2Idx = getEdgeIdInSimplex(mesh, simplex, edge2); - PCU_ALWAYS_ASSERT(edge2Idx > -1); - ma::Vector t1 = ma::Vector(0.0, 0.0, 0.0); - ma::Vector t2 = ma::Vector(0.0, 0.0, 0.0); - switch(pivotIndex) { - case 0: - if (edge1Idx == 0 && edge2Idx == 2) { - t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else if (edge1Idx == 2 && edge2Idx == 0) { - t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else - PCU_ALWAYS_ASSERT(0); - break; - case 1: - if (edge1Idx == 1 && edge2Idx == 0) { - t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else if (edge1Idx == 0 && edge2Idx == 1) { - t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else - PCU_ALWAYS_ASSERT(0); - break; - case 2: - if (edge1Idx == 2 && edge2Idx == 1) { - t1 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else if (edge1Idx == 1 && edge2Idx == 2) { - t1 = computeEdgeTangentAtVertex(mesh, edge2, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - t2 = computeEdgeTangentAtVertex(mesh, edge1, pivotVert, ma::Matrix(1,0,0,0,1,0,0,0,1)); - } - else - PCU_ALWAYS_ASSERT(0); - break; - default: - break; - } - - // At this point if t1xt2 is in the same direction as the normal the triangle is valid - apf::Vector3 normal2 = apf::cross(t1, t2); - if (normal * normal2 > 0) - return false; - - ma::Vector oldPoint = ma::getPosition(mesh,edge); - apf::Adjacent adjacent; - mesh->getAdjacent(edge,md,adjacent); - - /* mirror the vector edgeVectors[edgeIndex] with respect the other edge2 */ - double alpha = 0.5; - - apf::MeshEntity* edge1OppV = 0; - apf::MeshEntity* edge2OppV = 0; - apf::MeshEntity* vs[2]; - - mesh->getDownward(edge1, 0, vs); - edge1OppV = (vs[0] == pivotVert) ? vs[1] : vs[0]; - PCU_ALWAYS_ASSERT(edge1OppV); - - mesh->getDownward(edge2, 0, vs); - edge2OppV = (vs[0] == pivotVert) ? vs[1] : vs[0]; - PCU_ALWAYS_ASSERT(edge2OppV); - - apf::Vector3 L = ma::getPosition(mesh, edge1OppV) - ma::getPosition(mesh, pivotVert); - apf::Vector3 refL = ma::getPosition(mesh, edge2OppV) - ma::getPosition(mesh, pivotVert); - refL = refL/refL.getLength(); // refL is unit - - // get the part of L that is perpendicular to refL - apf::Vector3 x = L - refL * (refL * L); - // make sure x is in the plane of edge1 and edge2 - x = x - normal * (normal * x); - apf::Vector3 deltaX = L - x * alpha * 2; - ma::Vector newPoint = pivotPoint + deltaX; - - mesh->setPoint(edge,0,newPoint); - for (std::size_t i = 0; i < adjacent.getSize(); ++i){ - if (qual->checkValidity(adjacent[i]) < 0){ - mesh->setPoint(edge,0,oldPoint); - return false; - } - } - } - else - PCU_ALWAYS_ASSERT(0); - - return true; - } - Adapt* adapter; - ma::Mesh* mesh; - Quality* qual; - ma::Entity* simplex; - ma::Entity* edges[6]; - int md; - int ne; -public: - int nr; -}; - -class FaceOptimizer : public ma::Operator -{ -public: - FaceOptimizer(Adapt* a) { - adapter = a; - mesh = a->mesh; - faces[0] = faces[1] = faces[2] = faces[3] = 0; - simplex = 0; - md = mesh->getDimension(); - numf = 0; - ns = 0; - nf = 0; - } - ~FaceOptimizer() { - } - virtual int getTargetDimension() {return md;} - virtual bool shouldApply(ma::Entity* e) { - - std::vector ai = crv::getAllInvalidities(mesh, e); - int niv = ai.size(); - mesh->getDownward(e, 2, faces); - numf = 0; - if (niv != 0) { - numf = markUniqueFaces(mesh, e, ai, faces); - simplex = e; - } - return (numf > 0); - } - - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(faces, numf); - } - - virtual void apply(){ - int invaliditySize = 0; - //mesh->getDownward(simplex, 2, faces); - if (numf == 0) return; - for (int i = 0; i < numf; i++ ) { - if (mesh->getModelType(mesh->toModel(faces[i])) != 3) continue; - //CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, DETJ); - CrvFaceOptim *cfo = new CrvFaceOptim(adapter, faces[i], simplex, NIJK); - cfo->setMaxIter(100); - cfo->setTol(1e-8); - if (cfo->run(invaliditySize)) { - if (invaliditySize < 1) { - ns++; - delete cfo; - break; - } - } - else { - nf++; - if (invaliditySize < 1) { - delete cfo; - break; - } - } - delete cfo; - } - } -protected: - Adapt* adapter; - ma::Mesh* mesh; -public: - ma::Entity* faces[4]; - ma::Entity* simplex; - int numf; - int md; - int ns; - int nf; -}; - -class EdgeOptimizer : public ma::Operator -{ -public: - EdgeOptimizer(Adapt* a) { - adapter = a; - mesh = a->mesh; - edges[0] = edges[1] = edges[2] = edges[3] = edges[4] = edges[5] = 0; - simplex = 0; - md = mesh->getDimension(); - ns = 0; - nf = 0; - ne = 0; - } - ~EdgeOptimizer() { - } - virtual int getTargetDimension() {return md;} - virtual bool shouldApply(ma::Entity* e) { - std::vector ai = crv::getAllInvalidities(mesh, e); - mesh->getDownward(e, 1, edges); - int niv = ai.size(); - ne = 0; - if (niv != 0) { - ne = markAllEdges(mesh, e, ai, edges); - simplex = e; - } - return (ne > 0); - } - - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(edges, ne); - } - - virtual void apply() { - if (ne == 0) return; - for (int i = 0; i < ne; i++ ) { - int invaliditySize = 0; - bool hasDecreased = false; - CrvEntityOptim* ceo; - - if (mesh->getModelType(mesh->toModel(edges[i])) == 3) { - //ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, DETJ); - ceo = new CrvInternalEdgeOptim(adapter, edges[i], simplex, NIJK); - } - else { - //ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, DETJ); - ceo = new CrvBoundaryEdgeOptim(adapter, edges[i], simplex, NIJK); - } - - ceo->setMaxIter(100); - ceo->setTol(1e-8); - - if (ceo->run(invaliditySize)) { - ns++; - if (invaliditySize < 1) { - break; - delete ceo; - } - } - else { - nf++; - if (invaliditySize < 1) { - delete ceo; - break; - } - } - delete ceo; - } - } -protected: - Adapt* adapter; - ma::Mesh* mesh; - ma::Entity* edge; -public: - int ne; - int md; - ma::Entity* edges[6]; - ma::Entity* simplex; - int ns; - int nf; -}; - -static bool isCornerTriAngleLargeMetric(crv::Adapt *a, - ma::Entity* tri, int index) -{ - ma::Mesh* m = a->mesh; - // get downward vertexes - ma::Entity* down[3]; - m->getDownward(tri, 0, down); - // first get the size field at the center of the tri - ma::SizeField* sf = a->sizeField; - apf::Matrix3x3 Q; - apf::MeshElement* element = apf::createMeshElement(m, tri); - sf->getTransform(element, apf::Vector3(1./3.,1./3.,1./3.), Q); - ma::Vector cornerNormal = computeFaceNormalAtVertex(m, tri, down[index], Q); - apf::destroyMeshElement(element); - - ma::Vector normal = ma::getTriNormal(m,tri); - - // this statement is not exactly a fair comparison, but at least gives - // some level of control over what is considered an invalid angle - // an angle is "too large" if the dot product between the corner triangle - // and the triangle formed by its vertices is negative - if (cornerNormal*normal < a->input->validQuality) - return true; - - return false; -} - -/* Checks if an angle of a triangle is large (>= 180 degrees) - * which can be caused by two edges on the boundary curved to it - * - */ -static ma::Entity* isLargeAngleTriMetric(crv::Adapt* a, ma::Entity* e) -{ - ma::Mesh* m = a->mesh; - ma::Entity* edges[3]; - m->getDownward(e,1,edges); - for (int i = 0; i < 3; ++i) - { - ma::Entity* e0 = edges[i]; - ma::Entity* e1 = edges[(i+1) % 3]; - if(isBoundaryEntity(m,e0) && isBoundaryEntity(m,e1)) - { - // TODO: This conditions seems problematic. Think - // about a better version. My intuition is that the - // following to edges has to be marked - // (i+1)%3 and i%3 - if(isCornerTriAngleLargeMetric(a,e,(i+1) % 3)){ - ma::Entity* edge = edges[(i+2) % 3]; - if(!ma::getFlag(a,edge,ma::SPLIT) && !isBoundaryEntity(m,edge)){ - return edge; - } - } - } - } - return 0; -} - -/* Checks if an angle of a tet is large (>= 180 degrees) - * which can be caused by two edges on the boundary curved to it - * - * An analytic approach, looking at the control point net of points - * by comparing surface normals of each pair of control net points - * adjacent to the triangle is an incredibly complex ordering exercise - * Rather than attempt to do the ordering, sampling the Jacobian at - * P+1 points is used. A validity check on this edge could also be used - */ - -static ma::Entity* isLargeAngleTetMetric(crv::Adapt* a, ma::Entity* e) -{ - ma::Mesh* m = a->mesh; - // first get the size field at the center of the entity e - ma::SizeField* sf = a->sizeField; - apf::Matrix3x3 Q; - apf::MeshElement* element = apf::createMeshElement(m, e); - - sf->getTransform(element, apf::Vector3(0.25,0.25,0.25), Q); - - apf::destroyMeshElement(element); - - ma::Entity* edges[6]; - ma::Entity* faces[4]; - m->getDownward(e,1,edges); - m->getDownward(e,2,faces); - - - // find edge that matters - int index = -1; - for (int i = 0; i < 6; ++i){ - if(isBoundaryEntity(m,faces[edgeFaces[i][0]]) && - isBoundaryEntity(m,faces[edgeFaces[i][1]])){ - index = i; - break; - } - } - if(index < 0) return 0; - - if(!isBoundaryEntity(m,edges[index])) return 0; - - - ma::Entity* leftFace = faces[edgeFaces[index][0]]; - ma::Entity* rightFace = faces[edgeFaces[index][1]]; - double cosAngle = apf::computeCosAngleInTet(m, e, leftFace, rightFace, Q); - - ma::Entity* edge = 0; - if (cosAngle < -0.9) - edge = edges[oppEdges[index]]; - - return edge; -} - - -// BAD_QUALITY flag is used on edges to identify them -// as splits for quality, rather than for size refinement -// These two functions handle two seperate situations - -// First, triangles are looked at to see if they have an angle > 180 degrees -// There is also a check for the weird situation described above -// Second, tets are looked at to see if they have two faces on the boundary -// where the jacobian determinant is negative along the shared edge, -// indicative of a large angle (curving around a cylinder or sphere). - -static int markEdgesOppLargeAnglesTri(Adapt* a) -{ - int count = 0; - int prev_count; - - ma::Mesh* m = a->mesh; - ma::Entity* e; - - do { - ma::Iterator* it = m->begin(2); - prev_count = count; - while ((e = m->iterate(it))) - { - if(!hasTwoEntitiesOnBoundary(m,e,1)) continue; - ma::Entity* edge = isLargeAngleTriMetric(a,e); - if (edge) - { - PCU_ALWAYS_ASSERT(m->getType(edge) == 1); - ma::setFlag(a,edge,ma::SPLIT); - ma::setFlag(a,edge,ma::BAD_QUALITY); - if (a->mesh->isOwned(edge)) - ++count; - } - } - m->end(it); - } while(count > prev_count); - return PCU_Add_Long(count); -} - -static int markEdgesOppLargeAnglesTet(Adapt* a) -{ - int count = 0; - int prev_count; - - ma::Mesh* m = a->mesh; - ma::Entity* e; - - do { - ma::Iterator* it = m->begin(3); - prev_count = count; - while ((e = m->iterate(it))) - { - ma::Entity* edge = isLargeAngleTetMetric(a,e); - if (edge && !ma::getFlag(a,edge,ma::SPLIT)) - { - PCU_ALWAYS_ASSERT(m->getType(edge) == 1); - ma::setFlag(a,edge,ma::SPLIT); - ma::setFlag(a,edge,ma::BAD_QUALITY); - if (a->mesh->isOwned(edge)) - ++count; - } - } - m->end(it); - } while(count > prev_count); - return PCU_Add_Long(count); -} - -/* The whole idea is to do the quality check once, - * and then use the results to mark edges, etc for - * fixing - */ - -static int markEdgesToFix(Adapt* a, int flag) -{ - // do a invalidity check first - int invalid = markInvalidEntities(a); - if ( !invalid ) - return 0; - int count = 0; - - ma::Mesh* m = a->mesh; - ma::Entity* e; - - // markEdges could have upto 6 edges marked!!! - ma::Entity* edges[6]; - ma::Iterator* it = m->begin(m->getDimension()); - - while ((e = m->iterate(it))) - { - //int tag = crv::getTag(a,e); - //int n = markEdges(m,e,tag,edges); - - std::vector ai = crv::getAllInvalidities(m, e); - int niv = ai.size(); - - if (niv != 0) { - int n = markAllEdges(m, e, ai, edges); - for (int i = 0; i < n; ++i){ - ma::Entity* edge = edges[i]; - PCU_ALWAYS_ASSERT(edge); - - if (edge && !ma::getFlag(a,edge,flag)) { - ma::setFlag(a,edge,flag); - if (a->mesh->isOwned(edge)) - ++count; - } - } - } - } - m->end(it); - - return PCU_Add_Long(count); -} - -/* -static int markFacesToFix(Adapt* a, int flag) -{ - int invalid = markInvalidEntities(a); - if (!invalid) - return 0; - int count = 0; - - ma::Mesh* m = a->mesh; - ma::Entity* e; - - ma::Entity* faces[4]; - ma::Iterator* it = m->begin(m->getDimension()); - while ((e = m->iterate(it))) - { - std::vector ai = crv::getAllInvalidities(m, e); -// int tag = crv::getTag(a, e); -// int n = markFaces(m, e, tag, faces); - int n = markUniqueFaces(m, e, ai, faces); - for (int i = 0; i < n; i++) { - ma::Entity* face = faces[i]; - PCU_ALWAYS_ASSERT(face); - if (face && !ma::getFlag(a, face, flag)) { - if (m->getModelType(m->toModel(face)) != 2) - ma::setFlag(a, face, flag); - if (a->mesh->isOwned(face)) - count++; - } - } - } - m->end(it); - - return PCU_Add_Long(count); -} -*/ -int fixLargeBoundaryAngles(Adapt* a) -{ - double t0 = PCU_Time(); - int count = markEdgesOppLargeAnglesTet(a); - count += markEdgesOppLargeAnglesTri(a); - - if ( ! count){ - return 0; - } - splitEdges(a); - double t1 = PCU_Time(); - ma::print("split %d boundary edges with " - "large angles in %f seconds",count,t1-t0); - return 0; -} - -static void collapseInvalidEdges(Adapt* a) -{ - double t0 = PCU_Time(); - ma::Mesh* m = a->mesh; - int maxDimension = m->getDimension(); - PCU_ALWAYS_ASSERT(checkFlagConsistency(a,1,ma::COLLAPSE)); - int successCount = 0; - for (int modelDimension=1; modelDimension <= maxDimension; ++modelDimension) - { - checkAllEdgeCollapses(a,modelDimension); - findIndependentSet(a); - successCount += ma::collapseAllEdges(a, modelDimension); - } - successCount = PCU_Add_Long(successCount); - double t1 = PCU_Time(); - ma::print("Collapsed %d bad edges " - "in %f seconds",successCount, t1-t0); -} - -static void swapInvalidEdges(Adapt* a) -{ - double t0 = PCU_Time(); - EdgeSwapper es(a); - ma::applyOperator(a,&es); - double t1 = PCU_Time(); - ma::print("Swapped %d bad edges " - "in %f seconds",es.ns, t1-t0); -} - -static void repositionInvalidEdges(Adapt* a) -{ - double t0 = PCU_Time(); - EdgeReshaper es(a); - ma::applyOperator(a,&es); - double t1 = PCU_Time(); - ma::print("Repositioned %d bad edges " - "in %f seconds",es.nr, t1-t0); -} - -static void optimizeInvalidEdges(Adapt* a) -{ - double t0 = PCU_Time(); - EdgeOptimizer eo(a); - ma::applyOperator(a,&eo); - double t1 = PCU_Time(); - ma::print("Optimized %d bad edges, failed %d edges " - "in %f seconds",eo.ns, eo.nf, t1-t0); -} - -static void optimizeInvalidFaces(Adapt* a) -{ - double t0 = PCU_Time(); - FaceOptimizer fo(a); - ma::applyOperator(a, &fo); - double t1 = PCU_Time(); - ma::print("Optimized %d bad faces, failed %d faces " - "in %f seconds", fo.ns, fo.nf, t1-t0); -} - -int fixInvalidFaces(Adapt* a) -{ - - ma::Mesh* mesh = a->mesh; - apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); - apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); - apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); - - apf::MeshEntity* ent; - apf::MeshIterator* it; - - it = mesh->begin(1); - int count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(edge_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(2); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(face_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(3); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(tet_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - /* optimizeInvalidFaces(a); */ - - mesh->removeNumbering(edge_num); - mesh->removeNumbering(face_num); - mesh->removeNumbering(tet_num); - - return 0; -} - -int fixInvalidEdges(Adapt* a) -{ - - ma::Mesh* mesh = a->mesh; - apf::Numbering* edge_num = apf::createNumbering(mesh, "debug_num_edge", apf::getConstant(1), 1); - apf::Numbering* face_num = apf::createNumbering(mesh, "debug_num_face", apf::getConstant(2), 1); - apf::Numbering* tet_num = apf::createNumbering(mesh, "debug_num_tet", apf::getConstant(3), 1); - - apf::MeshEntity* ent; - apf::MeshIterator* it; - - it = mesh->begin(1); - int count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(edge_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(2); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(face_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - it = mesh->begin(3); - count = 0; - while( (ent = mesh->iterate(it)) ) { - apf::number(tet_num, ent, 0, 0, count); - count++; - } - mesh->end(it); - - if(a->mesh->getShape()->getOrder() == 2) - repositionInvalidEdges(a); - else - optimizeInvalidEdges(a); - - mesh->removeNumbering(edge_num); - mesh->removeNumbering(face_num); - mesh->removeNumbering(tet_num); -/* - int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - if (! count){ - return 0; - } - - collapseInvalidEdges(a); - swapInvalidEdges(a); -*/ - return 0; -} - -int fixInvalidEdgesCollapseAndSwap(Adapt* a) -{ - int count = markEdgesToFix(a,ma::BAD_QUALITY | ma::COLLAPSE ); - if (! count){ - return 0; - } - - collapseInvalidEdges(a); - swapInvalidEdges(a); - - return count; -} - -struct IsBadCrvQuality : public ma::Predicate -{ - IsBadCrvQuality(Adapt* a_):a(a_) - { - sh = crv::getShapeHandler(a); - } - ~IsBadCrvQuality() - { - delete sh; - } - bool operator()(apf::MeshEntity* e) - { - return sh->getQuality(e) < a->input->goodQuality; - } - Adapt* a; - ma::ShapeHandler* sh; -}; - -int markCrvBadQuality(Adapt* a) -{ - IsBadCrvQuality p(a); - return ma::markEntities(a, a->mesh->getDimension(), p, - ma::BAD_QUALITY, ma::OK_QUALITY); -} - - -int fixLargeAngles(Adapt *a) -{ - if (a->mesh->getDimension() == 3) { - CrvLargeAngleTetFixer tetFixer(a); - applyOperator(a, &tetFixer); - /* return tetFixer.getSuccessCount(); */ - } - else { - CrvLargeAngleTriFixer triFixer(a); - applyOperator(a, &triFixer); - /* return triFixer.getSuccessCount(); */ - } - return 0; -} - -static int fixShortEdgeElements(Adapt* a) -{ - CrvShortEdgeFixer fixer(a); - applyOperator(a,&fixer); - return fixer.nr; -} - -void fixCrvElementShapes(Adapt* a) -{ - if ( ! a->input->shouldFixShape) - return; - a->input->shouldForceAdaptation = true; - double t0 = PCU_Time(); - int count = markCrvBadQuality(a); - int originalCount = count; - int prev_count; - int i = 0; - do { - if ( ! count) - break; - prev_count = count; - fixLargeAngles(a); // update this - /* int numOpSuccess = fixLargeAngles(a); // update this */ - /* PCU_Add_Ints(&numOpSuccess,1); */ - /* if (PCU_Comm_Self() == 0) */ - /* lion_oprint(1,"==> %d large angle fix operations succeeded.\n", numOpSuccess); */ - markCrvBadQuality(a); - fixShortEdgeElements(a); // update this - /* int numEdgeRemoved = fixShortEdgeElements(a); // update this */ - /* PCU_Add_Ints(&numEdgeRemoved,1); */ - /* if (PCU_Comm_Self() == 0) */ - /* lion_oprint(1,"==> %d edges removal operations succeeded.\n", numEdgeRemoved); */ - //fixInvalidFaces(a); - count = markCrvBadQuality(a); - ++i; - } while(count < prev_count && i < 6); // the second conditions is to make sure this does not take long - double t1 = PCU_Time(); - ma::print("bad shapes down from %d to %d in %f seconds", - originalCount,count,t1-t0); - a->input->shouldForceAdaptation = false; -} - -}