From aac562093153670afa6f13c95fe6e3eff52c6da4 Mon Sep 17 00:00:00 2001 From: Aiden Woodruff Date: Tue, 4 Feb 2025 11:19:34 -0500 Subject: [PATCH 001/181] add aniso_ma_test2 - test/aniso_ma_test2.cc: copy from aniso_ma_test but create a uniform anisotropic sizefield with runtime parameters. - test/CMakeLists.txt: add aniso_ma_test2. - test/testing.cmake: add aniso_ma2 to run aniso_ma_test2. Signed-off-by: Aiden Woodruff --- test/CMakeLists.txt | 1 + test/aniso_ma_test2.cc | 62 ++++++++++++++++++++++++++++++++++++++++++ test/testing.cmake | 10 +++++++ 3 files changed, 73 insertions(+) create mode 100644 test/aniso_ma_test2.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e0c303870..1b332701c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -168,6 +168,7 @@ test_exe_func(xgc_split xgc_split.cc) test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) +test_exe_func(aniso_ma_test2 aniso_ma_test2.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) diff --git a/test/aniso_ma_test2.cc b/test/aniso_ma_test2.cc new file mode 100644 index 000000000..fe99cf8a9 --- /dev/null +++ b/test/aniso_ma_test2.cc @@ -0,0 +1,62 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m, double sf1, double sf2) : + mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + { + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m, lower, upper); + } + virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) + { + double h = average/sizeFactor1; + H = ma::Vector(h, h, h/sizeFactor2); + R = ma::Matrix( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + } + private: + ma::Mesh* mesh; + double sizeFactor1, sizeFactor2, average; + ma::Vector lower, upper; +}; + +int main(int argc, char* argv[]) { + if (argc != 5) { + std::cerr << "Usage: " << argv[0] << + " " << std::endl; + return 1; + } + const char* modelFile = argv[1]; + const char* meshFile = argv[2]; + double sizeFactor1 = std::atof(argv[3]), sizeFactor2 = std::atof(argv[4]); + MPI_Init(&argc, &argv); + pcu::PCU *PCUObj = new pcu::PCU(MPI_COMM_WORLD); + lion_set_verbosity(1); + gmi_register_mesh(); + ma::Mesh* m = apf::loadMdsMesh(modelFile, meshFile, PCUObj); + m->verify(); + apf::writeVtkFiles("aniso_ma_test2_before",m); + AnIso sf(m, sizeFactor1, sizeFactor2); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + ma::adapt(in); + m->verify(); + apf::writeVtkFiles("aniso_ma_test2_after",m); + m->destroyNative(); + apf::destroyMesh(m); + delete PCUObj; + MPI_Finalize(); +} + diff --git a/test/testing.cmake b/test/testing.cmake index 084bbb309..47507bdd8 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -328,6 +328,11 @@ if(ENABLE_ZOLTAN) "${MESHES}/cube/cube.dmg" "${MESHES}/cube/pumi670/cube.smb" "0") + mpi_test(aniso_ma2 1 + ./aniso_ma_test + "${MESHES}/cube/cube.dmg" + "${MESHES}/cube/pumi670/cube.smb" + "1" "8") mpi_test(aniso_ma_serial_log_interpolation 1 ./aniso_ma_test "${MESHES}/cube/cube.dmg" @@ -345,6 +350,11 @@ if(ENABLE_ZOLTAN) set_tests_properties(ma_2dLayersOff PROPERTIES PASS_REGULAR_EXPRESSION "number of triangle 18698") endif() +mpi_test(aniso_ma2 1 + ./aniso_ma_test2 + "${MESHES}/cube/cube.dmg" + "${MESHES}/cube/pumi670/cube.smb" + "1" "8") mpi_test(tet_serial 1 ./tetrahedronize "${MDIR}/pipe.${GXT}" From 3eebeb4d82d520be3e886afb16594d9e3f6cad31 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 13 Mar 2025 16:04:29 -0400 Subject: [PATCH 002/181] aniso ma test 2 changes --- test/aniso_ma_test2.cc | 10 ++++++++-- test/testing.cmake | 5 ----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/test/aniso_ma_test2.cc b/test/aniso_ma_test2.cc index fe99cf8a9..3fc4df947 100644 --- a/test/aniso_ma_test2.cc +++ b/test/aniso_ma_test2.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -34,9 +35,9 @@ class AnIso : public ma::AnisotropicFunction }; int main(int argc, char* argv[]) { - if (argc != 5) { + if (argc != 6) { std::cerr << "Usage: " << argv[0] << - " " << std::endl; + " " << std::endl; return 1; } const char* modelFile = argv[1]; @@ -51,9 +52,14 @@ int main(int argc, char* argv[]) { apf::writeVtkFiles("aniso_ma_test2_before",m); AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + // in->shouldFixShape = false; + // in->shouldCoarsen = false; + // in->shouldSnap = false; + // in->shouldCleanupLayer = false; ma::adapt(in); m->verify(); apf::writeVtkFiles("aniso_ma_test2_after",m); + m->writeNative(argv[5]); m->destroyNative(); apf::destroyMesh(m); delete PCUObj; diff --git a/test/testing.cmake b/test/testing.cmake index 47507bdd8..721b3ba61 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -350,11 +350,6 @@ if(ENABLE_ZOLTAN) set_tests_properties(ma_2dLayersOff PROPERTIES PASS_REGULAR_EXPRESSION "number of triangle 18698") endif() -mpi_test(aniso_ma2 1 - ./aniso_ma_test2 - "${MESHES}/cube/cube.dmg" - "${MESHES}/cube/pumi670/cube.smb" - "1" "8") mpi_test(tet_serial 1 ./tetrahedronize "${MDIR}/pipe.${GXT}" From e9ca0db9149b478b7a5eddec677940bdf27e2e83 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 19 Mar 2025 21:16:38 -0400 Subject: [PATCH 003/181] coarsen test --- ma/maCoarsen.cc | 66 ++++++++++++++++++++++++++ ma/maCoarsen.h | 1 + test/CMakeLists.txt | 1 + test/aniso_ma_test2.cc | 7 +++ test/coarsen.cc | 103 +++++++++++++++++++++++++++++++++++++++++ test/testing.cmake | 1 + 6 files changed, 179 insertions(+) create mode 100644 test/coarsen.cc diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 35089e344..96872af5d 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -13,6 +13,7 @@ #include "maMatchedCollapse.h" #include "maOperator.h" #include +#include "apfShape.h" namespace ma { @@ -253,4 +254,69 @@ bool coarsen(Adapt* a) return true; } +void printFields(Adapt* a, Mesh* m, std::string name) +{ + apf::Field* f = m->findField("collapse_edges"); + if (!f) + f = apf::createField(m, "collapse_edges", apf::SCALAR, apf::getConstant(1)); + apf::MeshIterator* it = m->begin(1); + apf::MeshEntity* e; + while ((e = m->iterate(it))) { + if (getFlag(a, e, COLLAPSE)) + apf::setScalar(f, e, 0, 1); + else + apf::setScalar(f, e, 0, 0); + } + m->end(it); + + f = m->findField("collapse_verts"); + if (!f) + f = apf::createFieldOn(m, "collapse_verts", apf::SCALAR); + it = m->begin(0); + while ((e = m->iterate(it))) { + if (getFlag(a, e, COLLAPSE)) + apf::setScalar(f, e, 0, 1); + else + apf::setScalar(f, e, 0, 0); + } + m->end(it); + + apf::writeVtkFiles(name.c_str(), m, 1); +} + +bool coarsenAndPrint(Adapt* a) +{ + if (!a->input->shouldCoarsen) + return false; + double t0 = pcu::Time(); + --(a->coarsensLeft); + long count = markEdgesToCollapse(a); + if ( ! count) + return false; + Mesh* m = a->mesh; + int maxDimension = m->getDimension(); + PCU_ALWAYS_ASSERT(checkFlagConsistency(a,1,COLLAPSE)); + long successCount = 0; + + printFields(a, m, "flag_edges"); + + for (int modelDimension=1; modelDimension <= maxDimension; ++modelDimension) + { + checkAllEdgeCollapses(a,modelDimension); + std::string dim = std::to_string(modelDimension); + printFields(a, m, "flag_verts"+dim); + findIndependentSet(a); + printFields(a, m, "independent_set"+dim); + if (m->hasMatching()) + successCount += collapseMatchedEdges(a, modelDimension); + else + successCount += collapseAllEdges(a, modelDimension); + apf::writeVtkFiles(("after_collapse"+dim).c_str(), m, 1); + } + successCount = m->getPCU()->Add(successCount); + double t1 = pcu::Time(); + print(m->getPCU(), "coarsened %li edges in %f seconds", successCount,t1-t0); + return true; +} + } diff --git a/ma/maCoarsen.h b/ma/maCoarsen.h index bf83b1e54..b0ebc435e 100644 --- a/ma/maCoarsen.h +++ b/ma/maCoarsen.h @@ -16,6 +16,7 @@ class Adapt; bool coarsen(Adapt* a); bool coarsenLayer(Adapt* a); +bool coarsenAndPrint(Adapt* a); void checkAllEdgeCollapses(Adapt* a, int modelDimension); void findIndependentSet(Adapt* a); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1b332701c..2d75b7eaf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -177,6 +177,7 @@ test_exe_func(newdim newdim.cc) test_exe_func(construct construct.cc) test_exe_func(constructThenGhost constructThenGhost.cc) test_exe_func(construct_bottom_up construct_bottom_up.cc) +test_exe_func(coarsen coarsen.cc) test_exe_func(embedded_edges embedded_edges.cc) test_exe_func(test_scaling test_scaling.cc) test_exe_func(mixedNumbering mixedNumbering.cc) diff --git a/test/aniso_ma_test2.cc b/test/aniso_ma_test2.cc index 3fc4df947..6a892a6ce 100644 --- a/test/aniso_ma_test2.cc +++ b/test/aniso_ma_test2.cc @@ -8,6 +8,8 @@ #include #include #include +#include "maCoarsen.h" +#include "maAdapt.h" class AnIso : public ma::AnisotropicFunction { @@ -40,6 +42,7 @@ int main(int argc, char* argv[]) { " " << std::endl; return 1; } + //Load Mesh const char* modelFile = argv[1]; const char* meshFile = argv[2]; double sizeFactor1 = std::atof(argv[3]), sizeFactor2 = std::atof(argv[4]); @@ -50,6 +53,8 @@ int main(int argc, char* argv[]) { ma::Mesh* m = apf::loadMdsMesh(modelFile, meshFile, PCUObj); m->verify(); apf::writeVtkFiles("aniso_ma_test2_before",m); + + //Adapt AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); // in->shouldFixShape = false; @@ -60,6 +65,8 @@ int main(int argc, char* argv[]) { m->verify(); apf::writeVtkFiles("aniso_ma_test2_after",m); m->writeNative(argv[5]); + + //Clean up m->destroyNative(); apf::destroyMesh(m); delete PCUObj; diff --git a/test/coarsen.cc b/test/coarsen.cc new file mode 100644 index 000000000..6f6da4294 --- /dev/null +++ b/test/coarsen.cc @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "maAdapt.h" +#include "maCoarsen.h" +#include "apfShape.h" + +double vtx_coords[6][3] = { + {1.0, 0.0, 0.0}, + {1.0, 0.5, 0.0}, + {1.0, 1.0, 0.0}, + {0.5, 0.5, 0.0}, + {0.0, 0.0, 0.0}, + {0.0, 1.0, 0.0} +}; + +apf::Gid triangles[5][3] = { + {0, 1, 3}, + {1, 2, 3}, + {0, 3, 4}, + {3, 2, 5}, + {3, 5, 4}, +}; + +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m, double sf1, double sf2) : + mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + { + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m, lower, upper); + } + virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) + { + double h = average/sizeFactor1; + H = ma::Vector(h, h, h/sizeFactor2); + R = ma::Matrix( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + } + private: + ma::Mesh* mesh; + double sizeFactor1, sizeFactor2, average; + ma::Vector lower, upper; +}; + + +int main(int argc, char** argv) +{ + MPI_Init(&argc,&argv); + { + pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); + lion_set_verbosity(1); + gmi_register_mesh(); + gmi_register_null(); + + apf::Gid* conn = &triangles[0][0]; + double* coords = &vtx_coords[0][0]; + + int nelem=5; + int etype=2; + int nverts=6; + int dim=2; + + //Create mesh + gmi_model* model = gmi_load(".null"); + apf::Mesh2* m = apf::makeEmptyMdsMesh(model, dim, false, &PCUObj); + apf::GlobalToVert outMap; + apf::construct(m, conn, nelem, etype, outMap); + apf::alignMdsRemotes(m); + apf::deriveMdsModel(m); + apf::setCoords(m, coords, nverts, outMap); + outMap.clear(); + m->verify(); + apf::writeVtkFiles("before_coarsen", m); + + //Coarsen + AnIso sf(m, 0.7, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + in->maximumIterations = 1; + in->shouldCoarsen = true; + validateInput(in); + ma::Adapt* a = new ma::Adapt(in); + coarsenAndPrint(a); + m->verify(); + + apf::writeVtkFiles("after_coarsen", m, 1); + + m->destroyNative(); + apf::destroyMesh(m); + } + MPI_Finalize(); +} + diff --git a/test/testing.cmake b/test/testing.cmake index 721b3ba61..0db7f5e71 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -629,6 +629,7 @@ mpi_test(construct_bottom_up 1 ./construct_bottom_up "${MDIR}/bottom_up_constructed_cube.smb" "${MDIR}/cube.dmg") +mpi_test(coarsen 1 ./coarsen) set(MDIR ${MESHES}/embeddedEdges) mpi_test(embedded_edges 1 ./embedded_edges From 3c2faa9804152aeb44a08edf77fa1898520a764f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 26 Mar 2025 23:17:02 -0400 Subject: [PATCH 004/181] simple snap --- ma/maRefine.cc | 12 ++++++++++++ ma/maRefine.h | 2 ++ ma/maSnap.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ test/cap2vtk.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 915d8481a..78cedee10 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -126,6 +126,17 @@ Refine::~Refine() m->destroyTag(numberTag); } +void AddVertexToSnap(Refine* r, Entity* vert) +{ + Adapt* a = r->adapt; + Mesh* m = a->mesh; + int dim = m->getDimension(); + int md = m->getModelType(m->toModel(vert)); + if (dim == md) return; + r->vtxToSnap.push(vert); + setFlag(a, vert, SNAP); +} + Entity* makeSplitVert(Refine* r, Entity* edge) { Adapt* a = r->adapt; @@ -144,6 +155,7 @@ Entity* makeSplitVert(Refine* r, Entity* edge) if (a->input->shouldTransferToClosestPoint) transferToClosestPointOnEdgeSplit(m,edge,0.5,param); Entity* vert = buildVertex(a,c,point,param); + AddVertexToSnap(r, vert); st->onVertex(me,xi,vert); sf->interpolate(me,xi,vert); apf::destroyMeshElement(me); diff --git a/ma/maRefine.h b/ma/maRefine.h index 88efd8275..acca94c8f 100644 --- a/ma/maRefine.h +++ b/ma/maRefine.h @@ -12,6 +12,7 @@ #include "maMesh.h" #include "maTables.h" +#include namespace ma { @@ -26,6 +27,7 @@ class Refine Tag* numberTag; EntityArray toSplit[4]; apf::DynamicArray newEntities[4]; + std::queue vtxToSnap; bool shouldCollect[4]; }; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index e754af553..6a5b8d140 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -11,6 +11,7 @@ #include "maAdapt.h" #include "maOperator.h" #include "maSnapper.h" +#include "maRefine.h" #include "maMatchedSnapper.h" #include "maLayer.h" #include "maMatch.h" @@ -903,7 +904,54 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } +void trySnapping(Adapt* a) { + Mesh* mesh = a->mesh; + Refine* refine = a->refine; + while (!refine->vtxToSnap.empty()) { + Entity* vertex = refine->vtxToSnap.front(); + refine->vtxToSnap.pop(); + Vector target; + Vector prev = getPosition(mesh, vertex); + + getSnapPoint(mesh, vertex, target); + + Upward adjacentElements; + mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); + mesh->setPoint(vertex, 0, target); + + if(!areTetsValid(mesh, adjacentElements)) + mesh->setPoint(vertex, 0, prev); + } +} + +void printSnapFields(Adapt* a, Mesh* m, std::string name) +{ + apf::Field* f = m->findField("vtx_to_snap"); + if (!f) + f = apf::createFieldOn(m, "vtx_to_snap", apf::SCALAR); + apf::MeshIterator* it = m->begin(0); + apf::MeshEntity* e; + while ((e = m->iterate(it))) { + if (getFlag(a, e, SNAP)) + apf::setScalar(f, e, 0, 1); + else + apf::setScalar(f, e, 0, 0); + } + m->end(it); + + apf::writeVtkFiles(name.c_str(), m, 1); +} + void snap(Adapt* a) +{ + if ( ! a->input->shouldSnap) + return; + printSnapFields(a, a->mesh, "snap_flag"); + trySnapping(a); + clearFlagFromDimension(a, SNAP, 0); +} + +void prevSnap(Adapt* a) { if ( ! a->input->shouldSnap) return; diff --git a/test/cap2vtk.cc b/test/cap2vtk.cc index a2891e4ec..67d675daa 100644 --- a/test/cap2vtk.cc +++ b/test/cap2vtk.cc @@ -21,6 +21,10 @@ #include #include #include +#include "maAdapt.h" +#include "maCoarsen.h" +#include "maRefine.h" +#include "maSnap.h" #include "CapstoneModule.h" @@ -37,6 +41,30 @@ using namespace CreateMG::Attribution; using namespace CreateMG::Mesh; using namespace CreateMG::Geometry; +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m, double sf1, double sf2) : + mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + { + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m, lower, upper); + } + virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) + { + double h = average/sizeFactor1; + H = ma::Vector(h, h, h/sizeFactor2); + R = ma::Matrix( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + } + private: + ma::Mesh* mesh; + double sizeFactor1, sizeFactor2, average; + ma::Vector lower, upper; +}; int main(int argc, char** argv) { @@ -134,8 +162,18 @@ int main(int argc, char** argv) // convert the mesh to apf/mds mesh apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); - - apf::writeVtkFiles(folderName, mesh); + mesh->verify(); + apf::writeVtkFiles("before_snap",mesh); + + //Adapt + AnIso sf(mesh, 2, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(mesh, &sf)); + in->maximumIterations = 1; + ma::Adapt* a = new ma::Adapt(in); + ma::refine(a); + ma::snap(a); + mesh->verify(); + apf::writeVtkFiles("after_snap",mesh); gmi_cap_stop(); } From 604c6a55e739fccf440a1ccff06238feac04778d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 28 Mar 2025 10:00:37 -0400 Subject: [PATCH 005/181] check snap --- ma/maSnap.cc | 49 ++++++++++++++++++++++++++++++++++++++----------- test/cap2vtk.cc | 10 +++++++--- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 6a5b8d140..ed26552b3 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -904,34 +904,59 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void trySnapping(Adapt* a) { +void trySnapping(Adapt* a) +{ Mesh* mesh = a->mesh; Refine* refine = a->refine; - while (!refine->vtxToSnap.empty()) { - Entity* vertex = refine->vtxToSnap.front(); - refine->vtxToSnap.pop(); - Vector target; - Vector prev = getPosition(mesh, vertex); + auto vtxToSnap = refine->vtxToSnap; + int notProcessed = vtxToSnap.size(); + print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); + while (notProcessed > 0) + { + notProcessed--; + Entity* vertex = vtxToSnap.front(); + vtxToSnap.pop(); + if (!getFlag(a, vertex, SNAP)) + { + print(a->mesh->getPCU(), "Error: Vertex incorrectly flagged to snap\n"); + continue; + } + + Vector prev = getPosition(mesh, vertex); + Vector target; getSnapPoint(mesh, vertex, target); + if (apf::areClose(prev, target, 1e-12)) + { + clearFlag(a, vertex, SNAP); + continue; + } Upward adjacentElements; mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); mesh->setPoint(vertex, 0, target); - if(!areTetsValid(mesh, adjacentElements)) + if (!areTetsValid(mesh, adjacentElements)) + { mesh->setPoint(vertex, 0, prev); + vtxToSnap.push(vertex); + } + else + clearFlag(a, vertex, SNAP); } + + print(a->mesh->getPCU(), "Number of vertices failed %d\n", vtxToSnap.size()); } void printSnapFields(Adapt* a, Mesh* m, std::string name) { - apf::Field* f = m->findField("vtx_to_snap"); + apf::Field* f = m->findField("SNAP"); if (!f) - f = apf::createFieldOn(m, "vtx_to_snap", apf::SCALAR); + f = apf::createFieldOn(m, "SNAP", apf::SCALAR); apf::MeshIterator* it = m->begin(0); apf::MeshEntity* e; - while ((e = m->iterate(it))) { + while ((e = m->iterate(it))) + { if (getFlag(a, e, SNAP)) apf::setScalar(f, e, 0, 1); else @@ -946,9 +971,11 @@ void snap(Adapt* a) { if ( ! a->input->shouldSnap) return; - printSnapFields(a, a->mesh, "snap_flag"); + printSnapFields(a, a->mesh, "vtx_to_snap"); trySnapping(a); + printSnapFields(a, a->mesh, "vtx_snap_failed"); clearFlagFromDimension(a, SNAP, 0); + a->refine->vtxToSnap = {}; } void prevSnap(Adapt* a) diff --git a/test/cap2vtk.cc b/test/cap2vtk.cc index 67d675daa..bc7f672ad 100644 --- a/test/cap2vtk.cc +++ b/test/cap2vtk.cc @@ -25,6 +25,7 @@ #include "maCoarsen.h" #include "maRefine.h" #include "maSnap.h" +#include "lionPrint.h" #include "CapstoneModule.h" @@ -166,12 +167,15 @@ int main(int argc, char** argv) apf::writeVtkFiles("before_snap",mesh); //Adapt + lion_set_verbosity(1); AnIso sf(mesh, 2, 1); ma::Input* in = ma::makeAdvanced(ma::configure(mesh, &sf)); - in->maximumIterations = 1; ma::Adapt* a = new ma::Adapt(in); - ma::refine(a); - ma::snap(a); + for (int i = 0; i < in->maximumIterations; ++i) + { + ma::refine(a); + ma::snap(a); + } mesh->verify(); apf::writeVtkFiles("after_snap",mesh); From 9801f04d7607f0bfabb03f395e26ee0dd2adcb83 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 11:18:00 -0400 Subject: [PATCH 006/181] refineSnap test --- gmi_cap/gmi_cap.cc | 2 + ma/maRefine.cc | 7 ++ test/CMakeLists.txt | 1 + test/refineSnap.cc | 186 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 test/refineSnap.cc diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index 64b23e26a..67111c6f9 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -197,6 +197,8 @@ static int periodic(struct gmi_model* m, struct gmi_ent* e, int dim) /* PARAM_COMPOSITE=4, //!< parametrization of a composite edge or face */ /* PARAM_UNBOUNDED=8 //!< infinite parametrization */ /* }; */ + if (paramType & 1) return 0; + return paramType & (1<<1); } diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 78cedee10..1fb055fc7 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -19,6 +19,7 @@ #include "maLayer.h" #include #include +#include namespace ma { @@ -149,6 +150,12 @@ Entity* makeSplitVert(Refine* r, Entity* edge) apf::MeshElement* me = apf::createMeshElement(m,edge); Vector point; apf::mapLocalToGlobal(me,xi,point); + + // Vector failed(-0.279880, -0.093306, 0.132892); + // if (apf::areClose(point, failed, 1e-5)){ + // printf("===FAILED FOUND\n"); + // } + Vector param(0,0,0); //prevents uninitialized values if (a->input->shouldTransferParametric) transferParametricOnEdgeSplit(m,edge,0.5,param); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2d75b7eaf..25eb083e3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -169,6 +169,7 @@ test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) test_exe_func(aniso_ma_test2 aniso_ma_test2.cc) +test_exe_func(refineSnap refineSnap.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) diff --git a/test/refineSnap.cc b/test/refineSnap.cc new file mode 100644 index 000000000..26947386a --- /dev/null +++ b/test/refineSnap.cc @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "maAdapt.h" +#include "maCoarsen.h" +#include "maRefine.h" +#include "maSnap.h" +#include "lionPrint.h" + + +#include "CapstoneModule.h" +#include "CreateMG_Framework_Core.h" +#include "CreateMG_Framework_Analysis.h" +#include "CreateMG_Framework_Application.h" +#include "CreateMG_Framework_Attributes.h" +#include "CreateMG_Framework_Core.h" +#include "CreateMG_Framework_Geometry.h" +#include "CreateMG_Framework_Mesh.h" + +using namespace CreateMG; +using namespace CreateMG::Attribution; +using namespace CreateMG::Mesh; +using namespace CreateMG::Geometry; + +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m, double sf1, double sf2) : + mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + { + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m, lower, upper); + } + virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) + { + double h = average/sizeFactor1; + H = ma::Vector(h, h, h/sizeFactor2); + R = ma::Matrix( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + } + private: + ma::Mesh* mesh; + double sizeFactor1, sizeFactor2, average; + ma::Vector lower, upper; +}; + +int main(int argc, char** argv) +{ + MPI_Init(&argc, &argv); + { + pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); + + if (argc != 3) { + if(0==PCUObj.Self()) + std::cerr << "usage: " << argv[0] + << " \n"; + return EXIT_FAILURE; + } + + + gmi_register_mesh(); + gmi_register_null(); + + const char* creFileName = argv[1]; + const char* folderName = argv[2]; + + // load capstone mesh + // create an instance of the Capstone Module activating CREATE/CREATE/CREATE + // for the Geometry/Mesh/Attribution databases + /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ + const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD + const std::string mdbName("Mesh Database : Create"); + const std::string adbName("Attribution Database : Create"); + + CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); + + GeometryDatabaseInterface *g = cs.get_geometry(); + MeshDatabaseInterface *m = cs.get_mesh(); + AppContext *c = cs.get_context(); + + + PCU_ALWAYS_ASSERT(g); + PCU_ALWAYS_ASSERT(m); + PCU_ALWAYS_ASSERT(c); + + v_string filenames; + filenames.push_back(creFileName); + + M_GModel gmodel = cs.load_files(filenames); + + int numbreps = 0; + MG_CALL(g->get_num_breps(numbreps)); + std::cout << "number of b reps is " << numbreps << std::endl; + if(numbreps == 0) + error(HERE, ERR_INVALID_INPUT, "Model is empty"); + + M_MModel mmodel; + // Pick the volume mesh model from associated mesh models to this geom model + std::vector mmodels; + MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); + for(std::size_t i = 0; i < mmodels.size(); ++i) + { + M_MModel ammodel = mmodels[i]; + std::size_t numregs = 0; + std::size_t numfaces = 0; + std::size_t numedges = 0; + std::size_t numverts = 0; + MG_API_CALL(m, set_current_model(ammodel)); + MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); + MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); + MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); + MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); + std::cout << "num regions is " << numregs << std::endl; + std::cout << "num faces is " << numfaces << std::endl; + std::cout << "num edges is " << numedges << std::endl; + std::cout << "num verts is " << numverts << std::endl; + std::cout << "-----------" << std::endl; + if(numregs > 0) + { + mmodel = ammodel; + break; + } + } + + /* SET THE ADJACENCIES */ + MG_API_CALL(m, set_adjacency_state(REGION2FACE| + REGION2EDGE| + REGION2VERTEX| + FACE2EDGE| + FACE2VERTEX)); + MG_API_CALL(m, set_reverse_states()); + MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); + MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); + MG_API_CALL(m, compute_adjacency()); + + + gmi_cap_start(); + gmi_register_cap(); + + // convert the mesh to apf/mds mesh + + apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); + mesh->verify(); + apf::writeVtkFiles("before_snap",mesh); + + //Adapt + lion_set_verbosity(1); + AnIso sf(mesh, 2, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(mesh, &sf)); + in->maximumIterations = 1; + ma::Adapt* a = new ma::Adapt(in); + for (int i = 0; i < in->maximumIterations; ++i) + { + ma::refine(a); + ma::snap(a); + } + mesh->verify(); + apf::writeVtkFiles("after_snap",mesh); + + gmi_cap_stop(); + } + MPI_Finalize(); +} From 3f5899451bb5e4534cc33c10f48058b16ea470b2 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 11:26:17 -0400 Subject: [PATCH 007/181] revert cap2vtk changes --- test/cap2vtk.cc | 47 ++--------------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/test/cap2vtk.cc b/test/cap2vtk.cc index bc7f672ad..c6a8656c1 100644 --- a/test/cap2vtk.cc +++ b/test/cap2vtk.cc @@ -21,11 +21,6 @@ #include #include #include -#include "maAdapt.h" -#include "maCoarsen.h" -#include "maRefine.h" -#include "maSnap.h" -#include "lionPrint.h" #include "CapstoneModule.h" @@ -42,30 +37,6 @@ using namespace CreateMG::Attribution; using namespace CreateMG::Mesh; using namespace CreateMG::Geometry; -class AnIso : public ma::AnisotropicFunction -{ - public: - AnIso(ma::Mesh* m, double sf1, double sf2) : - mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) - { - average = ma::getAverageEdgeLength(m); - ma::getBoundingBox(m, lower, upper); - } - virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) - { - double h = average/sizeFactor1; - H = ma::Vector(h, h, h/sizeFactor2); - R = ma::Matrix( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 - ); - } - private: - ma::Mesh* mesh; - double sizeFactor1, sizeFactor2, average; - ma::Vector lower, upper; -}; int main(int argc, char** argv) { @@ -161,23 +132,9 @@ int main(int argc, char** argv) gmi_register_cap(); // convert the mesh to apf/mds mesh - apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); - mesh->verify(); - apf::writeVtkFiles("before_snap",mesh); - - //Adapt - lion_set_verbosity(1); - AnIso sf(mesh, 2, 1); - ma::Input* in = ma::makeAdvanced(ma::configure(mesh, &sf)); - ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < in->maximumIterations; ++i) - { - ma::refine(a); - ma::snap(a); - } - mesh->verify(); - apf::writeVtkFiles("after_snap",mesh); + + apf::writeVtkFiles(folderName, mesh); gmi_cap_stop(); } From 03c286986e999c3bef513aeecbee5a854f602933 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 11:34:07 -0400 Subject: [PATCH 008/181] remove white space --- gmi_cap/gmi_cap.cc | 1 - test/cap2vtk.cc | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index 67111c6f9..b51498a71 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -198,7 +198,6 @@ static int periodic(struct gmi_model* m, struct gmi_ent* e, int dim) /* PARAM_UNBOUNDED=8 //!< infinite parametrization */ /* }; */ if (paramType & 1) return 0; - return paramType & (1<<1); } diff --git a/test/cap2vtk.cc b/test/cap2vtk.cc index c6a8656c1..a2891e4ec 100644 --- a/test/cap2vtk.cc +++ b/test/cap2vtk.cc @@ -132,6 +132,7 @@ int main(int argc, char** argv) gmi_register_cap(); // convert the mesh to apf/mds mesh + apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); apf::writeVtkFiles(folderName, mesh); From fe63fd1ee59d9f624456dc15f5269f0734c01828 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 15:18:29 -0400 Subject: [PATCH 009/181] added .smb option --- test/refineSnap.cc | 167 ++++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 76 deletions(-) diff --git a/test/refineSnap.cc b/test/refineSnap.cc index 26947386a..e7903fce1 100644 --- a/test/refineSnap.cc +++ b/test/refineSnap.cc @@ -26,6 +26,7 @@ #include "maRefine.h" #include "maSnap.h" #include "lionPrint.h" +#include #include "CapstoneModule.h" @@ -73,10 +74,11 @@ int main(int argc, char** argv) { pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); - if (argc != 3) { - if(0==PCUObj.Self()) + if (argc < 2) { + if(PCUObj.Self()==0) std::cerr << "usage: " << argv[0] - << " \n"; + << " <.cre file> or\n" + << " <.smb file> \n"; return EXIT_FAILURE; } @@ -84,85 +86,98 @@ int main(int argc, char** argv) gmi_register_mesh(); gmi_register_null(); - const char* creFileName = argv[1]; - const char* folderName = argv[2]; - - // load capstone mesh - // create an instance of the Capstone Module activating CREATE/CREATE/CREATE - // for the Geometry/Mesh/Attribution databases - /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ - const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD - const std::string mdbName("Mesh Database : Create"); - const std::string adbName("Attribution Database : Create"); - - CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); - - GeometryDatabaseInterface *g = cs.get_geometry(); - MeshDatabaseInterface *m = cs.get_mesh(); - AppContext *c = cs.get_context(); - - - PCU_ALWAYS_ASSERT(g); - PCU_ALWAYS_ASSERT(m); - PCU_ALWAYS_ASSERT(c); - - v_string filenames; - filenames.push_back(creFileName); - - M_GModel gmodel = cs.load_files(filenames); - - int numbreps = 0; - MG_CALL(g->get_num_breps(numbreps)); - std::cout << "number of b reps is " << numbreps << std::endl; - if(numbreps == 0) - error(HERE, ERR_INVALID_INPUT, "Model is empty"); - - M_MModel mmodel; - // Pick the volume mesh model from associated mesh models to this geom model - std::vector mmodels; - MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); - for(std::size_t i = 0; i < mmodels.size(); ++i) + std::string meshFile(argv[1]); + apf::Mesh2* mesh; + if (meshFile.substr(meshFile.find_last_of(".") + 1) == ".smb") { - M_MModel ammodel = mmodels[i]; - std::size_t numregs = 0; - std::size_t numfaces = 0; - std::size_t numedges = 0; - std::size_t numverts = 0; - MG_API_CALL(m, set_current_model(ammodel)); - MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); - MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); - MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); - MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); - std::cout << "num regions is " << numregs << std::endl; - std::cout << "num faces is " << numfaces << std::endl; - std::cout << "num edges is " << numedges << std::endl; - std::cout << "num verts is " << numverts << std::endl; - std::cout << "-----------" << std::endl; - if(numregs > 0) - { - mmodel = ammodel; - break; - } + if (argc < 3) { + if(PCUObj.Self()==0) std::cerr << "usage: "<< argv[0] << " <.smb file> \n"; + return EXIT_FAILURE; + } + const char* modelFile = argv[2]; + mesh = apf::loadMdsMesh(modelFile, meshFile.c_str(), &PCUObj); } + else if (meshFile.substr(meshFile.find_last_of(".") + 1) == ".cre") + { + // load capstone mesh + // create an instance of the Capstone Module activating CREATE/CREATE/CREATE + // for the Geometry/Mesh/Attribution databases + /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ + const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD + const std::string mdbName("Mesh Database : Create"); + const std::string adbName("Attribution Database : Create"); + + CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); + + GeometryDatabaseInterface *g = cs.get_geometry(); + MeshDatabaseInterface *m = cs.get_mesh(); + AppContext *c = cs.get_context(); + + PCU_ALWAYS_ASSERT(g); + PCU_ALWAYS_ASSERT(m); + PCU_ALWAYS_ASSERT(c); + + v_string filenames; + filenames.push_back(meshFile); + + M_GModel gmodel = cs.load_files(filenames); + + int numbreps = 0; + MG_CALL(g->get_num_breps(numbreps)); + std::cout << "number of b reps is " << numbreps << std::endl; + if(numbreps == 0) + error(HERE, ERR_INVALID_INPUT, "Model is empty"); + + M_MModel mmodel; + // Pick the volume mesh model from associated mesh models to this geom model + std::vector mmodels; + MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); + for(std::size_t i = 0; i < mmodels.size(); ++i) + { + M_MModel ammodel = mmodels[i]; + std::size_t numregs = 0; + std::size_t numfaces = 0; + std::size_t numedges = 0; + std::size_t numverts = 0; + MG_API_CALL(m, set_current_model(ammodel)); + MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); + MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); + MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); + MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); + std::cout << "num regions is " << numregs << std::endl; + std::cout << "num faces is " << numfaces << std::endl; + std::cout << "num edges is " << numedges << std::endl; + std::cout << "num verts is " << numverts << std::endl; + std::cout << "-----------" << std::endl; + if(numregs > 0) + { + mmodel = ammodel; + break; + } + } - /* SET THE ADJACENCIES */ - MG_API_CALL(m, set_adjacency_state(REGION2FACE| - REGION2EDGE| - REGION2VERTEX| - FACE2EDGE| - FACE2VERTEX)); - MG_API_CALL(m, set_reverse_states()); - MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); - MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); - MG_API_CALL(m, compute_adjacency()); - + /* SET THE ADJACENCIES */ + MG_API_CALL(m, set_adjacency_state(REGION2FACE| + REGION2EDGE| + REGION2VERTEX| + FACE2EDGE| + FACE2VERTEX)); + MG_API_CALL(m, set_reverse_states()); + MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); + MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); + MG_API_CALL(m, compute_adjacency()); - gmi_cap_start(); - gmi_register_cap(); + gmi_cap_start(); + gmi_register_cap(); - // convert the mesh to apf/mds mesh + // convert the mesh to apf/mds mesh - apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); + mesh = apf::createMesh(m,g,&PCUObj); + } + else { + std::cerr << "unsupported file type\n"; + return EXIT_FAILURE; + } mesh->verify(); apf::writeVtkFiles("before_snap",mesh); From 5624760b1003b0a19e6661a655c3e4e078e209aa Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 16:22:32 -0400 Subject: [PATCH 010/181] fixed test --- test/refineSnap.cc | 155 ++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 86 deletions(-) diff --git a/test/refineSnap.cc b/test/refineSnap.cc index e7903fce1..94a510599 100644 --- a/test/refineSnap.cc +++ b/test/refineSnap.cc @@ -86,98 +86,81 @@ int main(int argc, char** argv) gmi_register_mesh(); gmi_register_null(); - std::string meshFile(argv[1]); - apf::Mesh2* mesh; - if (meshFile.substr(meshFile.find_last_of(".") + 1) == ".smb") + const char* meshFile = argv[1]; + // load capstone mesh + // create an instance of the Capstone Module activating CREATE/CREATE/CREATE + // for the Geometry/Mesh/Attribution databases + /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ + const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD + const std::string mdbName("Mesh Database : Create"); + const std::string adbName("Attribution Database : Create"); + + CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); + + GeometryDatabaseInterface *g = cs.get_geometry(); + MeshDatabaseInterface *m = cs.get_mesh(); + AppContext *c = cs.get_context(); + + PCU_ALWAYS_ASSERT(g); + PCU_ALWAYS_ASSERT(m); + PCU_ALWAYS_ASSERT(c); + + v_string filenames; + filenames.push_back(meshFile); + + M_GModel gmodel = cs.load_files(filenames); + + int numbreps = 0; + MG_CALL(g->get_num_breps(numbreps)); + std::cout << "number of b reps is " << numbreps << std::endl; + if(numbreps == 0) + error(HERE, ERR_INVALID_INPUT, "Model is empty"); + + M_MModel mmodel; + // Pick the volume mesh model from associated mesh models to this geom model + std::vector mmodels; + MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); + for(std::size_t i = 0; i < mmodels.size(); ++i) { - if (argc < 3) { - if(PCUObj.Self()==0) std::cerr << "usage: "<< argv[0] << " <.smb file> \n"; - return EXIT_FAILURE; - } - const char* modelFile = argv[2]; - mesh = apf::loadMdsMesh(modelFile, meshFile.c_str(), &PCUObj); + M_MModel ammodel = mmodels[i]; + std::size_t numregs = 0; + std::size_t numfaces = 0; + std::size_t numedges = 0; + std::size_t numverts = 0; + MG_API_CALL(m, set_current_model(ammodel)); + MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); + MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); + MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); + MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); + std::cout << "num regions is " << numregs << std::endl; + std::cout << "num faces is " << numfaces << std::endl; + std::cout << "num edges is " << numedges << std::endl; + std::cout << "num verts is " << numverts << std::endl; + std::cout << "-----------" << std::endl; + if(numregs > 0) + { + mmodel = ammodel; + break; + } } - else if (meshFile.substr(meshFile.find_last_of(".") + 1) == ".cre") - { - // load capstone mesh - // create an instance of the Capstone Module activating CREATE/CREATE/CREATE - // for the Geometry/Mesh/Attribution databases - /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ - const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD - const std::string mdbName("Mesh Database : Create"); - const std::string adbName("Attribution Database : Create"); - - CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); - - GeometryDatabaseInterface *g = cs.get_geometry(); - MeshDatabaseInterface *m = cs.get_mesh(); - AppContext *c = cs.get_context(); - - PCU_ALWAYS_ASSERT(g); - PCU_ALWAYS_ASSERT(m); - PCU_ALWAYS_ASSERT(c); - - v_string filenames; - filenames.push_back(meshFile); - - M_GModel gmodel = cs.load_files(filenames); - - int numbreps = 0; - MG_CALL(g->get_num_breps(numbreps)); - std::cout << "number of b reps is " << numbreps << std::endl; - if(numbreps == 0) - error(HERE, ERR_INVALID_INPUT, "Model is empty"); - - M_MModel mmodel; - // Pick the volume mesh model from associated mesh models to this geom model - std::vector mmodels; - MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); - for(std::size_t i = 0; i < mmodels.size(); ++i) - { - M_MModel ammodel = mmodels[i]; - std::size_t numregs = 0; - std::size_t numfaces = 0; - std::size_t numedges = 0; - std::size_t numverts = 0; - MG_API_CALL(m, set_current_model(ammodel)); - MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); - MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); - MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); - MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); - std::cout << "num regions is " << numregs << std::endl; - std::cout << "num faces is " << numfaces << std::endl; - std::cout << "num edges is " << numedges << std::endl; - std::cout << "num verts is " << numverts << std::endl; - std::cout << "-----------" << std::endl; - if(numregs > 0) - { - mmodel = ammodel; - break; - } - } - /* SET THE ADJACENCIES */ - MG_API_CALL(m, set_adjacency_state(REGION2FACE| - REGION2EDGE| - REGION2VERTEX| - FACE2EDGE| - FACE2VERTEX)); - MG_API_CALL(m, set_reverse_states()); - MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); - MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); - MG_API_CALL(m, compute_adjacency()); + /* SET THE ADJACENCIES */ + MG_API_CALL(m, set_adjacency_state(REGION2FACE| + REGION2EDGE| + REGION2VERTEX| + FACE2EDGE| + FACE2VERTEX)); + MG_API_CALL(m, set_reverse_states()); + MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); + MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); + MG_API_CALL(m, compute_adjacency()); - gmi_cap_start(); - gmi_register_cap(); + gmi_cap_start(); + gmi_register_cap(); - // convert the mesh to apf/mds mesh + // convert the mesh to apf/mds mesh - mesh = apf::createMesh(m,g,&PCUObj); - } - else { - std::cerr << "unsupported file type\n"; - return EXIT_FAILURE; - } + apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); mesh->verify(); apf::writeVtkFiles("before_snap",mesh); From e27bc6392aaf455fe315fe83efa7d87423687bd9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 16:25:14 -0400 Subject: [PATCH 011/181] rename file --- test/CMakeLists.txt | 2 +- test/{refineSnap.cc => adaptCap.cc} | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) rename test/{refineSnap.cc => adaptCap.cc} (99%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 25eb083e3..ee42c7921 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -169,7 +169,7 @@ test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) test_exe_func(aniso_ma_test2 aniso_ma_test2.cc) -test_exe_func(refineSnap refineSnap.cc) +test_exe_func(adaptCap adaptCap.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) diff --git a/test/refineSnap.cc b/test/adaptCap.cc similarity index 99% rename from test/refineSnap.cc rename to test/adaptCap.cc index 94a510599..4a2c286e6 100644 --- a/test/refineSnap.cc +++ b/test/adaptCap.cc @@ -26,8 +26,6 @@ #include "maRefine.h" #include "maSnap.h" #include "lionPrint.h" -#include - #include "CapstoneModule.h" #include "CreateMG_Framework_Core.h" From 493a2bf4e6974f914f421bf7122147a070d91971 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 20:42:56 -0400 Subject: [PATCH 012/181] aniso adapt test --- test/aniso_adapt.h | 56 ++++++++++++++++++++++++++++++++++++++++++ test/aniso_ma_test2.cc | 41 +++---------------------------- 2 files changed, 59 insertions(+), 38 deletions(-) create mode 100644 test/aniso_adapt.h diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h new file mode 100644 index 000000000..1f7f3f13b --- /dev/null +++ b/test/aniso_adapt.h @@ -0,0 +1,56 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "maCoarsen.h" +#include "maAdapt.h" +#include "maRefine.h" +#include "maSnap.h" + +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m, double sf1, double sf2) : + mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + { + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m, lower, upper); + } + virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) + { + double h = average/sizeFactor1; + H = ma::Vector(h, h, h/sizeFactor2); + R = ma::Matrix( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + } + private: + ma::Mesh* mesh; + double sizeFactor1, sizeFactor2, average; + ma::Vector lower, upper; +}; + +void refineSnapTest(ma::Mesh* m) +{ + m->verify(); + apf::writeVtkFiles("before_refine_snap_test",m); + AnIso sf(m, 2, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + ma::Adapt* a = new ma::Adapt(in); + in->maximumIterations = 1; + for (int i = 0; i < in->maximumIterations; ++i) + { + ma::refine(a); + ma::snap(a); + } + m->verify(); + apf::writeVtkFiles("after_refine_snap_test",m); +} \ No newline at end of file diff --git a/test/aniso_ma_test2.cc b/test/aniso_ma_test2.cc index 6a892a6ce..b75baf01d 100644 --- a/test/aniso_ma_test2.cc +++ b/test/aniso_ma_test2.cc @@ -8,33 +8,7 @@ #include #include #include -#include "maCoarsen.h" -#include "maAdapt.h" - -class AnIso : public ma::AnisotropicFunction -{ - public: - AnIso(ma::Mesh* m, double sf1, double sf2) : - mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) - { - average = ma::getAverageEdgeLength(m); - ma::getBoundingBox(m, lower, upper); - } - virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) - { - double h = average/sizeFactor1; - H = ma::Vector(h, h, h/sizeFactor2); - R = ma::Matrix( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 - ); - } - private: - ma::Mesh* mesh; - double sizeFactor1, sizeFactor2, average; - ma::Vector lower, upper; -}; +#include "aniso_adapt.h" int main(int argc, char* argv[]) { if (argc != 6) { @@ -51,19 +25,10 @@ int main(int argc, char* argv[]) { lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile, meshFile, PCUObj); - m->verify(); - apf::writeVtkFiles("aniso_ma_test2_before",m); //Adapt - AnIso sf(m, sizeFactor1, sizeFactor2); - ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); - // in->shouldFixShape = false; - // in->shouldCoarsen = false; - // in->shouldSnap = false; - // in->shouldCleanupLayer = false; - ma::adapt(in); - m->verify(); - apf::writeVtkFiles("aniso_ma_test2_after",m); + refineSnapTest(m); + m->writeNative(argv[5]); //Clean up From 5fdc1b69999be90634d0ec1718e0897e71c64099 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 9 Apr 2025 21:02:46 -0400 Subject: [PATCH 013/181] rename cap and sim test --- test/CMakeLists.txt | 4 ++-- test/{adaptCap.cc => aniso_adapt_cap.cc} | 0 test/{aniso_ma_test2.cc => aniso_adapt_sim.cc} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename test/{adaptCap.cc => aniso_adapt_cap.cc} (100%) rename test/{aniso_ma_test2.cc => aniso_adapt_sim.cc} (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ee42c7921..1603c597d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -168,8 +168,8 @@ test_exe_func(xgc_split xgc_split.cc) test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) -test_exe_func(aniso_ma_test2 aniso_ma_test2.cc) -test_exe_func(adaptCap adaptCap.cc) +test_exe_func(aniso_adapt_sim aniso_adapt_sim.cc) +test_exe_func(aniso_adapt_cap aniso_adapt_cap.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) diff --git a/test/adaptCap.cc b/test/aniso_adapt_cap.cc similarity index 100% rename from test/adaptCap.cc rename to test/aniso_adapt_cap.cc diff --git a/test/aniso_ma_test2.cc b/test/aniso_adapt_sim.cc similarity index 100% rename from test/aniso_ma_test2.cc rename to test/aniso_adapt_sim.cc From b2bdb77b294c3ecde479e02cd409f0eab9f27acd Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 15:49:32 -0400 Subject: [PATCH 014/181] fixed sim test --- test/aniso_adapt.h | 5 ++--- test/aniso_adapt_sim.cc | 46 ++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 1f7f3f13b..c67687af1 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -38,14 +38,13 @@ class AnIso : public ma::AnisotropicFunction ma::Vector lower, upper; }; -void refineSnapTest(ma::Mesh* m) +void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) { m->verify(); apf::writeVtkFiles("before_refine_snap_test",m); - AnIso sf(m, 2, 1); + AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - in->maximumIterations = 1; for (int i = 0; i < in->maximumIterations; ++i) { ma::refine(a); diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index b75baf01d..47b2b1d36 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -10,26 +10,58 @@ #include #include "aniso_adapt.h" +#include +#include +#include +#include +#include +#include + +#include "SimParasolidKrnl.h" +#include "MeshSimAdapt.h" +#include "SimDiscrete.h" +#include "SimAdvMeshing.h" +#include "SimMeshTools.h" + int main(int argc, char* argv[]) { - if (argc != 6) { + if (argc != 4) { std::cerr << "Usage: " << argv[0] << - " " << std::endl; + " " << std::endl; return 1; } //Load Mesh const char* modelFile = argv[1]; const char* meshFile = argv[2]; - double sizeFactor1 = std::atof(argv[3]), sizeFactor2 = std::atof(argv[4]); MPI_Init(&argc, &argv); pcu::PCU *PCUObj = new pcu::PCU(MPI_COMM_WORLD); lion_set_verbosity(1); gmi_register_mesh(); - ma::Mesh* m = apf::loadMdsMesh(modelFile, meshFile, PCUObj); + + Sim_logOn("anisoadapt.log"); + MS_init(); + SimAdvMeshing_start(); + SimModel_start(); + Sim_readLicenseFile(NULL); + SimPartitionedMesh_start(&argc,&argv); + + gmi_sim_start(); + gmi_register_sim(); + pProgress progress = Progress_new(); + Progress_setDefaultCallback(progress); + + pGModel model = 0; + pParMesh mesh = 0; + gmi_model* mdl_ref; + ma::Mesh* mesh_ref; + + mdl_ref = gmi_sim_load(argv[1], argv[2]); + model = gmi_export_sim(mdl_ref); + mesh = PM_load(argv[3], model, progress); + mesh_ref = apf::createMesh(mesh, PCUObj); + apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); //Adapt - refineSnapTest(m); - - m->writeNative(argv[5]); + refineSnapTest(m, 3, 1); //Clean up m->destroyNative(); From 7d1394ccfed0ab09abc34fb23bf16631af362919 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 15:51:13 -0400 Subject: [PATCH 015/181] simplify sim test --- test/aniso_adapt_sim.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 47b2b1d36..cfe91a37b 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -49,15 +49,10 @@ int main(int argc, char* argv[]) { pProgress progress = Progress_new(); Progress_setDefaultCallback(progress); - pGModel model = 0; - pParMesh mesh = 0; - gmi_model* mdl_ref; - ma::Mesh* mesh_ref; - - mdl_ref = gmi_sim_load(argv[1], argv[2]); - model = gmi_export_sim(mdl_ref); - mesh = PM_load(argv[3], model, progress); - mesh_ref = apf::createMesh(mesh, PCUObj); + gmi_model* mdl_ref = gmi_sim_load(argv[1], argv[2]); + pGModel model = gmi_export_sim(mdl_ref); + pParMesh mesh = PM_load(argv[3], model, progress); + ma::Mesh* mesh_ref = apf::createMesh(mesh, PCUObj); apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); //Adapt From ecf7b681d04874f9ab47244c280a8a0b26c1a57c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 17:37:31 -0400 Subject: [PATCH 016/181] rename vtk file --- test/aniso_adapt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index c67687af1..71da1c9d4 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -41,7 +41,7 @@ class AnIso : public ma::AnisotropicFunction void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) { m->verify(); - apf::writeVtkFiles("before_refine_snap_test",m); + apf::writeVtkFiles("before_refine_snap",m); AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); @@ -51,5 +51,5 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) ma::snap(a); } m->verify(); - apf::writeVtkFiles("after_refine_snap_test",m); + apf::writeVtkFiles("after_refine_snap",m); } \ No newline at end of file From 4e70f29b4a7f60184d9ba8f61fb8e59cbec63e9c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 20:58:31 -0400 Subject: [PATCH 017/181] wrong copy --- ma/maSnap.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index ed26552b3..c968c3e79 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -908,14 +908,13 @@ void trySnapping(Adapt* a) { Mesh* mesh = a->mesh; Refine* refine = a->refine; - auto vtxToSnap = refine->vtxToSnap; - int notProcessed = vtxToSnap.size(); + int notProcessed = refine->vtxToSnap.size(); print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); while (notProcessed > 0) { notProcessed--; - Entity* vertex = vtxToSnap.front(); - vtxToSnap.pop(); + Entity* vertex = refine->vtxToSnap.front(); + refine->vtxToSnap.pop(); if (!getFlag(a, vertex, SNAP)) { @@ -939,13 +938,13 @@ void trySnapping(Adapt* a) if (!areTetsValid(mesh, adjacentElements)) { mesh->setPoint(vertex, 0, prev); - vtxToSnap.push(vertex); + refine->vtxToSnap.push(vertex); } else clearFlag(a, vertex, SNAP); } - print(a->mesh->getPCU(), "Number of vertices failed %d\n", vtxToSnap.size()); + print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); } void printSnapFields(Adapt* a, Mesh* m, std::string name) From e01cd2e0eafe6c4f414d6fb15921a98ec43ffef9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 22:39:21 -0400 Subject: [PATCH 018/181] get fpp --- ma/maSnap.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index c968c3e79..8aa48d096 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -904,7 +904,23 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void trySnapping(Adapt* a) +void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, Upward& adjacentElements) +{ + FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); + FPP->setVertex(vertex); + apf::Up bad; + bad.n = 0; + for (size_t i = 0; i < adjacentElements.getSize(); ++i) { + bad.e[bad.n++] = adjacentElements[i]; + } + + FPP->setBadElements(bad); + std::vector edgesFromFPP; + FPP->getCandidateEdges(edgesFromFPP); + printf("NUM EDGES FPP %d\n", edgesFromFPP.size()); +} + +void trySnapping(Adapt* a, Tag* snapTag) { Mesh* mesh = a->mesh; Refine* refine = a->refine; @@ -938,7 +954,10 @@ void trySnapping(Adapt* a) if (!areTetsValid(mesh, adjacentElements)) { mesh->setPoint(vertex, 0, prev); + mesh->setDoubleTag(vertex, snapTag, &target[0]); + tryCollapseToVtx(a, vertex, snapTag, adjacentElements); refine->vtxToSnap.push(vertex); + mesh->removeTag(vertex,snapTag); } else clearFlag(a, vertex, SNAP); @@ -968,12 +987,14 @@ void printSnapFields(Adapt* a, Mesh* m, std::string name) void snap(Adapt* a) { - if ( ! a->input->shouldSnap) + if (!a->input->shouldSnap) return; printSnapFields(a, a->mesh, "vtx_to_snap"); - trySnapping(a); + Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); + trySnapping(a, snapTag); printSnapFields(a, a->mesh, "vtx_snap_failed"); clearFlagFromDimension(a, SNAP, 0); + a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; } From 3ad34c05f5cfce4747152e033270d6927ef0aa13 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 10 Apr 2025 23:18:25 -0400 Subject: [PATCH 019/181] refactor invalid --- ma/maSnap.cc | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 8aa48d096..f0d7dd79b 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -904,20 +904,25 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, Upward& adjacentElements) +void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) { FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); FPP->setVertex(vertex); - apf::Up bad; - bad.n = 0; - for (size_t i = 0; i < adjacentElements.getSize(); ++i) { - bad.e[bad.n++] = adjacentElements[i]; - } - - FPP->setBadElements(bad); + FPP->setBadElements(invalid); std::vector edgesFromFPP; FPP->getCandidateEdges(edgesFromFPP); - printf("NUM EDGES FPP %d\n", edgesFromFPP.size()); + printf("INVALID %d FPP %d\n", invalid.n, edgesFromFPP.size()); +} + +void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) +{ + invalid.n = 0; + Vector v[4]; + for (size_t i = 0; i < adjacentElements.getSize(); ++i) { + ma::getVertPoints(mesh,adjacentElements[i],v); + if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) + invalid.e[invalid.n++] = adjacentElements[i]; + } } void trySnapping(Adapt* a, Tag* snapTag) @@ -951,11 +956,14 @@ void trySnapping(Adapt* a, Tag* snapTag) mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); mesh->setPoint(vertex, 0, target); - if (!areTetsValid(mesh, adjacentElements)) + apf::Up invalid; + getInvalidTets(mesh, adjacentElements, invalid); + + if (invalid.n > 0) { mesh->setPoint(vertex, 0, prev); mesh->setDoubleTag(vertex, snapTag, &target[0]); - tryCollapseToVtx(a, vertex, snapTag, adjacentElements); + tryCollapseToVtx(a, vertex, snapTag, invalid); refine->vtxToSnap.push(vertex); mesh->removeTag(vertex,snapTag); } From 4dfe5ac8a10dab06f1611cf46430b69ff4a7855c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 11 Apr 2025 13:49:10 -0400 Subject: [PATCH 020/181] fixed tabs --- ma/maSnap.cc | 1 + ma/maSnapper.cc | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index f0d7dd79b..94d95ebd6 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -912,6 +912,7 @@ void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) std::vector edgesFromFPP; FPP->getCandidateEdges(edgesFromFPP); printf("INVALID %d FPP %d\n", invalid.n, edgesFromFPP.size()); + delete FPP; } void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 14c9a1651..ebb072a08 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -345,7 +345,7 @@ bool FirstProblemPlane::find() lion_oprint(1, "Info: Found Infinitely Many Intersection Points!\n"); Vector newDirection = intersect - ray.start; if (newDirection.getLength() < minDist) { - dists.push_back(newDirection.getLength()); + dists.push_back(newDirection.getLength()); minDist = dists.back(); problemFace = face; problemRegion = elem; @@ -374,8 +374,8 @@ bool FirstProblemPlane::find() minDist += tol; for (int i = 0; i < n; i++) { if (dists[i] < minDist) { - coplanarProblemRegions.e[coplanarProblemRegions.n] = problemRegions.e[i]; - coplanarProblemRegions.n++; + coplanarProblemRegions.e[coplanarProblemRegions.n] = problemRegions.e[i]; + coplanarProblemRegions.n++; } } } @@ -477,8 +477,8 @@ void FirstProblemPlane::findCommonEdges(apf::Up& cpRegions) int nDownEdges = mesh->getDownward(cpRegions.e[0], 1, edges); for (int i = 0; i < nDownEdges; i++) { if (isLowInHigh(mesh, edges[i], vert)) { - commEdges.e[commEdges.n] = edges[i]; - commEdges.n++; + commEdges.e[commEdges.n] = edges[i]; + commEdges.n++; } } return; From 9437c742a8d22d59c906811f68b8b7b6d820f136 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 11 Apr 2025 17:21:07 -0400 Subject: [PATCH 021/181] assert cap not discontinuous and periodic --- gmi_cap/gmi_cap.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index b51498a71..4bf6ba53c 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -198,7 +198,9 @@ static int periodic(struct gmi_model* m, struct gmi_ent* e, int dim) /* PARAM_UNBOUNDED=8 //!< infinite parametrization */ /* }; */ if (paramType & 1) return 0; - return paramType & (1<<1); + int isPeriodic = paramType & (1<<1); + PCU_ALWAYS_ASSERT(isPeriodic == false); //TODO: for now cannot handle periodic geometric entity (with discontinuity in parametric coords) + return isPeriodic; } static void range(struct gmi_model* m, struct gmi_ent* e, int dim, From 5a95b70137f4a36b65deb4a10d23ca608f6c01ea Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 11 Apr 2025 19:01:07 -0400 Subject: [PATCH 022/181] update aniso adapt cap --- gmi_cap/gmi_cap.cc | 2 +- test/aniso_adapt_cap.cc | 44 ++++------------------------------------- 2 files changed, 5 insertions(+), 41 deletions(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index 4bf6ba53c..e21769311 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -199,7 +199,7 @@ static int periodic(struct gmi_model* m, struct gmi_ent* e, int dim) /* }; */ if (paramType & 1) return 0; int isPeriodic = paramType & (1<<1); - PCU_ALWAYS_ASSERT(isPeriodic == false); //TODO: for now cannot handle periodic geometric entity (with discontinuity in parametric coords) + PCU_ALWAYS_ASSERT_VERBOSE(isPeriodic == false, "for now cannot handle periodic geometric entity (with discontinuity in parametric coords)"); return isPeriodic; } diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 4a2c286e6..d034d7b37 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -26,6 +26,7 @@ #include "maRefine.h" #include "maSnap.h" #include "lionPrint.h" +#include "aniso_adapt.h" #include "CapstoneModule.h" #include "CreateMG_Framework_Core.h" @@ -41,31 +42,6 @@ using namespace CreateMG::Attribution; using namespace CreateMG::Mesh; using namespace CreateMG::Geometry; -class AnIso : public ma::AnisotropicFunction -{ - public: - AnIso(ma::Mesh* m, double sf1, double sf2) : - mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) - { - average = ma::getAverageEdgeLength(m); - ma::getBoundingBox(m, lower, upper); - } - virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) - { - double h = average/sizeFactor1; - H = ma::Vector(h, h, h/sizeFactor2); - R = ma::Matrix( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 - ); - } - private: - ma::Mesh* mesh; - double sizeFactor1, sizeFactor2, average; - ma::Vector lower, upper; -}; - int main(int argc, char** argv) { MPI_Init(&argc, &argv); @@ -159,22 +135,10 @@ int main(int argc, char** argv) // convert the mesh to apf/mds mesh apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); - mesh->verify(); - apf::writeVtkFiles("before_snap",mesh); - - //Adapt lion_set_verbosity(1); - AnIso sf(mesh, 2, 1); - ma::Input* in = ma::makeAdvanced(ma::configure(mesh, &sf)); - in->maximumIterations = 1; - ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < in->maximumIterations; ++i) - { - ma::refine(a); - ma::snap(a); - } - mesh->verify(); - apf::writeVtkFiles("after_snap",mesh); + + //Adapt + refineSnapTest(mesh, 3, 1); gmi_cap_stop(); } From a06d243ee9b443d8084c47dfc1480a2a45e5a37b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 12 Apr 2025 22:04:48 -0400 Subject: [PATCH 023/181] moved tag vtx --- ma/maSnap.cc | 59 ++++++++++++++++++++++--------------------------- ma/maSnapper.cc | 10 ++++----- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 94d95ebd6..4829c0fb4 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -841,29 +841,35 @@ bool snapMatchedVerts(Adapt* a, Tag* t, bool isSimple, long& successCount) return a->mesh->getPCU()->Or(op.didAnything); } -long tagVertsToSnap(Adapt* a, Tag*& t) +long tagVertsToSnap(Adapt* a, Tag*& tag) { Mesh* m = a->mesh; + Refine* refine = a->refine; int dim = m->getDimension(); - t = m->createDoubleTag("ma_snap", 3); - Entity* v; - long n = 0; - Iterator* it = m->begin(0); - while ((v = m->iterate(it))) { - int md = m->getModelType(m->toModel(v)); - if (dim == 3 && md == 3) - continue; - Vector s; - getSnapPoint(m, v, s); - Vector x = getPosition(m, v); - if (apf::areClose(s, x, 1e-12)) + tag = m->createDoubleTag("ma_snap", 3); + int notProcessed = refine->vtxToSnap.size(); + int owned = 0; + while (notProcessed > 0) + { + notProcessed--; + Entity* vertex = refine->vtxToSnap.front(); + refine->vtxToSnap.pop(); + PCU_ALWAYS_ASSERT(getFlag(a, vertex, SNAP)); + + Vector target; + getSnapPoint(m, vertex, target); + Vector prev = getPosition(m, vertex); + if (apf::areClose(prev, target, 1e-12)) + { + clearFlag(a, vertex, SNAP); continue; - m->setDoubleTag(v, t, &s[0]); - if (m->isOwned(v)) - ++n; + } + m->setDoubleTag(vertex, tag, &target[0]); + if (m->isOwned(vertex)) + ++owned; + refine->vtxToSnap.push(vertex); } - m->end(it); - return m->getPCU()->Add(n); + return m->getPCU()->Add(owned); } static void markVertsToSnap(Adapt* a, Tag* t) @@ -938,20 +944,9 @@ void trySnapping(Adapt* a, Tag* snapTag) Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); - if (!getFlag(a, vertex, SNAP)) - { - print(a->mesh->getPCU(), "Error: Vertex incorrectly flagged to snap\n"); - continue; - } - Vector prev = getPosition(mesh, vertex); Vector target; - getSnapPoint(mesh, vertex, target); - if (apf::areClose(prev, target, 1e-12)) - { - clearFlag(a, vertex, SNAP); - continue; - } + mesh->getDoubleTag(vertex, snapTag, &target[0]); Upward adjacentElements; mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); @@ -963,7 +958,6 @@ void trySnapping(Adapt* a, Tag* snapTag) if (invalid.n > 0) { mesh->setPoint(vertex, 0, prev); - mesh->setDoubleTag(vertex, snapTag, &target[0]); tryCollapseToVtx(a, vertex, snapTag, invalid); refine->vtxToSnap.push(vertex); mesh->removeTag(vertex,snapTag); @@ -999,7 +993,8 @@ void snap(Adapt* a) if (!a->input->shouldSnap) return; printSnapFields(a, a->mesh, "vtx_to_snap"); - Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); + Tag* snapTag; + tagVertsToSnap(a, snapTag); trySnapping(a, snapTag); printSnapFields(a, a->mesh, "vtx_snap_failed"); clearFlagFromDimension(a, SNAP, 0); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index ebb072a08..c2c8b5a5e 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -517,11 +517,11 @@ void FirstProblemPlane::findCommonEdges(apf::Up& cpRegions) if (!isLowInHigh(mesh, region, edges[i])) { flag = 0; break; - } - if (flag) { - commEdges.e[commEdges.n] = edges[i]; - commEdges.n++; - } + } + if (flag) { + commEdges.e[commEdges.n] = edges[i]; + commEdges.n++; + } } } } From d486034bef4f1ef746139833dc4077e5bf205c20 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 12 Apr 2025 22:18:20 -0400 Subject: [PATCH 024/181] moved try reposition --- ma/maSnap.cc | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 4829c0fb4..a839221fc 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -910,7 +910,7 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) +bool tryCollapseToVertex(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) { FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); FPP->setVertex(vertex); @@ -919,6 +919,7 @@ void tryCollapseToVtx(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) FPP->getCandidateEdges(edgesFromFPP); printf("INVALID %d FPP %d\n", invalid.n, edgesFromFPP.size()); delete FPP; + return false; } void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) @@ -932,6 +933,19 @@ void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) } } +bool tryReposition(Mesh* mesh, Entity* vertex, Tag* snapTag, apf::Up& invalid) +{ + Vector prev = getPosition(mesh, vertex); + Vector target; + mesh->getDoubleTag(vertex, snapTag, &target[0]); + Upward adjacentElements; + mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); + mesh->setPoint(vertex, 0, target); + getInvalidTets(mesh, adjacentElements, invalid); + if (invalid.n == 0) return true; + mesh->setPoint(vertex, 0, prev); +} + void trySnapping(Adapt* a, Tag* snapTag) { Mesh* mesh = a->mesh; @@ -944,26 +958,18 @@ void trySnapping(Adapt* a, Tag* snapTag) Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); - Vector prev = getPosition(mesh, vertex); - Vector target; - mesh->getDoubleTag(vertex, snapTag, &target[0]); + apf::Up invalid; + bool success = tryReposition(mesh, vertex, snapTag, invalid); - Upward adjacentElements; - mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); - mesh->setPoint(vertex, 0, target); + if (!success) + success = tryCollapseToVertex(a, vertex, snapTag, invalid); - apf::Up invalid; - getInvalidTets(mesh, adjacentElements, invalid); - - if (invalid.n > 0) - { - mesh->setPoint(vertex, 0, prev); - tryCollapseToVtx(a, vertex, snapTag, invalid); - refine->vtxToSnap.push(vertex); + if (success) { mesh->removeTag(vertex,snapTag); + clearFlag(a, vertex, SNAP); } else - clearFlag(a, vertex, SNAP); + refine->vtxToSnap.push(vertex); } print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); From ec767eba21d3a2fc67c76ceecdb7def1a5b5861c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 12 Apr 2025 23:39:09 -0400 Subject: [PATCH 025/181] collapse to vtx done --- ma/maSnap.cc | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index a839221fc..9ee968f68 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -910,14 +910,33 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -bool tryCollapseToVertex(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) +bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, Tag* snapTag, apf::Up& invalid) { FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); FPP->setVertex(vertex); FPP->setBadElements(invalid); - std::vector edgesFromFPP; - FPP->getCandidateEdges(edgesFromFPP); - printf("INVALID %d FPP %d\n", invalid.n, edgesFromFPP.size()); + std::vector collapseOptions; + FPP->getCandidateEdges(collapseOptions); + setFlagMatched(a,vertex,DONT_COLLAPSE); + double q = a->input->validQuality; + for (size_t i = 0; i < collapseOptions.size(); ++i) { + Entity* edge = collapseOptions[i]; + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + if (!collapse.setEdge(edge)) + continue; + if (!collapse.checkClass()) + continue; + if (!collapse.checkTopo()) + continue; + bool oldForce = a->input->shouldForceAdaptation; + a->input->shouldForceAdaptation = true; + if (!collapse.tryBothDirections(q)) + continue; + a->input->shouldForceAdaptation = oldForce; + collapse.destroyOldElements(); + clearFlagMatched(a,vertex,DONT_COLLAPSE); + return true; //TODO: select from best quality instead of first + } delete FPP; return false; } @@ -950,6 +969,8 @@ void trySnapping(Adapt* a, Tag* snapTag) { Mesh* mesh = a->mesh; Refine* refine = a->refine; + Collapse collapse; + collapse.Init(a); int notProcessed = refine->vtxToSnap.size(); print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); while (notProcessed > 0) @@ -962,7 +983,7 @@ void trySnapping(Adapt* a, Tag* snapTag) bool success = tryReposition(mesh, vertex, snapTag, invalid); if (!success) - success = tryCollapseToVertex(a, vertex, snapTag, invalid); + success = tryCollapseToVertex(a, collapse, vertex, snapTag, invalid); if (success) { mesh->removeTag(vertex,snapTag); From 8f6578d4d85d11bdfd9ec397b006dca0e6a3385d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 16 Apr 2025 21:41:27 -0400 Subject: [PATCH 026/181] using ma_dbg --- ma/maSnap.cc | 36 +++++++++++++----------------------- test/aniso_adapt.h | 2 +- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 9ee968f68..9c955a7dc 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -915,12 +915,12 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, Tag* snap FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); FPP->setVertex(vertex); FPP->setBadElements(invalid); - std::vector collapseOptions; - FPP->getCandidateEdges(collapseOptions); + std::vector commEdges; + FPP->getCandidateEdges(commEdges); setFlagMatched(a,vertex,DONT_COLLAPSE); double q = a->input->validQuality; - for (size_t i = 0; i < collapseOptions.size(); ++i) { - Entity* edge = collapseOptions[i]; + for (size_t i = 0; i < commEdges.size(); ++i) { + Entity* edge = commEdges[i]; PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); if (!collapse.setEdge(edge)) continue; @@ -952,8 +952,9 @@ void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) } } -bool tryReposition(Mesh* mesh, Entity* vertex, Tag* snapTag, apf::Up& invalid) +bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) { + Mesh* mesh = adapt->mesh; Vector prev = getPosition(mesh, vertex); Vector target; mesh->getDoubleTag(vertex, snapTag, &target[0]); @@ -963,6 +964,7 @@ bool tryReposition(Mesh* mesh, Entity* vertex, Tag* snapTag, apf::Up& invalid) getInvalidTets(mesh, adjacentElements, invalid); if (invalid.n == 0) return true; mesh->setPoint(vertex, 0, prev); + return false; } void trySnapping(Adapt* a, Tag* snapTag) @@ -980,7 +982,7 @@ void trySnapping(Adapt* a, Tag* snapTag) refine->vtxToSnap.pop(); apf::Up invalid; - bool success = tryReposition(mesh, vertex, snapTag, invalid); + bool success = tryReposition(a, vertex, snapTag, invalid); if (!success) success = tryCollapseToVertex(a, collapse, vertex, snapTag, invalid); @@ -998,32 +1000,20 @@ void trySnapping(Adapt* a, Tag* snapTag) void printSnapFields(Adapt* a, Mesh* m, std::string name) { - apf::Field* f = m->findField("SNAP"); - if (!f) - f = apf::createFieldOn(m, "SNAP", apf::SCALAR); - apf::MeshIterator* it = m->begin(0); - apf::MeshEntity* e; - while ((e = m->iterate(it))) - { - if (getFlag(a, e, SNAP)) - apf::setScalar(f, e, 0, 1); - else - apf::setScalar(f, e, 0, 0); - } - m->end(it); - - apf::writeVtkFiles(name.c_str(), m, 1); + apf::writeVtkFiles(name.c_str(), m); + ma_dbg::addTargetLocation(a, "snap_target"); + apf::writeVtkFiles((name+"_fields").c_str(), m, 1); } void snap(Adapt* a) { if (!a->input->shouldSnap) return; - printSnapFields(a, a->mesh, "vtx_to_snap"); Tag* snapTag; tagVertsToSnap(a, snapTag); + printSnapFields(a, a->mesh, "before_last_snap"); trySnapping(a, snapTag); - printSnapFields(a, a->mesh, "vtx_snap_failed"); + printSnapFields(a, a->mesh, "after_last_snap"); clearFlagFromDimension(a, SNAP, 0); a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 71da1c9d4..d514149a9 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -45,7 +45,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < in->maximumIterations; ++i) + for (int i = 0; i < 2; ++i) { ma::refine(a); ma::snap(a); From 89175a40d45c64a56e08d69aea8697f5ef4ae956 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 16 Apr 2025 22:55:33 -0400 Subject: [PATCH 027/181] collapse tet edges --- ma/maSnap.cc | 58 ++++++++++++++++++++++++++++++++++++++++++-------- ma/maSnapper.h | 6 +++--- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 9c955a7dc..238969b0e 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -910,13 +910,40 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, Tag* snapTag, apf::Up& invalid) +bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityToBeat) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + if (!collapse.setEdge(edge)) + return false; + if (!collapse.checkClass()) + return false; + if (!collapse.checkTopo()) + return false; + if (!collapse.tryBothDirections(qualityToBeat)) + return false; + collapse.destroyOldElements(); + return true; +} + +bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, Entity* vertex, std::vector &commEdges) +{ + //TODO: handle edge cases + for (int i=0; imesh, edge, vertex); + apf::Up adjEdges; + a->mesh->getUp(vertexFPP, adjEdges); + for (int j=0; jinput->validQuality)) return true; + } + } + return false; +} + +bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, std::vector &commEdges) { - FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); - FPP->setVertex(vertex); - FPP->setBadElements(invalid); - std::vector commEdges; - FPP->getCandidateEdges(commEdges); setFlagMatched(a,vertex,DONT_COLLAPSE); double q = a->input->validQuality; for (size_t i = 0; i < commEdges.size(); ++i) { @@ -937,10 +964,19 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, Tag* snap clearFlagMatched(a,vertex,DONT_COLLAPSE); return true; //TODO: select from best quality instead of first } - delete FPP; return false; } +std::vector getCommEdgesFromFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) +{ + FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); + FPP->setVertex(vertex); + FPP->setBadElements(invalid); + std::vector commEdges; + FPP->getCandidateEdges(commEdges); + return commEdges; +} + void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) { invalid.n = 0; @@ -984,8 +1020,10 @@ void trySnapping(Adapt* a, Tag* snapTag) apf::Up invalid; bool success = tryReposition(a, vertex, snapTag, invalid); - if (!success) - success = tryCollapseToVertex(a, collapse, vertex, snapTag, invalid); + std::vector commEdges; + if (!success) commEdges = getCommEdgesFromFPP(a, vertex, snapTag, invalid); + if (!success) success = tryCollapseToVertex(a, collapse, vertex, commEdges); + if (!success) success = tryCollapseTetEdges(a, collapse, vertex, commEdges); if (success) { mesh->removeTag(vertex,snapTag); @@ -993,6 +1031,8 @@ void trySnapping(Adapt* a, Tag* snapTag) } else refine->vtxToSnap.push(vertex); + + // delete FPP; } print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 9711d5e65..0de81e277 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -55,15 +55,15 @@ class FirstProblemPlane void setVertex(Entity* v); void setBadElements(apf::Up& badElements); void getCandidateEdges(std::vector &edges); + Entity* vert; + Entity* problemFace; + apf::Up commEdges; private: Adapt* adapter; Tag* snapTag; - Entity* vert; apf::Up problemRegions; - Entity* problemFace; Entity* problemRegion; Vector intersection; - apf::Up commEdges; double tol; bool find(); void findCandidateEdges(std::vector &edges); From 24f8d4dbb5e7a06fa3c62c4af77e4f41adf105f8 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Apr 2025 17:12:33 -0400 Subject: [PATCH 028/181] simplify try collpase --- ma/maSnap.cc | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 238969b0e..2a12a729e 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -944,27 +944,22 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, Entity* vertex, std::vect bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, std::vector &commEdges) { - setFlagMatched(a,vertex,DONT_COLLAPSE); + bool flag = getFlag(a,vertex,DONT_COLLAPSE); + if (!flag) setFlag(a,vertex,DONT_COLLAPSE); + bool oldForce = a->input->shouldForceAdaptation; + a->input->shouldForceAdaptation = true; double q = a->input->validQuality; + bool success = false; for (size_t i = 0; i < commEdges.size(); ++i) { Entity* edge = commEdges[i]; - PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - if (!collapse.setEdge(edge)) - continue; - if (!collapse.checkClass()) - continue; - if (!collapse.checkTopo()) - continue; - bool oldForce = a->input->shouldForceAdaptation; - a->input->shouldForceAdaptation = true; - if (!collapse.tryBothDirections(q)) - continue; - a->input->shouldForceAdaptation = oldForce; - collapse.destroyOldElements(); - clearFlagMatched(a,vertex,DONT_COLLAPSE); - return true; //TODO: select from best quality instead of first + success = tryCollapseEdge(a, commEdges[i], collapse, q); + if (success) break; //TODO: select from best quality instead of first } - return false; + + a->input->shouldForceAdaptation = oldForce; + if (!flag) clearFlag(a,vertex,DONT_COLLAPSE); + + return success; } std::vector getCommEdgesFromFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) From 9da25961051dc856747180e1bca43acaff390b3f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Apr 2025 17:20:10 -0400 Subject: [PATCH 029/181] rename --- ma/maSnap.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 2a12a729e..9ef94a8a6 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -946,9 +946,10 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, std::vect { bool flag = getFlag(a,vertex,DONT_COLLAPSE); if (!flag) setFlag(a,vertex,DONT_COLLAPSE); - bool oldForce = a->input->shouldForceAdaptation; + bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; double q = a->input->validQuality; + bool success = false; for (size_t i = 0; i < commEdges.size(); ++i) { Entity* edge = commEdges[i]; @@ -956,7 +957,7 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, std::vect if (success) break; //TODO: select from best quality instead of first } - a->input->shouldForceAdaptation = oldForce; + a->input->shouldForceAdaptation = shouldForce; if (!flag) clearFlag(a,vertex,DONT_COLLAPSE); return success; From 9e812e3a3b89a8a6d900b0b96f4a49596cd9c02f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Apr 2025 18:14:58 -0400 Subject: [PATCH 030/181] using FPP --- ma/maSnap.cc | 36 +++++++++++++++++++++++------------- ma/maSnapper.cc | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 9ef94a8a6..ad0171f42 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -942,35 +942,45 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, Entity* vertex, std::vect return false; } -bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Entity* vertex, std::vector &commEdges) +bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProblemPlane* FPP) { - bool flag = getFlag(a,vertex,DONT_COLLAPSE); - if (!flag) setFlag(a,vertex,DONT_COLLAPSE); + bool flag = getFlag(a,FPP->vert,DONT_COLLAPSE); + if (!flag) setFlag(a,FPP->vert,DONT_COLLAPSE); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; double q = a->input->validQuality; + Vector position = getPosition(a->mesh, FPP->vert); + Vector target; + a->mesh->getDoubleTag(FPP->vert, snapTag, &target[0]); + double distTarget = (position - target).getLength(); + bool success = false; - for (size_t i = 0; i < commEdges.size(); ++i) { - Entity* edge = commEdges[i]; - success = tryCollapseEdge(a, commEdges[i], collapse, q); + for (size_t i = 0; i < FPP->commEdges.n; ++i) { + Entity* edge = FPP->commEdges.e[i]; + Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); + Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); + double vertFPPdist = (vFPPCoord - target).getLength(); + if (vertFPPdist > distTarget) continue; + + success = tryCollapseEdge(a, edge, collapse, q); if (success) break; //TODO: select from best quality instead of first } a->input->shouldForceAdaptation = shouldForce; - if (!flag) clearFlag(a,vertex,DONT_COLLAPSE); + if (!flag) clearFlag(a,FPP->vert,DONT_COLLAPSE); return success; } -std::vector getCommEdgesFromFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) +FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) { FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); FPP->setVertex(vertex); FPP->setBadElements(invalid); std::vector commEdges; FPP->getCandidateEdges(commEdges); - return commEdges; + return FPP; } void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) @@ -1016,10 +1026,10 @@ void trySnapping(Adapt* a, Tag* snapTag) apf::Up invalid; bool success = tryReposition(a, vertex, snapTag, invalid); - std::vector commEdges; - if (!success) commEdges = getCommEdgesFromFPP(a, vertex, snapTag, invalid); - if (!success) success = tryCollapseToVertex(a, collapse, vertex, commEdges); - if (!success) success = tryCollapseTetEdges(a, collapse, vertex, commEdges); + FirstProblemPlane* FPP; + if (!success) FPP = getFPP(a, vertex, snapTag, invalid); + if (!success) success = tryCollapseToVertex(a, collapse, snapTag, FPP); + // if (!success) success = tryCollapseTetEdges(a, collapse, vertex, commEdges); if (success) { mesh->removeTag(vertex,snapTag); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index c2c8b5a5e..6c2ee6669 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -171,7 +171,7 @@ static bool tryDigging2(Adapt* a, Collapse& c, apf::Up& badElements, nedges = m->getDownward(elem, 1, edges); for (int j = 0; j < nedges; ++j){ if (tryDiggingEdge(a, c, edges[j])) - return true; + return true; } } return false; From 5237926805671bff9644d7a702e52578ccddba00 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Apr 2025 22:52:36 -0400 Subject: [PATCH 031/181] trying to collapse tet edges --- ma/maSnap.cc | 58 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index ad0171f42..edf5235d5 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -925,20 +925,48 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityT return true; } -bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, Entity* vertex, std::vector &commEdges) +bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { - //TODO: handle edge cases - for (int i=0; imesh, edge, vertex); - apf::Up adjEdges; - a->mesh->getUp(vertexFPP, adjEdges); - for (int j=0; jinput->validQuality)) return true; + apf::Up& commEdges = FPP->commEdges; + double qual = a->input->validQuality; + + //Try to reduce num common edges to one + Entity* pbEdges[3]; + a->mesh->getDownward(FPP->problemFace, 1, pbEdges); + + switch(commEdges.n) { + case 2: { + Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); + Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + + for (int i=0; i<3; i++) { + Entity* pbVert[2]; + a->mesh->getDownward(pbEdges[i], 0, pbVert); + if (pbVert[0] == v1 && pbVert[1] == v2) break; + if (pbVert[1] == v1 && pbVert[0] == v2) break; + if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; + } + break; } + // case 3: { + // for (int i=0; i<3; i++) + // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; + // break; + // } } + + // for (int i=0; imesh, edge, FPP->vert); + // apf::Up adjEdges; + // a->mesh->getUp(vertexFPP, adjEdges); + // for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; + // if (tryCollapseEdge(a, edgeDel, collapse, qual)) return true; + // } + // } return false; } @@ -960,6 +988,7 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble Entity* edge = FPP->commEdges.e[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); + //TODO: add logic for boundary layers double vertFPPdist = (vFPPCoord - target).getLength(); if (vertFPPdist > distTarget) continue; @@ -997,6 +1026,7 @@ void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) { Mesh* mesh = adapt->mesh; + if (!mesh->hasTag(vertex, snapTag)) return true; Vector prev = getPosition(mesh, vertex); Vector target; mesh->getDoubleTag(vertex, snapTag, &target[0]); @@ -1026,10 +1056,10 @@ void trySnapping(Adapt* a, Tag* snapTag) apf::Up invalid; bool success = tryReposition(a, vertex, snapTag, invalid); - FirstProblemPlane* FPP; + FirstProblemPlane* FPP = 0; if (!success) FPP = getFPP(a, vertex, snapTag, invalid); if (!success) success = tryCollapseToVertex(a, collapse, snapTag, FPP); - // if (!success) success = tryCollapseTetEdges(a, collapse, vertex, commEdges); + if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (success) { mesh->removeTag(vertex,snapTag); @@ -1038,7 +1068,7 @@ void trySnapping(Adapt* a, Tag* snapTag) else refine->vtxToSnap.push(vertex); - // delete FPP; + if (FPP) delete FPP; } print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); From 81eb05ce781fb0517463851ba021bc12fb8a816e Mon Sep 17 00:00:00 2001 From: Angelyr Date: Mon, 21 Apr 2025 13:25:27 -0400 Subject: [PATCH 032/181] print cavity --- ma/maDBG.cc | 11 +++++++---- ma/maSnap.cc | 52 +++++++++++++++++++++++++++++++++++--------------- ma/maSnapper.h | 4 ++-- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/ma/maDBG.cc b/ma/maDBG.cc index 2460ec809..2b4321f43 100644 --- a/ma/maDBG.cc +++ b/ma/maDBG.cc @@ -33,7 +33,8 @@ namespace ma_dbg { void writeMesh(ma::Mesh* m, const char* prefix, - const char* suffix) + const char* suffix, + int dim=-1) { std::stringstream ss; if (std::string(suffix) != "") @@ -42,7 +43,7 @@ void writeMesh(ma::Mesh* m, ss << prefix; std::string tmp = ss.str(); const char* fileName = tmp.c_str(); - apf::writeVtkFiles(fileName, m); + apf::writeVtkFiles(fileName, m, dim); } void addTargetLocation(ma::Adapt* a, @@ -208,7 +209,7 @@ void dumpMeshWithFlag(ma::Adapt* a, } ss << prefix << "_" << std::setfill('0') << std::setw(3) << iter; - writeMesh(a->mesh, ss.str().c_str(), ""); + writeMesh(a->mesh, ss.str().c_str(), "", dim); apf::Field* colorField; colorField = a->mesh->findField(flagName); @@ -240,7 +241,9 @@ void createCavityMesh(ma::Adapt* a, cavityMesh->acceptChanges(); std::stringstream ss; - ss << a->input->debugFolder << "/"; + if (a->input->debugFolder) { + ss << a->input->debugFolder << "/"; + } ss << prefix; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index edf5235d5..5b2fa6285 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -910,6 +910,30 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } +void printFPP(Adapt* a, FirstProblemPlane* FPP) +{ + ma_dbg::addTargetLocation(a, "snap_target"); + EntityArray invalid; + for (int i=0; iproblemRegions.n; i++){ + invalid.append(FPP->problemRegions.e[i]); + } + ma_dbg::createCavityMesh(a, invalid, "invalid"); + + EntityArray pbFace; + pbFace.append(FPP->problemFace); + ma_dbg::createCavityMesh(a, pbFace, "pbFace"); + + EntityArray pbRegion; + pbRegion.append(FPP->problemRegion); + ma_dbg::createCavityMesh(a, pbRegion, "pbRegion"); + + for (int i=0; icommEdges.n; i++) + setFlag(a, FPP->commEdges.e[i], CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "commEdges", "commEdges"); + for (int i=0; icommEdges.n; i++) + clearFlag(a, FPP->commEdges.e[i], CHECKED); +} + bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityToBeat) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); @@ -927,6 +951,7 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityT bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { + printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; double qual = a->input->validQuality; @@ -935,19 +960,19 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) a->mesh->getDownward(FPP->problemFace, 1, pbEdges); switch(commEdges.n) { - case 2: { - Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); - Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + // case 2: { + // Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); + // Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); - for (int i=0; i<3; i++) { - Entity* pbVert[2]; - a->mesh->getDownward(pbEdges[i], 0, pbVert); - if (pbVert[0] == v1 && pbVert[1] == v2) break; - if (pbVert[1] == v1 && pbVert[0] == v2) break; - if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; - } - break; - } + // for (int i=0; i<3; i++) { + // Entity* pbVert[2]; + // a->mesh->getDownward(pbEdges[i], 0, pbVert); + // if (pbVert[0] == v1 && pbVert[1] == v2) break; + // if (pbVert[1] == v1 && pbVert[0] == v2) break; + // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; + // } + // break; + // } // case 3: { // for (int i=0; i<3; i++) // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; @@ -972,8 +997,6 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProblemPlane* FPP) { - bool flag = getFlag(a,FPP->vert,DONT_COLLAPSE); - if (!flag) setFlag(a,FPP->vert,DONT_COLLAPSE); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; double q = a->input->validQuality; @@ -997,7 +1020,6 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble } a->input->shouldForceAdaptation = shouldForce; - if (!flag) clearFlag(a,FPP->vert,DONT_COLLAPSE); return success; } diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 0de81e277..a2923866c 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -58,11 +58,11 @@ class FirstProblemPlane Entity* vert; Entity* problemFace; apf::Up commEdges; + apf::Up problemRegions; + Entity* problemRegion; private: Adapt* adapter; Tag* snapTag; - apf::Up problemRegions; - Entity* problemRegion; Vector intersection; double tol; bool find(); From 0375093e4696bb681a0b9353af03339ff6c19c25 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 24 Apr 2025 14:32:41 -0400 Subject: [PATCH 033/181] more FPP info --- ma/maDBG.cc | 2 +- ma/maSnap.cc | 63 +++++++++++++++++++++++++---------------- ma/maSnapper.h | 2 +- pumi-meshes | 2 +- test/aniso_adapt_cap.cc | 2 +- 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/ma/maDBG.cc b/ma/maDBG.cc index 2b4321f43..d16336195 100644 --- a/ma/maDBG.cc +++ b/ma/maDBG.cc @@ -169,7 +169,7 @@ void dumpMeshWithQualities(ma::Adapt* a, ss << std::setfill('0') << std::setw(3) << iter << "_"; ss << prefix; - writeMesh(a->mesh, ss.str().c_str(), ""); + writeMesh(a->mesh, ss.str().c_str(), "", -1); apf::Field* colorField; colorField = a->mesh->findField("qual_metric"); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 5b2fa6285..d9d0ffd5e 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -21,6 +21,8 @@ #include #include #include +#include +#include namespace ma { @@ -912,26 +914,31 @@ long snapTaggedVerts(Adapt* a, Tag* tag) void printFPP(Adapt* a, FirstProblemPlane* FPP) { - ma_dbg::addTargetLocation(a, "snap_target"); + apf::writeVtkFiles("FPP_mesh", a->mesh); + ma_dbg::addTargetLocation(a, "FPP_snap_target"); EntityArray invalid; for (int i=0; iproblemRegions.n; i++){ invalid.append(FPP->problemRegions.e[i]); } - ma_dbg::createCavityMesh(a, invalid, "invalid"); + ma_dbg::createCavityMesh(a, invalid, "FPP_invalid"); EntityArray pbFace; pbFace.append(FPP->problemFace); - ma_dbg::createCavityMesh(a, pbFace, "pbFace"); + ma_dbg::createCavityMesh(a, pbFace, "FPP_pbFace"); EntityArray pbRegion; pbRegion.append(FPP->problemRegion); - ma_dbg::createCavityMesh(a, pbRegion, "pbRegion"); + ma_dbg::createCavityMesh(a, pbRegion, "FPP_pbRegion"); for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "commEdges", "commEdges"); + ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_commEdges", "FPP_commEdges"); for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); + + setFlag(a, FPP->vert, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_vertex", "FPP_vertex"); + clearFlag(a, FPP->vert, CHECKED); } bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityToBeat) @@ -949,8 +956,12 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityT return true; } +static int numReached=1; + bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { + if (numReached++ != 1) return false; + printf("commEdges %d\n", FPP->commEdges.n); printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; double qual = a->input->validQuality; @@ -959,26 +970,30 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) Entity* pbEdges[3]; a->mesh->getDownward(FPP->problemFace, 1, pbEdges); - switch(commEdges.n) { - // case 2: { - // Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); - // Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + // switch(commEdges.n) { + // case 2: { + // Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); + // Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); - // for (int i=0; i<3; i++) { - // Entity* pbVert[2]; - // a->mesh->getDownward(pbEdges[i], 0, pbVert); - // if (pbVert[0] == v1 && pbVert[1] == v2) break; - // if (pbVert[1] == v1 && pbVert[0] == v2) break; - // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; - // } - // break; - // } - // case 3: { - // for (int i=0; i<3; i++) - // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; - // break; - // } - } + // for (int i=0; i<3; i++) { + // Entity* pbVert[2]; + // a->mesh->getDownward(pbEdges[i], 0, pbVert); + // if (pbVert[0] == v1 && pbVert[1] == v2) break; + // if (pbVert[1] == v1 && pbVert[0] == v2) break; + // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; + // } + // break; + // } + // case 3: { + // for (int i=0; i<3; i++) + // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; + // break; + // } + // } + + // for (int i=0; i Date: Thu, 24 Apr 2025 17:49:39 -0400 Subject: [PATCH 034/181] fixed FPP --- ma/maSnap.cc | 5 ++--- ma/maSnapper.cc | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index d9d0ffd5e..98b58bd24 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -960,7 +960,7 @@ static int numReached=1; bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { - if (numReached++ != 1) return false; + if (numReached++ != 8) return false; printf("commEdges %d\n", FPP->commEdges.n); printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; @@ -1014,7 +1014,6 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble { bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; - double q = a->input->validQuality; Vector position = getPosition(a->mesh, FPP->vert); Vector target; @@ -1030,7 +1029,7 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble double vertFPPdist = (vFPPCoord - target).getLength(); if (vertFPPdist > distTarget) continue; - success = tryCollapseEdge(a, edge, collapse, q); + success = tryCollapseEdge(a, edge, collapse, 0); if (success) break; //TODO: select from best quality instead of first } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 6c2ee6669..ac18e44b5 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -354,7 +354,7 @@ bool FirstProblemPlane::find() // ones should have been taken care of by this point } else - dists.push_back(minDist + 1.0 + tol); + dists.push_back(newDirection.getLength()); } } @@ -518,10 +518,10 @@ void FirstProblemPlane::findCommonEdges(apf::Up& cpRegions) flag = 0; break; } - if (flag) { - commEdges.e[commEdges.n] = edges[i]; - commEdges.n++; - } + } + if (flag) { + commEdges.e[commEdges.n] = edges[i]; + commEdges.n++; } } } From 7747e2a7d2c4968ed05b835f329234a5876eb921 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 25 Apr 2025 12:24:28 -0400 Subject: [PATCH 035/181] add classification --- ma/maDBG.cc | 21 +++++++++++++++++++++ ma/maDBG.h | 3 +++ ma/maSnap.cc | 16 ++++++++-------- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/ma/maDBG.cc b/ma/maDBG.cc index d16336195..f766a296c 100644 --- a/ma/maDBG.cc +++ b/ma/maDBG.cc @@ -46,6 +46,27 @@ void writeMesh(ma::Mesh* m, apf::writeVtkFiles(fileName, m, dim); } +void addClassification(ma::Adapt* a, + const char* fieldName) +{ + ma::Mesh* m = a->mesh; + apf::Field* field; + field = m->findField(fieldName); + if (field) + apf::destroyField(field); + + field = apf::createFieldOn(m, fieldName, apf::SCALAR); + ma::Entity* ent; + ma::Iterator* it; + it = m->begin(0); + while ( (ent = m->iterate(it)) ){ + ma::Model* g = m->toModel(ent); + double modelDimension = (double)m->getModelType(g); + apf::setComponents(field, ent, 0, &modelDimension); + } + m->end(it); +} + void addTargetLocation(ma::Adapt* a, const char* fieldName) { diff --git a/ma/maDBG.h b/ma/maDBG.h index 027a245fd..2d7ed62f9 100644 --- a/ma/maDBG.h +++ b/ma/maDBG.h @@ -25,6 +25,9 @@ void writeMesh(ma::Mesh* m, const char* prefix, const char* suffix); +void addClassification(ma::Adapt* a, + const char* fieldName); + void addTargetLocation(ma::Adapt* a, const char* fieldName); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 98b58bd24..af7741317 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -914,30 +914,29 @@ long snapTaggedVerts(Adapt* a, Tag* tag) void printFPP(Adapt* a, FirstProblemPlane* FPP) { - apf::writeVtkFiles("FPP_mesh", a->mesh); - ma_dbg::addTargetLocation(a, "FPP_snap_target"); + apf::writeVtkFiles("FPP_Mesh", a->mesh); EntityArray invalid; for (int i=0; iproblemRegions.n; i++){ invalid.append(FPP->problemRegions.e[i]); } - ma_dbg::createCavityMesh(a, invalid, "FPP_invalid"); + ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); EntityArray pbFace; pbFace.append(FPP->problemFace); - ma_dbg::createCavityMesh(a, pbFace, "FPP_pbFace"); + ma_dbg::createCavityMesh(a, pbFace, "FPP_Face"); EntityArray pbRegion; pbRegion.append(FPP->problemRegion); - ma_dbg::createCavityMesh(a, pbRegion, "FPP_pbRegion"); + ma_dbg::createCavityMesh(a, pbRegion, "FPP_Region"); for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_commEdges", "FPP_commEdges"); + ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); setFlag(a, FPP->vert, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_vertex", "FPP_vertex"); + ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_Vertex", "FPP_Vertex"); clearFlag(a, FPP->vert, CHECKED); } @@ -960,7 +959,7 @@ static int numReached=1; bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { - if (numReached++ != 8) return false; + if (numReached++ != 1) return false; printf("commEdges %d\n", FPP->commEdges.n); printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; @@ -1114,6 +1113,7 @@ void printSnapFields(Adapt* a, Mesh* m, std::string name) { apf::writeVtkFiles(name.c_str(), m); ma_dbg::addTargetLocation(a, "snap_target"); + ma_dbg::addClassification(a, "classification"); apf::writeVtkFiles((name+"_fields").c_str(), m, 1); } From 5fc7efab21cdc5708c0a7d19c2dfac37a15f4aa8 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Apr 2025 15:57:08 -0400 Subject: [PATCH 036/181] fixed writing FPP face --- ma/maSnap.cc | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index af7741317..295aa785c 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -921,23 +921,21 @@ void printFPP(Adapt* a, FirstProblemPlane* FPP) } ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); - EntityArray pbFace; - pbFace.append(FPP->problemFace); - ma_dbg::createCavityMesh(a, pbFace, "FPP_Face"); - - EntityArray pbRegion; - pbRegion.append(FPP->problemRegion); - ma_dbg::createCavityMesh(a, pbRegion, "FPP_Region"); - - for (int i=0; icommEdges.n; i++) - setFlag(a, FPP->commEdges.e[i], CHECKED); + for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); - for (int i=0; icommEdges.n; i++) - clearFlag(a, FPP->commEdges.e[i], CHECKED); + for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); setFlag(a, FPP->vert, CHECKED); ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_Vertex", "FPP_Vertex"); clearFlag(a, FPP->vert, CHECKED); + + setFlag(a, FPP->problemFace, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Face", "FPP_Face"); + clearFlag(a, FPP->problemFace, CHECKED); + + setFlag(a, FPP->problemRegion, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Region", "FPP_Region"); + clearFlag(a, FPP->problemRegion, CHECKED); } bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityToBeat) @@ -963,7 +961,7 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) printf("commEdges %d\n", FPP->commEdges.n); printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; - double qual = a->input->validQuality; + double qual = a->input->goodQuality; //Try to reduce num common edges to one Entity* pbEdges[3]; From 6a460aa30bc4c39ba87db3bc6c29fd7d16f52f79 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Apr 2025 22:12:21 -0400 Subject: [PATCH 037/181] collapse best quality --- ma/maCollapse.cc | 39 ++++++++++++++++++++++++++++++++++++++- ma/maCollapse.h | 2 ++ ma/maSnap.cc | 45 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 184e7e2be..faa8b4147 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -55,6 +55,25 @@ bool Collapse::tryThisDirectionNoCancel(double qualityToBeat) return true; } +double Collapse::getQualityThisDirection() { + PCU_ALWAYS_ASSERT( ! adapt->mesh->isShared(vertToCollapse)); + rebuildElements(); + // check quality of linear t before fitting + if ((adapt->mesh->getDimension()==2) + &&( ! isGood2DMesh())) + return -1; + // check the linear quality of tets before fitting + // reject if one is negative + if(adapt->mesh->getDimension()==3 && cavity.shouldFit + && !areTetsValid(adapt->mesh,newElements)) + return -1; + // since they are okay in a linear sense, now fit and do a quality assessment + fitElements(); + double q = getWorstQuality(adapt, newElements); + destroyNewElements(); + return q; +} + bool Collapse::tryThisDirection(double qualityToBeat) { if (!tryThisDirectionNoCancel(qualityToBeat)) { @@ -64,6 +83,7 @@ bool Collapse::tryThisDirection(double qualityToBeat) return true; } +//TODO: Test this change bool Collapse::tryBothDirections(double qualityToBeat) { computeElementSets(); @@ -74,8 +94,11 @@ bool Collapse::tryBothDirections(double qualityToBeat) qualityToBeat = std::min(adapt->input->goodQuality, std::max(getOldQuality(),adapt->input->validQuality)); - if (tryThisDirection(qualityToBeat)) + if (tryThisDirectionNoCancel(qualityToBeat)) return true; + else + destroyNewElements(); + if ( ! getFlag(adapt,vertToKeep,COLLAPSE)) return false; std::swap(vertToKeep,vertToCollapse); @@ -87,6 +110,20 @@ bool Collapse::tryBothDirections(double qualityToBeat) return tryThisDirection(qualityToBeat); } +double Collapse::getQualityFromCollapse() { + computeElementSets(); + double q = getQualityThisDirection(); + if (q == -1) { + if (!getFlag(adapt,vertToKeep,COLLAPSE)) + return false; + std::swap(vertToKeep,vertToCollapse); + computeElementSets(); + q = std::max(q, getQualityThisDirection()); + } + unmark(); + return q; +} + bool Collapse::setEdge(Entity* e) { if (getFlag(adapt,e,DONT_COLLAPSE)) diff --git a/ma/maCollapse.h b/ma/maCollapse.h index bf70c50a3..636f2139f 100644 --- a/ma/maCollapse.h +++ b/ma/maCollapse.h @@ -41,6 +41,8 @@ class Collapse bool tryThisDirectionNoCancel(double qualityToBeat); bool tryBothDirections(double qualityToBeat); void getOldElements(EntityArray& oldElements); + double getQualityThisDirection(); + double getQualityFromCollapse(); double getOldQuality(); Adapt* adapt; Entity* edge; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 295aa785c..1e03c0661 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -938,21 +938,46 @@ void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemRegion, CHECKED); } -bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse, double qualityToBeat) +bool matchingClassification(Adapt* a, Entity* edge) +{ + Entity* vertex[2]; + a->mesh->getDownward(edge,0,vertex); + int md1 = a->mesh->getModelType(a->mesh->toModel(vertex[0])); + int md2 = a->mesh->getModelType(a->mesh->toModel(vertex[1])); + return md1 == md2; +} + +bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + // if (matchingClassification(a, edge)) + // return false; if (!collapse.setEdge(edge)) return false; if (!collapse.checkClass()) return false; if (!collapse.checkTopo()) return false; - if (!collapse.tryBothDirections(qualityToBeat)) + if (!collapse.tryBothDirections(0)) return false; collapse.destroyOldElements(); return true; } +double getQualityFromCollapse(Adapt* a, Entity* edge, Collapse& collapse) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + // if (matchingClassification(a, edge)) + // return -1; + if (!collapse.setEdge(edge)) + return -1; + if (!collapse.checkClass()) + return -1; + if (!collapse.checkTopo()) + return -1; + return collapse.getQualityFromCollapse(); +} + static int numReached=1; bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) @@ -1017,7 +1042,9 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble a->mesh->getDoubleTag(FPP->vert, snapTag, &target[0]); double distTarget = (position - target).getLength(); - bool success = false; + double bestQuality = -1; + Entity* bestEdge; + for (size_t i = 0; i < FPP->commEdges.n; ++i) { Entity* edge = FPP->commEdges.e[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); @@ -1026,12 +1053,18 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble double vertFPPdist = (vFPPCoord - target).getLength(); if (vertFPPdist > distTarget) continue; - success = tryCollapseEdge(a, edge, collapse, 0); - if (success) break; //TODO: select from best quality instead of first + double quality = getQualityFromCollapse(a, edge, collapse); + if (quality > bestQuality) { + bestQuality = quality; + bestEdge = edge; + } } - a->input->shouldForceAdaptation = shouldForce; + bool success = false; + if (bestQuality > -1) + success = tryCollapseEdge(a, bestEdge, collapse); + a->input->shouldForceAdaptation = shouldForce; return success; } From 766549a5f36357e9e6e0f7a652bdfa7f83fbefba Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Apr 2025 22:45:11 -0400 Subject: [PATCH 038/181] collapsing all edges step one --- ma/maSnap.cc | 66 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 1e03c0661..892946d76 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -950,8 +950,8 @@ bool matchingClassification(Adapt* a, Entity* edge) bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - // if (matchingClassification(a, edge)) - // return false; + if (matchingClassification(a, edge)) + return false; if (!collapse.setEdge(edge)) return false; if (!collapse.checkClass()) @@ -967,8 +967,8 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) double getQualityFromCollapse(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - // if (matchingClassification(a, edge)) - // return -1; + if (matchingClassification(a, edge)) + return -1; if (!collapse.setEdge(edge)) return -1; if (!collapse.checkClass()) @@ -982,11 +982,12 @@ static int numReached=1; bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { - if (numReached++ != 1) return false; - printf("commEdges %d\n", FPP->commEdges.n); - printFPP(a, FPP); + // if (numReached++ != 1) return false; + // printf("commEdges %d\n", FPP->commEdges.n); + // printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; - double qual = a->input->goodQuality; + bool shouldForce = a->input->shouldForceAdaptation; + a->input->shouldForceAdaptation = true; //Try to reduce num common edges to one Entity* pbEdges[3]; @@ -1013,23 +1014,40 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) // } // } - // for (int i=0; imesh, edge, FPP->vert); - // apf::Up adjEdges; - // a->mesh->getUp(vertexFPP, adjEdges); - // for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; - // if (tryCollapseEdge(a, edgeDel, collapse, qual)) return true; - // } - // } - return false; + for (int i=0; i bestQuality) { + bestQuality = quality; + bestEdge = commEdges.e[i]; + } + } + + for (int i=0; imesh, edge, FPP->vert); + apf::Up adjEdges; + a->mesh->getUp(vertexFPP, adjEdges); + for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; + double quality = getQualityFromCollapse(a, edgeDel, collapse); + if (quality > bestQuality) { + bestQuality = quality; + bestEdge = edgeDel; + } + } + } + + bool success = false; + if (bestQuality > -1) + success = tryCollapseEdge(a, bestEdge, collapse); + + a->input->shouldForceAdaptation = shouldForce; + return success; } bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProblemPlane* FPP) From 2824a714519d89147c62183a4c1d84081b8d9b0d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Apr 2025 23:08:09 -0400 Subject: [PATCH 039/181] seperated reduce common edges --- ma/maSnap.cc | 84 ++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 892946d76..148eb2528 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -978,41 +978,14 @@ double getQualityFromCollapse(Adapt* a, Entity* edge, Collapse& collapse) return collapse.getQualityFromCollapse(); } +//TODO: remove static int numReached=1; bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { // if (numReached++ != 1) return false; - // printf("commEdges %d\n", FPP->commEdges.n); // printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; - bool shouldForce = a->input->shouldForceAdaptation; - a->input->shouldForceAdaptation = true; - - //Try to reduce num common edges to one - Entity* pbEdges[3]; - a->mesh->getDownward(FPP->problemFace, 1, pbEdges); - - // switch(commEdges.n) { - // case 2: { - // Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); - // Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); - - // for (int i=0; i<3; i++) { - // Entity* pbVert[2]; - // a->mesh->getDownward(pbEdges[i], 0, pbVert); - // if (pbVert[0] == v1 && pbVert[1] == v2) break; - // if (pbVert[1] == v1 && pbVert[0] == v2) break; - // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; - // } - // break; - // } - // case 3: { - // for (int i=0; i<3; i++) - // if (tryCollapseEdge(a, pbEdges[i], collapse, qual)) return true; - // break; - // } - // } double bestQuality = -1; Entity* bestEdge; @@ -1042,19 +1015,44 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) } } - bool success = false; - if (bestQuality > -1) - success = tryCollapseEdge(a, bestEdge, collapse); + if (bestQuality > -1) + return tryCollapseEdge(a, bestEdge, collapse); + else return false; +} - a->input->shouldForceAdaptation = shouldForce; - return success; +bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +{ + apf::Up& commEdges = FPP->commEdges; + if (commEdges.n > 0) + printf("===MAKE SURE TO TEST===\n"); + + Entity* pbEdges[3]; + a->mesh->getDownward(FPP->problemFace, 1, pbEdges); + switch(commEdges.n) { + case 2: { + Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); + Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + + for (int i=0; i<3; i++) { + Entity* pbVert[2]; + a->mesh->getDownward(pbEdges[i], 0, pbVert); + if (pbVert[0] == v1 && pbVert[1] == v2) break; + if (pbVert[1] == v1 && pbVert[0] == v2) break; + if (tryCollapseEdge(a, pbEdges[i], collapse)) return true; + } + break; + } + case 3: { + for (int i=0; i<3; i++) + if (tryCollapseEdge(a, pbEdges[i], collapse)) return true; + break; + } + } + return false; } bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProblemPlane* FPP) { - bool shouldForce = a->input->shouldForceAdaptation; - a->input->shouldForceAdaptation = true; - Vector position = getPosition(a->mesh, FPP->vert); Vector target; a->mesh->getDoubleTag(FPP->vert, snapTag, &target[0]); @@ -1078,12 +1076,9 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble } } - bool success = false; - if (bestQuality > -1) - success = tryCollapseEdge(a, bestEdge, collapse); - - a->input->shouldForceAdaptation = shouldForce; - return success; + if (bestQuality > -1) + return tryCollapseEdge(a, bestEdge, collapse); + else return false; } FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) @@ -1131,6 +1126,9 @@ void trySnapping(Adapt* a, Tag* snapTag) collapse.Init(a); int notProcessed = refine->vtxToSnap.size(); print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); + bool shouldForce = a->input->shouldForceAdaptation; + a->input->shouldForceAdaptation = true; + while (notProcessed > 0) { notProcessed--; @@ -1143,6 +1141,7 @@ void trySnapping(Adapt* a, Tag* snapTag) FirstProblemPlane* FPP = 0; if (!success) FPP = getFPP(a, vertex, snapTag, invalid); if (!success) success = tryCollapseToVertex(a, collapse, snapTag, FPP); + if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (success) { @@ -1155,6 +1154,7 @@ void trySnapping(Adapt* a, Tag* snapTag) if (FPP) delete FPP; } + a->input->shouldForceAdaptation = shouldForce; print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); } From 974584a3c3089a9ba11e885188ce43665b377740 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Apr 2025 18:14:50 -0400 Subject: [PATCH 040/181] get best quality collapse --- ma/maSnap.cc | 63 ++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 148eb2528..eb26fb521 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -964,18 +964,27 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) return true; } -double getQualityFromCollapse(Adapt* a, Entity* edge, Collapse& collapse) +struct BestCollapse +{ + double quality=-1; + Entity* edge; +}; + +void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestCollapse& best) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); if (matchingClassification(a, edge)) - return -1; + return; if (!collapse.setEdge(edge)) - return -1; + return; if (!collapse.checkClass()) - return -1; + return; if (!collapse.checkTopo()) - return -1; - return collapse.getQualityFromCollapse(); + return; + double quality = collapse.getQualityFromCollapse(); + if (quality < best.quality) return; + best.quality = quality; + best.edge = edge; } //TODO: remove @@ -987,15 +996,10 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) // printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; - double bestQuality = -1; - Entity* bestEdge; + BestCollapse best; for (int i=0; i bestQuality) { - bestQuality = quality; - bestEdge = commEdges.e[i]; - } + getBestQualityCollapse(a, commEdges.e[i], collapse, best); } for (int i=0; imesh, FPP->problemFace, edgeDel)) continue; - double quality = getQualityFromCollapse(a, edgeDel, collapse); - if (quality > bestQuality) { - bestQuality = quality; - bestEdge = edgeDel; - } + //TODO: MISSING CONDITION FROM OLD CODE + getBestQualityCollapse(a, edgeDel, collapse, best); } } - if (bestQuality > -1) - return tryCollapseEdge(a, bestEdge, collapse); + if (best.quality > -1) + return tryCollapseEdge(a, best.edge, collapse); else return false; } @@ -1051,15 +1052,14 @@ bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) return false; } -bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProblemPlane* FPP) +bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { Vector position = getPosition(a->mesh, FPP->vert); Vector target; - a->mesh->getDoubleTag(FPP->vert, snapTag, &target[0]); + a->mesh->getDoubleTag(FPP->vert, FPP->snapTag, &target[0]); double distTarget = (position - target).getLength(); - double bestQuality = -1; - Entity* bestEdge; + BestCollapse best; for (size_t i = 0; i < FPP->commEdges.n; ++i) { Entity* edge = FPP->commEdges.e[i]; @@ -1068,16 +1068,11 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, Tag* snapTag, FirstProble //TODO: add logic for boundary layers double vertFPPdist = (vFPPCoord - target).getLength(); if (vertFPPdist > distTarget) continue; - - double quality = getQualityFromCollapse(a, edge, collapse); - if (quality > bestQuality) { - bestQuality = quality; - bestEdge = edge; - } + getBestQualityCollapse(a, edge, collapse, best); } - if (bestQuality > -1) - return tryCollapseEdge(a, bestEdge, collapse); + if (best.quality > -1) + return tryCollapseEdge(a, best.edge, collapse); else return false; } @@ -1140,8 +1135,8 @@ void trySnapping(Adapt* a, Tag* snapTag) FirstProblemPlane* FPP = 0; if (!success) FPP = getFPP(a, vertex, snapTag, invalid); - if (!success) success = tryCollapseToVertex(a, collapse, snapTag, FPP); - if (!success) success = tryReduceCommonEdges(a, collapse, FPP); + if (!success) success = tryCollapseToVertex(a, collapse, FPP); + // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (success) { From ddd67b3a2b307da70d1dc4abf6631aee5a0ed15c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Apr 2025 18:19:11 -0400 Subject: [PATCH 041/181] reduce common edges --- ma/maSnap.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index eb26fb521..fcc386bfc 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -1024,8 +1024,7 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; - if (commEdges.n > 0) - printf("===MAKE SURE TO TEST===\n"); + BestCollapse best; Entity* pbEdges[3]; a->mesh->getDownward(FPP->problemFace, 1, pbEdges); @@ -1039,17 +1038,19 @@ bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) a->mesh->getDownward(pbEdges[i], 0, pbVert); if (pbVert[0] == v1 && pbVert[1] == v2) break; if (pbVert[1] == v1 && pbVert[0] == v2) break; - if (tryCollapseEdge(a, pbEdges[i], collapse)) return true; + getBestQualityCollapse(a, pbEdges[i], collapse, best); } break; } case 3: { for (int i=0; i<3; i++) - if (tryCollapseEdge(a, pbEdges[i], collapse)) return true; + getBestQualityCollapse(a, pbEdges[i], collapse, best); break; } } - return false; + if (best.quality > -1) + return tryCollapseEdge(a, best.edge, collapse); + else return false; } bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) @@ -1136,7 +1137,7 @@ void trySnapping(Adapt* a, Tag* snapTag) FirstProblemPlane* FPP = 0; if (!success) FPP = getFPP(a, vertex, snapTag, invalid); if (!success) success = tryCollapseToVertex(a, collapse, FPP); - // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); + if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (success) { From 22834732775f6d68547888cc876a68e67a68435f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Apr 2025 23:48:37 -0400 Subject: [PATCH 042/181] print first failed fpp --- ma/maSnap.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index fcc386bfc..25ee72203 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -987,15 +987,9 @@ void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestColl best.edge = edge; } -//TODO: remove -static int numReached=1; - bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { - // if (numReached++ != 1) return false; - // printFPP(a, FPP); apf::Up& commEdges = FPP->commEdges; - BestCollapse best; for (int i=0; imesh; @@ -1140,6 +1137,8 @@ void trySnapping(Adapt* a, Tag* snapTag) if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); + if (!success && numReached++ == 1) printFPP(a, FPP); + if (success) { mesh->removeTag(vertex,snapTag); clearFlag(a, vertex, SNAP); From e6475c31299519ed85739b4d6da5bf503a1d144b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 1 May 2025 17:05:32 -0400 Subject: [PATCH 043/181] make sure snap flag isn't lost --- ma/maSnap.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 25ee72203..161e37e6d 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -950,6 +950,10 @@ bool matchingClassification(Adapt* a, Entity* edge) bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + + Entity* vertex[2]; + a->mesh->getDownward(edge,0,vertex); + if (matchingClassification(a, edge)) return false; if (!collapse.setEdge(edge)) @@ -961,6 +965,13 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) if (!collapse.tryBothDirections(0)) return false; collapse.destroyOldElements(); + + Entity* collapsed = vertex[0]; + Entity* kept = vertex[1]; + if (a->mesh->hasUp(collapsed)) + std::swap(collapsed, kept); + PCU_ALWAYS_ASSERT(a->mesh->hasUp(kept)); + PCU_ALWAYS_ASSERT(!getFlag(a, collapsed, SNAP)); //TODO REMOVE return true; } @@ -1108,9 +1119,6 @@ bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) return false; } -//TODO: remove -static int numReached=1; - void trySnapping(Adapt* a, Tag* snapTag) { Mesh* mesh = a->mesh; @@ -1121,6 +1129,7 @@ void trySnapping(Adapt* a, Tag* snapTag) print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; + int numFailed = 0; while (notProcessed > 0) { @@ -1137,7 +1146,8 @@ void trySnapping(Adapt* a, Tag* snapTag) if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); - if (!success && numReached++ == 1) printFPP(a, FPP); + if (!success) numFailed++; + if (numFailed == 1) printFPP(a, FPP); if (success) { mesh->removeTag(vertex,snapTag); From 31737b4c6aca16cbea379cfe34f4874de4df65a5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 1 May 2025 18:46:33 -0400 Subject: [PATCH 044/181] try collapse multiple times --- ma/maSnap.cc | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 161e37e6d..c095f8706 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -934,7 +934,7 @@ void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemFace, CHECKED); setFlag(a, FPP->problemRegion, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Region", "FPP_Region"); + ma_dbg::dumpMeshWithFlag(a, 0, 3, CHECKED, "FPP_Region", "FPP_Region"); clearFlag(a, FPP->problemRegion, CHECKED); } @@ -951,10 +951,8 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - Entity* vertex[2]; - a->mesh->getDownward(edge,0,vertex); - - if (matchingClassification(a, edge)) + int md = a->mesh->getModelType(a->mesh->toModel(edge)); + if (md < 3) return false; if (!collapse.setEdge(edge)) return false; @@ -965,13 +963,6 @@ bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) if (!collapse.tryBothDirections(0)) return false; collapse.destroyOldElements(); - - Entity* collapsed = vertex[0]; - Entity* kept = vertex[1]; - if (a->mesh->hasUp(collapsed)) - std::swap(collapsed, kept); - PCU_ALWAYS_ASSERT(a->mesh->hasUp(kept)); - PCU_ALWAYS_ASSERT(!getFlag(a, collapsed, SNAP)); //TODO REMOVE return true; } @@ -984,7 +975,9 @@ struct BestCollapse void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestCollapse& best) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - if (matchingClassification(a, edge)) + + int md = a->mesh->getModelType(a->mesh->toModel(edge)); + if (md < 3) return; if (!collapse.setEdge(edge)) return; @@ -1121,27 +1114,30 @@ bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) void trySnapping(Adapt* a, Tag* snapTag) { - Mesh* mesh = a->mesh; Refine* refine = a->refine; Collapse collapse; collapse.Init(a); - int notProcessed = refine->vtxToSnap.size(); - print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", notProcessed); + print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", refine->vtxToSnap.size()); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; int numFailed = 0; - while (notProcessed > 0) + while (refine->vtxToSnap.size() > 0) { - notProcessed--; Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); apf::Up invalid; bool success = tryReposition(a, vertex, snapTag, invalid); - FirstProblemPlane* FPP = 0; - if (!success) FPP = getFPP(a, vertex, snapTag, invalid); + if (success) { + a->mesh->removeTag(vertex,snapTag); + clearFlag(a, vertex, SNAP); + continue; + } + + FirstProblemPlane* FPP = getFPP(a, vertex, snapTag, invalid); + if (!success) success = tryCollapseToVertex(a, collapse, FPP); if (!success) success = tryReduceCommonEdges(a, collapse, FPP); if (!success) success = tryCollapseTetEdges(a, collapse, FPP); @@ -1149,18 +1145,13 @@ void trySnapping(Adapt* a, Tag* snapTag) if (!success) numFailed++; if (numFailed == 1) printFPP(a, FPP); - if (success) { - mesh->removeTag(vertex,snapTag); - clearFlag(a, vertex, SNAP); - } - else - refine->vtxToSnap.push(vertex); + if (success) refine->vtxToSnap.push(vertex); if (FPP) delete FPP; } a->input->shouldForceAdaptation = shouldForce; - print(a->mesh->getPCU(), "Number of vertices failed %d\n", refine->vtxToSnap.size()); + print(a->mesh->getPCU(), "Number of vertices failed %d\n", numFailed); } void printSnapFields(Adapt* a, Mesh* m, std::string name) From 7cbd69ed1a7e5d0e7ee9d131eb31713a50b43742 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 3 May 2025 15:32:24 -0400 Subject: [PATCH 045/181] same side --- ma/maSnap.cc | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index c095f8706..859e53f1d 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -938,22 +938,10 @@ void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemRegion, CHECKED); } -bool matchingClassification(Adapt* a, Entity* edge) -{ - Entity* vertex[2]; - a->mesh->getDownward(edge,0,vertex); - int md1 = a->mesh->getModelType(a->mesh->toModel(vertex[0])); - int md2 = a->mesh->getModelType(a->mesh->toModel(vertex[1])); - return md1 == md2; -} - bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - int md = a->mesh->getModelType(a->mesh->toModel(edge)); - if (md < 3) - return false; if (!collapse.setEdge(edge)) return false; if (!collapse.checkClass()) @@ -976,8 +964,7 @@ void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestColl { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - int md = a->mesh->getModelType(a->mesh->toModel(edge)); - if (md < 3) + if (!a->sizeField->shouldCollapse(edge)) return; if (!collapse.setEdge(edge)) return; @@ -991,6 +978,26 @@ void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestColl best.edge = edge; } +bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) +{ + Entity* faceVert[3]; + a->mesh->getDownward(face, 0, faceVert); + Vector facePos[3]; + for (int i=0; i < 3; ++i) + facePos[i] = getPosition(a->mesh,faceVert[i]); + + Vector normal = apf::cross((facePos[1]-facePos[0]),(facePos[2]-facePos[0])); + Vector testPos = getPosition(a->mesh, testVert); + Vector refPos = getPosition(a->mesh, refVert); + const double tol=1e-12; + + double dr = (testPos - facePos[0]) * normal; + if (dr*dr < tol) return false; //testVert is on the face + double ds = (refPos - facePos[0]) * normal; + if (dr*ds < 0.0) return false; //different sides of face + return true; //same side of face +} + bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; @@ -1009,7 +1016,8 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) Entity* edgeDel = adjEdges.e[j]; if (edgeDel==edge) continue; if (isLowInHigh(a->mesh, FPP->problemFace, edgeDel)) continue; - //TODO: MISSING CONDITION FROM OLD CODE + Entity* vertDel = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); + if (sameSide(a, vertDel, FPP->vert, FPP->problemFace)) continue; getBestQualityCollapse(a, edgeDel, collapse, best); } } @@ -1121,9 +1129,11 @@ void trySnapping(Adapt* a, Tag* snapTag) bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; int numFailed = 0; + int startSize = refine->vtxToSnap.size(); while (refine->vtxToSnap.size() > 0) { + if (startSize-- == 0) break; //Stop after one move Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); From f3393b48351b0fafe43bc8cb5082812f5b6b020f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 8 May 2025 15:57:11 -0400 Subject: [PATCH 046/181] added size check --- ma/maCollapse.cc | 32 +++++++++++++++++++++++++++++--- ma/maCollapse.h | 1 + ma/maSnap.cc | 8 +++----- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index faa8b4147..d3b90203f 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -55,6 +55,32 @@ bool Collapse::tryThisDirectionNoCancel(double qualityToBeat) return true; } +bool Collapse::edgesGoodSize() { + PCU_ALWAYS_ASSERT(elementsToKeep.size()); + PCU_ALWAYS_ASSERT(elementsToKeep.size() == newElements.size()); + size_t i=0; + double maxSize=0; + double ratioAtMaxSize=0; + APF_ITERATE(EntitySet,elementsToKeep,it) { + Entity* edgesBefore[6]; + adapt->mesh->getDownward(*it,1,edgesBefore); + Entity* edgesAfter[6]; + adapt->mesh->getDownward(newElements[i++],1,edgesAfter); + for (int j=0; j<6; j++) { + double sizeBefore = adapt->sizeField->measure(edgesBefore[j]); + double sizeAfter = adapt->sizeField->measure(edgesAfter[j]); + double ratio = sizeAfter/sizeBefore; + if (sizeAfter > maxSize) { + maxSize = sizeAfter; + ratioAtMaxSize = ratio; + } + } + } + // printf("maxSize %f Ratio %f\n", maxSize, ratioAtMaxSize); + if (maxSize > 1.5 && ratioAtMaxSize > 1.44 ) return false; + return true; +} + double Collapse::getQualityThisDirection() { PCU_ALWAYS_ASSERT( ! adapt->mesh->isShared(vertToCollapse)); rebuildElements(); @@ -69,9 +95,7 @@ double Collapse::getQualityThisDirection() { return -1; // since they are okay in a linear sense, now fit and do a quality assessment fitElements(); - double q = getWorstQuality(adapt, newElements); - destroyNewElements(); - return q; + return getWorstQuality(adapt, newElements); } bool Collapse::tryThisDirection(double qualityToBeat) @@ -113,12 +137,14 @@ bool Collapse::tryBothDirections(double qualityToBeat) double Collapse::getQualityFromCollapse() { computeElementSets(); double q = getQualityThisDirection(); + destroyNewElements(); if (q == -1) { if (!getFlag(adapt,vertToKeep,COLLAPSE)) return false; std::swap(vertToKeep,vertToCollapse); computeElementSets(); q = std::max(q, getQualityThisDirection()); + destroyNewElements(); } unmark(); return q; diff --git a/ma/maCollapse.h b/ma/maCollapse.h index 636f2139f..2500e9b6f 100644 --- a/ma/maCollapse.h +++ b/ma/maCollapse.h @@ -41,6 +41,7 @@ class Collapse bool tryThisDirectionNoCancel(double qualityToBeat); bool tryBothDirections(double qualityToBeat); void getOldElements(EntityArray& oldElements); + bool edgesGoodSize(); double getQualityThisDirection(); double getQualityFromCollapse(); double getOldQuality(); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 859e53f1d..c026669a8 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -964,8 +964,6 @@ void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestColl { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - if (!a->sizeField->shouldCollapse(edge)) - return; if (!collapse.setEdge(edge)) return; if (!collapse.checkClass()) @@ -1149,11 +1147,11 @@ void trySnapping(Adapt* a, Tag* snapTag) FirstProblemPlane* FPP = getFPP(a, vertex, snapTag, invalid); if (!success) success = tryCollapseToVertex(a, collapse, FPP); - if (!success) success = tryReduceCommonEdges(a, collapse, FPP); - if (!success) success = tryCollapseTetEdges(a, collapse, FPP); + // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); + // if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (!success) numFailed++; - if (numFailed == 1) printFPP(a, FPP); + if (!success && numFailed == 1) printFPP(a, FPP); if (success) refine->vtxToSnap.push(vertex); From f1542389d8daba6db08b3d997c866941423e4abc Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 8 May 2025 23:44:30 -0400 Subject: [PATCH 047/181] collapse one direction --- ma/maSnap.cc | 83 ++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index c026669a8..336384ada 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -938,42 +938,49 @@ void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemRegion, CHECKED); } -bool tryCollapseEdge(Adapt* a, Entity* edge, Collapse& collapse) +bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - - if (!collapse.setEdge(edge)) - return false; - if (!collapse.checkClass()) - return false; - if (!collapse.checkTopo()) - return false; - if (!collapse.tryBothDirections(0)) - return false; - collapse.destroyOldElements(); - return true; + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + + bool result = false; + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo() && + collapse.tryBothDirections(0)) { + collapse.destroyOldElements(); + result = true; + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); + return result; } struct BestCollapse { double quality=-1; Entity* edge; + Entity* keep; }; -void getBestQualityCollapse(Adapt* a, Entity* edge, Collapse& collapse, BestCollapse& best) +void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, BestCollapse& best) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - - if (!collapse.setEdge(edge)) - return; - if (!collapse.checkClass()) - return; - if (!collapse.checkTopo()) - return; - double quality = collapse.getQualityFromCollapse(); - if (quality < best.quality) return; - best.quality = quality; - best.edge = edge; + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo()) { + double quality = collapse.getQualityFromCollapse(); + if (quality > 0 && quality > best.quality) { + best.quality = quality; + best.edge = edge; + best.keep = keep; + } + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); } bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) @@ -1002,7 +1009,7 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) BestCollapse best; for (int i=0; imesh, FPP->problemFace, edgeDel)) continue; - Entity* vertDel = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); - if (sameSide(a, vertDel, FPP->vert, FPP->problemFace)) continue; - getBestQualityCollapse(a, edgeDel, collapse, best); + Entity* vertKeep = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); + if (sameSide(a, vertKeep, FPP->vert, FPP->problemFace)) continue; + getBestQualityCollapse(a, edgeDel, vertKeep, collapse, best); } } if (best.quality > -1) - return tryCollapseEdge(a, best.edge, collapse); + return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } @@ -1042,18 +1049,18 @@ bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) a->mesh->getDownward(pbEdges[i], 0, pbVert); if (pbVert[0] == v1 && pbVert[1] == v2) break; if (pbVert[1] == v1 && pbVert[0] == v2) break; - getBestQualityCollapse(a, pbEdges[i], collapse, best); + getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); } break; } case 3: { for (int i=0; i<3; i++) - getBestQualityCollapse(a, pbEdges[i], collapse, best); + getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); break; } } if (best.quality > -1) - return tryCollapseEdge(a, best.edge, collapse); + return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } @@ -1071,13 +1078,13 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); //TODO: add logic for boundary layers - double vertFPPdist = (vFPPCoord - target).getLength(); - if (vertFPPdist > distTarget) continue; - getBestQualityCollapse(a, edge, collapse, best); + double distToFPPVert = (vFPPCoord - target).getLength(); + if (distToFPPVert > distTarget) continue; + getBestQualityCollapse(a, edge, FPP->vert, collapse, best); } if (best.quality > -1) - return tryCollapseEdge(a, best.edge, collapse); + return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } @@ -1131,7 +1138,7 @@ void trySnapping(Adapt* a, Tag* snapTag) while (refine->vtxToSnap.size() > 0) { - if (startSize-- == 0) break; //Stop after one move + if (startSize-- == 0) break; //TEMP: Stop after one move Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); @@ -1148,7 +1155,7 @@ void trySnapping(Adapt* a, Tag* snapTag) if (!success) success = tryCollapseToVertex(a, collapse, FPP); // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); - // if (!success) success = tryCollapseTetEdges(a, collapse, FPP); + if (!success) success = tryCollapseTetEdges(a, collapse, FPP); if (!success) numFailed++; if (!success && numFailed == 1) printFPP(a, FPP); From e4dbbef9b4462861698cc704477f7ca5cdd773c6 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 10 May 2025 14:46:28 -0400 Subject: [PATCH 048/181] quality greater than zero --- ma/maSnap.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 336384ada..c57127033 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -974,7 +974,7 @@ void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collapse& coll collapse.checkClass() && collapse.checkTopo()) { double quality = collapse.getQualityFromCollapse(); - if (quality > 0 && quality > best.quality) { + if (quality > best.quality) { best.quality = quality; best.edge = edge; best.keep = keep; @@ -1027,7 +1027,7 @@ bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) } } - if (best.quality > -1) + if (best.quality > 0) return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } @@ -1059,7 +1059,7 @@ bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) break; } } - if (best.quality > -1) + if (best.quality > 0) return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } @@ -1083,7 +1083,7 @@ bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) getBestQualityCollapse(a, edge, FPP->vert, collapse, best); } - if (best.quality > -1) + if (best.quality > 0) return tryCollapseEdge(a, best.edge, best.keep, collapse); else return false; } From 776b8ff2e8522b56800b9690813312adc898338b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 10 May 2025 15:46:24 -0400 Subject: [PATCH 049/181] moved snap code --- ma/maSnap.cc | 239 +----------------------------- ma/maSnapper.cc | 386 +++++++++++++++++++++++++++++------------------- 2 files changed, 237 insertions(+), 388 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index c57127033..3ccd7305a 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -912,221 +912,9 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void printFPP(Adapt* a, FirstProblemPlane* FPP) -{ - apf::writeVtkFiles("FPP_Mesh", a->mesh); - EntityArray invalid; - for (int i=0; iproblemRegions.n; i++){ - invalid.append(FPP->problemRegions.e[i]); - } - ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); - - for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); - for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); - - setFlag(a, FPP->vert, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_Vertex", "FPP_Vertex"); - clearFlag(a, FPP->vert, CHECKED); - - setFlag(a, FPP->problemFace, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Face", "FPP_Face"); - clearFlag(a, FPP->problemFace, CHECKED); - - setFlag(a, FPP->problemRegion, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 3, CHECKED, "FPP_Region", "FPP_Region"); - clearFlag(a, FPP->problemRegion, CHECKED); -} - -bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) -{ - PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - bool alreadyFlagged = true; - if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); - if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); - - bool result = false; - if (collapse.setEdge(edge) && - collapse.checkClass() && - collapse.checkTopo() && - collapse.tryBothDirections(0)) { - collapse.destroyOldElements(); - result = true; - } - if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); - return result; -} - -struct BestCollapse -{ - double quality=-1; - Entity* edge; - Entity* keep; -}; - -void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, BestCollapse& best) -{ - PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - bool alreadyFlagged = true; - if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); - if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); - if (collapse.setEdge(edge) && - collapse.checkClass() && - collapse.checkTopo()) { - double quality = collapse.getQualityFromCollapse(); - if (quality > best.quality) { - best.quality = quality; - best.edge = edge; - best.keep = keep; - } - } - if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); -} - -bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) -{ - Entity* faceVert[3]; - a->mesh->getDownward(face, 0, faceVert); - Vector facePos[3]; - for (int i=0; i < 3; ++i) - facePos[i] = getPosition(a->mesh,faceVert[i]); - - Vector normal = apf::cross((facePos[1]-facePos[0]),(facePos[2]-facePos[0])); - Vector testPos = getPosition(a->mesh, testVert); - Vector refPos = getPosition(a->mesh, refVert); - const double tol=1e-12; - - double dr = (testPos - facePos[0]) * normal; - if (dr*dr < tol) return false; //testVert is on the face - double ds = (refPos - facePos[0]) * normal; - if (dr*ds < 0.0) return false; //different sides of face - return true; //same side of face -} - -bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) -{ - apf::Up& commEdges = FPP->commEdges; - BestCollapse best; - - for (int i=0; imesh, edge, FPP->vert); - apf::Up adjEdges; - a->mesh->getUp(vertexFPP, adjEdges); - for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; - Entity* vertKeep = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); - if (sameSide(a, vertKeep, FPP->vert, FPP->problemFace)) continue; - getBestQualityCollapse(a, edgeDel, vertKeep, collapse, best); - } - } - - if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); - else return false; -} - -bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) -{ - apf::Up& commEdges = FPP->commEdges; - BestCollapse best; - - Entity* pbEdges[3]; - a->mesh->getDownward(FPP->problemFace, 1, pbEdges); - switch(commEdges.n) { - case 2: { - Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); - Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); - - for (int i=0; i<3; i++) { - Entity* pbVert[2]; - a->mesh->getDownward(pbEdges[i], 0, pbVert); - if (pbVert[0] == v1 && pbVert[1] == v2) break; - if (pbVert[1] == v1 && pbVert[0] == v2) break; - getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); - } - break; - } - case 3: { - for (int i=0; i<3; i++) - getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); - break; - } - } - if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); - else return false; -} - -bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) -{ - Vector position = getPosition(a->mesh, FPP->vert); - Vector target; - a->mesh->getDoubleTag(FPP->vert, FPP->snapTag, &target[0]); - double distTarget = (position - target).getLength(); - - BestCollapse best; - - for (size_t i = 0; i < FPP->commEdges.n; ++i) { - Entity* edge = FPP->commEdges.e[i]; - Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); - Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); - //TODO: add logic for boundary layers - double distToFPPVert = (vFPPCoord - target).getLength(); - if (distToFPPVert > distTarget) continue; - getBestQualityCollapse(a, edge, FPP->vert, collapse, best); - } - - if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); - else return false; -} - -FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) -{ - FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); - FPP->setVertex(vertex); - FPP->setBadElements(invalid); - std::vector commEdges; - FPP->getCandidateEdges(commEdges); - return FPP; -} - -void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) -{ - invalid.n = 0; - Vector v[4]; - for (size_t i = 0; i < adjacentElements.getSize(); ++i) { - ma::getVertPoints(mesh,adjacentElements[i],v); - if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) - invalid.e[invalid.n++] = adjacentElements[i]; - } -} - -bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) -{ - Mesh* mesh = adapt->mesh; - if (!mesh->hasTag(vertex, snapTag)) return true; - Vector prev = getPosition(mesh, vertex); - Vector target; - mesh->getDoubleTag(vertex, snapTag, &target[0]); - Upward adjacentElements; - mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); - mesh->setPoint(vertex, 0, target); - getInvalidTets(mesh, adjacentElements, invalid); - if (invalid.n == 0) return true; - mesh->setPoint(vertex, 0, prev); - return false; -} - void trySnapping(Adapt* a, Tag* snapTag) { + Snapper snapper(a, snapTag, false); Refine* refine = a->refine; Collapse collapse; collapse.Init(a); @@ -1141,28 +929,11 @@ void trySnapping(Adapt* a, Tag* snapTag) if (startSize-- == 0) break; //TEMP: Stop after one move Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); - - apf::Up invalid; - bool success = tryReposition(a, vertex, snapTag, invalid); - - if (success) { - a->mesh->removeTag(vertex,snapTag); - clearFlag(a, vertex, SNAP); - continue; + snapper.setVert(vertex); + if (!snapper.run()) { + refine->vtxToSnap.push(vertex); + numFailed++; } - - FirstProblemPlane* FPP = getFPP(a, vertex, snapTag, invalid); - - if (!success) success = tryCollapseToVertex(a, collapse, FPP); - // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); - if (!success) success = tryCollapseTetEdges(a, collapse, FPP); - - if (!success) numFailed++; - if (!success && numFailed == 1) printFPP(a, FPP); - - if (success) refine->vtxToSnap.push(vertex); - - if (FPP) delete FPP; } a->input->shouldForceAdaptation = shouldForce; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index ac18e44b5..df1fd84ca 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -11,6 +11,7 @@ #include "maAdapt.h" #include "maShapeHandler.h" #include "maSnap.h" +#include "maDBG.h" #include #include #include @@ -42,8 +43,6 @@ bool Snapper::requestLocality(apf::CavityOp* o) { if (!o->requestLocality(&vert, 1)) return false; - if (isSimple) - return true; /* in order to try an edge collapse (we don't yet know which edge), bring in a cavity such that all adjacent edges have both vertices local. @@ -71,112 +70,6 @@ static bool didInvert(Mesh* m, Vector& oldNormal, Entity* tri) return (oldNormal * getTriNormal(m, tri)) < 0; } -static void collectBadElements(Adapt* a, Upward& es, - apf::NewArray& normals, apf::Up& bad) -{ - Mesh* m = a->mesh; - bad.n = 0; - for (size_t i = 0; i < es.getSize(); ++i) { -/* for now, when snapping a vertex on the boundary - layer, ignore the quality of layer elements. - not only do we not have metrics for this, but the - algorithm that moves curves would need to change */ - if (getFlag(a, es[i], LAYER)) - continue; - double quality = a->shape->getQuality(es[i]); - if (quality < a->input->validQuality) - bad.e[bad.n++] = es[i]; -/* check for triangles whose normals have changed by - more than 90 degrees when the vertex was snapped */ - else if ((m->getDimension() == 2) && - didInvert(m, normals[i], es[i])) - bad.e[bad.n++] = es[i]; - } - PCU_ALWAYS_ASSERT(bad.n < (int)(sizeof(bad.e) / sizeof(Entity*))); -} - -static bool trySnapping(Adapt* adapter, Tag* tag, Entity* vert, - apf::Up& badElements) -{ - Mesh* mesh = adapter->mesh; - Vector x = getPosition(mesh, vert); - Vector s; - mesh->getDoubleTag(vert, tag, &s[0]); -/* gather the adjacent elements */ - Upward elements; - mesh->getAdjacent(vert, mesh->getDimension(), elements); -/* in 2D, get the old triangle normals */ - apf::NewArray normals; - computeNormals(mesh, elements, normals); -/* move the vertex to the desired point */ - mesh->setPoint(vert, 0, s); -/* check resulting cavity */ - collectBadElements(adapter, elements, normals, badElements); - if (badElements.n) { - /* not ok, put the vertex back where it was */ - mesh->setPoint(vert, 0, x); - return false; - } else { - /* ok, take off the snap tag */ - mesh->removeTag(vert, tag); - return true; - } -} - -static bool tryDiggingEdge(Adapt* adapter, Collapse& collapse, Entity* e) -{ - Mesh* mesh = adapter->mesh; - PCU_ALWAYS_ASSERT(mesh->getType(e) == apf::Mesh::EDGE); - if ( ! collapse.setEdge(e)) - return false; - if ( ! collapse.checkClass()) - return false; - if ( ! collapse.checkTopo()) - return false; - double q = adapter->input->validQuality; - bool oldShouldForce = adapter->input->shouldForceAdaptation; - adapter->input->shouldForceAdaptation = true; - if ( ! collapse.tryBothDirections(q)) - return false; - adapter->input->shouldForceAdaptation = oldShouldForce; - collapse.destroyOldElements(); - return true; -} - -static bool tryDigging2(Adapt* a, Collapse& c, apf::Up& badElements, - FirstProblemPlane* FPP) -{ - - Mesh* m = a->mesh; - int dim = m->getDimension(); - - // first go through the candidate edges found by the first problem plane - // (if any) - std::vector edgesFromFPP; - edgesFromFPP.clear(); - if (FPP && dim == 3) { - FPP->setBadElements(badElements); - FPP->getCandidateEdges(edgesFromFPP); - } - for (size_t i = 0; i < edgesFromFPP.size(); ++i) { - if (tryDiggingEdge(a, c, edgesFromFPP[i])) - return true; - } - - // next try all the edges - for (int i = 0; i < badElements.n; ++i) { - Entity* elem = badElements.e[i]; - Downward edges; - int nedges; - nedges = m->getDownward(elem, 1, edges); - for (int j = 0; j < nedges; ++j){ - if (tryDiggingEdge(a, c, edges[j])) - return true; - } - } - return false; -} - static void updateVertexParametricCoords( Mesh* m, Entity* vert, @@ -219,64 +112,249 @@ static void updateVertexParametricCoords( m->setParam(vert, pBar); } -static bool tryMoving(Adapt* adapter, Entity* v, Tag* tag) +static void printFPP(Adapt* a, FirstProblemPlane* FPP) { - Mesh* m = adapter->mesh; - PCU_ALWAYS_ASSERT_VERBOSE(m->hasTag(v, tag), - "expecting the vertex to have a tag!"); - bool hadItBefore = getFlag(adapter, v, DONT_MOVE); - setFlag(adapter, v, DONT_MOVE); - Vector newTarget; - m->getDoubleTag(v, tag, &newTarget[0]); // default - updateVertexParametricCoords(m, v, newTarget); - m->setDoubleTag(v, tag, &newTarget[0]); - if (!hadItBefore) - clearFlag(adapter, v, DONT_MOVE); - return true; + apf::writeVtkFiles("FPP_Mesh", a->mesh); + EntityArray invalid; + for (int i=0; iproblemRegions.n; i++){ + invalid.append(FPP->problemRegions.e[i]); + } + ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); + + for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); + for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); + + setFlag(a, FPP->vert, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_Vertex", "FPP_Vertex"); + clearFlag(a, FPP->vert, CHECKED); + + setFlag(a, FPP->problemFace, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Face", "FPP_Face"); + clearFlag(a, FPP->problemFace, CHECKED); + + setFlag(a, FPP->problemRegion, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, 3, CHECKED, "FPP_Region", "FPP_Region"); + clearFlag(a, FPP->problemRegion, CHECKED); +} + +static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + + bool result = false; + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo() && + collapse.tryBothDirections(0)) { + collapse.destroyOldElements(); + result = true; + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); + return result; } -static bool tryDigging(Adapt* a, Collapse& c, Entity* v, - apf::Up& badElements, FirstProblemPlane* FPP = 0) +struct BestCollapse { - bool hadItBefore = getFlag(a, v, DONT_COLLAPSE); - setFlag(a, v, DONT_COLLAPSE); - bool ok = tryDigging2(a, c, badElements, FPP); - if (!hadItBefore) - clearFlag(a, v, DONT_COLLAPSE); - return ok; + double quality=-1; + Entity* edge; + Entity* keep; +}; + +static void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, BestCollapse& best) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo()) { + double quality = collapse.getQualityFromCollapse(); + if (quality > best.quality) { + best.quality = quality; + best.edge = edge; + best.keep = keep; + } + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); +} + +static bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) +{ + Entity* faceVert[3]; + a->mesh->getDownward(face, 0, faceVert); + Vector facePos[3]; + for (int i=0; i < 3; ++i) + facePos[i] = getPosition(a->mesh,faceVert[i]); + + Vector normal = apf::cross((facePos[1]-facePos[0]),(facePos[2]-facePos[0])); + Vector testPos = getPosition(a->mesh, testVert); + Vector refPos = getPosition(a->mesh, refVert); + const double tol=1e-12; + + double dr = (testPos - facePos[0]) * normal; + if (dr*dr < tol) return false; //testVert is on the face + double ds = (refPos - facePos[0]) * normal; + if (dr*ds < 0.0) return false; //different sides of face + return true; //same side of face +} + +static bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +{ + apf::Up& commEdges = FPP->commEdges; + BestCollapse best; + + for (int i=0; imesh, edge, FPP->vert); + apf::Up adjEdges; + a->mesh->getUp(vertexFPP, adjEdges); + for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; + Entity* vertKeep = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); + if (sameSide(a, vertKeep, FPP->vert, FPP->problemFace)) continue; + getBestQualityCollapse(a, edgeDel, vertKeep, collapse, best); + } + } + + if (best.quality > 0) + return tryCollapseEdge(a, best.edge, best.keep, collapse); + else return false; +} + +static bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +{ + apf::Up& commEdges = FPP->commEdges; + BestCollapse best; + + Entity* pbEdges[3]; + a->mesh->getDownward(FPP->problemFace, 1, pbEdges); + switch(commEdges.n) { + case 2: { + Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); + Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + + for (int i=0; i<3; i++) { + Entity* pbVert[2]; + a->mesh->getDownward(pbEdges[i], 0, pbVert); + if (pbVert[0] == v1 && pbVert[1] == v2) break; + if (pbVert[1] == v1 && pbVert[0] == v2) break; + getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); + } + break; + } + case 3: { + for (int i=0; i<3; i++) + getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); + break; + } + } + if (best.quality > 0) + return tryCollapseEdge(a, best.edge, best.keep, collapse); + else return false; +} + +static bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +{ + Vector position = getPosition(a->mesh, FPP->vert); + Vector target; + a->mesh->getDoubleTag(FPP->vert, FPP->snapTag, &target[0]); + double distTarget = (position - target).getLength(); + + BestCollapse best; + + for (size_t i = 0; i < FPP->commEdges.n; ++i) { + Entity* edge = FPP->commEdges.e[i]; + Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); + Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); + //TODO: add logic for boundary layers + double distToFPPVert = (vFPPCoord - target).getLength(); + if (distToFPPVert > distTarget) continue; + getBestQualityCollapse(a, edge, FPP->vert, collapse, best); + } + + if (best.quality > 0) + return tryCollapseEdge(a, best.edge, best.keep, collapse); + else return false; +} + +static FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up& invalid) +{ + FirstProblemPlane* FPP = new FirstProblemPlane(a, snapTag); + FPP->setVertex(vertex); + FPP->setBadElements(invalid); + std::vector commEdges; + FPP->getCandidateEdges(commEdges); + return FPP; +} + +static void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) +{ + invalid.n = 0; + Vector v[4]; + for (size_t i = 0; i < adjacentElements.getSize(); ++i) { + ma::getVertPoints(mesh,adjacentElements[i],v); + if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) + invalid.e[invalid.n++] = adjacentElements[i]; + } +} + +static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) +{ + Mesh* mesh = adapt->mesh; + if (!mesh->hasTag(vertex, snapTag)) return true; + Vector prev = getPosition(mesh, vertex); + Vector target; + mesh->getDoubleTag(vertex, snapTag, &target[0]); + Upward adjacentElements; + mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); + mesh->setPoint(vertex, 0, target); + getInvalidTets(mesh, adjacentElements, invalid); + if (invalid.n == 0) return true; + mesh->setPoint(vertex, 0, prev); + return false; } bool Snapper::trySimpleSnap() { - apf::Up badElements; - return trySnapping(adapter, snapTag, vert, badElements); + apf::Up invalid; + return tryReposition(adapter, vert, snapTag, invalid); } +static int numFailed = 0; + bool Snapper::run() { - dug = false; - moved = false; - apf::Up badElements; - bool ok = trySnapping(adapter, snapTag, vert, badElements); - if (isSimple) - return ok; - // there is no need for the following if there exists no bad elements - if (badElements.n == 0) return true; - FirstProblemPlane* FPP; -#ifdef DO_FPP - FPP = new FirstProblemPlane(adapter, snapTag); - FPP->setVertex(vert); -#else - FPP = 0; -#endif - if (adapter->mesh->getDimension() == 2) - moved = tryMoving(adapter, vert, snapTag); - else - dug = tryDigging(adapter, collapse, vert, badElements, FPP); - delete FPP; - if (!dug && !moved) - return false; - return trySnapping(adapter, snapTag, vert, badElements); + apf::Up invalid; + bool success = tryReposition(adapter, vert, snapTag, invalid); + + if (success) { + adapter->mesh->removeTag(vert,snapTag); + clearFlag(adapter, vert, SNAP); + return true; + } + + FirstProblemPlane* FPP = getFPP(adapter, vert, snapTag, invalid); + + if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); + // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); + // if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); + + if (!success) numFailed++; + if (!success && numFailed == 1) printFPP(adapter, FPP); + + if (FPP) delete FPP; + return !success; } FirstProblemPlane::FirstProblemPlane(Adapt* a, Tag* st) From 1ba989dd42b2691c3bf24c8c17020f0e2f788789 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 10 May 2025 16:38:50 -0400 Subject: [PATCH 050/181] using size check --- ma/maCollapse.cc | 3 +++ ma/maSnap.cc | 6 +++--- ma/maSnapper.cc | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index d3b90203f..0128a3529 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -93,6 +93,9 @@ double Collapse::getQualityThisDirection() { if(adapt->mesh->getDimension()==3 && cavity.shouldFit && !areTetsValid(adapt->mesh,newElements)) return -1; + // make sure we aren't undoing refinement + if(!edgesGoodSize()) + return -1; // since they are okay in a linear sense, now fit and do a quality assessment fitElements(); return getWorstQuality(adapt, newElements); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 3ccd7305a..bde664e36 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -930,10 +930,10 @@ void trySnapping(Adapt* a, Tag* snapTag) Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); snapper.setVert(vertex); - if (!snapper.run()) { - refine->vtxToSnap.push(vertex); + if (!snapper.run()) numFailed++; - } + else if (getFlag(a, vertex, SNAP)) + refine->vtxToSnap.push(vertex); } a->input->shouldForceAdaptation = shouldForce; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index df1fd84ca..28ad8c236 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -354,7 +354,7 @@ bool Snapper::run() if (!success && numFailed == 1) printFPP(adapter, FPP); if (FPP) delete FPP; - return !success; + return success; } FirstProblemPlane::FirstProblemPlane(Adapt* a, Tag* st) From 05cb90fe3a7abc56c270f9f23c7c4457413571da Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 10 May 2025 17:14:13 -0400 Subject: [PATCH 051/181] remove unused --- ma/maSnap.cc | 66 +++++++------------------------------------------ ma/maSnapper.cc | 5 ++-- 2 files changed, 11 insertions(+), 60 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index bde664e36..2b4e45161 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -916,8 +916,6 @@ void trySnapping(Adapt* a, Tag* snapTag) { Snapper snapper(a, snapTag, false); Refine* refine = a->refine; - Collapse collapse; - collapse.Init(a); print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", refine->vtxToSnap.size()); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; @@ -940,23 +938,22 @@ void trySnapping(Adapt* a, Tag* snapTag) print(a->mesh->getPCU(), "Number of vertices failed %d\n", numFailed); } -void printSnapFields(Adapt* a, Mesh* m, std::string name) -{ - apf::writeVtkFiles(name.c_str(), m); - ma_dbg::addTargetLocation(a, "snap_target"); - ma_dbg::addClassification(a, "classification"); - apf::writeVtkFiles((name+"_fields").c_str(), m, 1); -} - void snap(Adapt* a) { if (!a->input->shouldSnap) return; Tag* snapTag; tagVertsToSnap(a, snapTag); - printSnapFields(a, a->mesh, "before_last_snap"); + + ma_dbg::addTargetLocation(a, "snap_target"); + ma_dbg::addClassification(a, "classification"); + apf::writeVtkFiles("before_last_snap", a->mesh); + trySnapping(a, snapTag); - printSnapFields(a, a->mesh, "after_last_snap"); + + apf::writeVtkFiles("after_last_snap", a->mesh); + ma_dbg::dumpMeshWithFlag(a, 0, 0, SNAP, "snap_tag", "after_last_snap_tag"); + clearFlagFromDimension(a, SNAP, 0); a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; @@ -983,49 +980,4 @@ void prevSnap(Adapt* a) if (a->hasLayer) checkLayerShape(a->mesh, "after snapping"); } - -void visualizeGeometricInfo(Mesh* m, const char* name) -{ - Tag* dimensionTag = m->createIntTag("ma_geom_dim",1); - Tag* idTag = m->createIntTag("ma_geom_id",1); - apf::Field* field = apf::createLagrangeField(m,"ma_param",apf::VECTOR,1); - apf::Field* targetField = apf::createLagrangeField(m,"ma_target",apf::VECTOR,1); - Iterator* it = m->begin(0); - Entity* v; - while ((v = m->iterate(it))) - { - Model* c = m->toModel(v); - int dimension = m->getModelType(c); - m->setIntTag(v,dimensionTag,&dimension); - int id = m->getModelTag(c); - m->setIntTag(v,idTag,&id); - Vector p; - Vector xp = getPosition(m, v); - m->getParam(v,p); - if (dimension == 2 || dimension == 1) { - Vector x; - m->isParamPointInsideModel(c, &p[0], x); - apf::setVector(targetField, v, 0, x - xp); - } - else { - Vector x(0., 0., 0.); - apf::setVector(targetField, v, 0, x); - } - apf::setVector(field,v,0,p); - } - m->end(it); - apf::writeVtkFiles(name,m); - it = m->begin(0); - while ((v = m->iterate(it))) - { - m->removeTag(v,dimensionTag); - m->removeTag(v,idTag); - } - m->end(it); - m->destroyTag(dimensionTag); - m->destroyTag(idTag); - apf::destroyField(field); - apf::destroyField(targetField); -} - } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 28ad8c236..093677205 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -347,11 +347,10 @@ bool Snapper::run() FirstProblemPlane* FPP = getFPP(adapter, vert, snapTag, invalid); if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); - // if (!success) success = tryReduceCommonEdges(a, collapse, FPP); + // if (!success) success = tryReduceCommonEdges(adapter, collapse, FPP); // if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); - if (!success) numFailed++; - if (!success && numFailed == 1) printFPP(adapter, FPP); + if (!success && numFailed++ == 1) printFPP(adapter, FPP); if (FPP) delete FPP; return success; From c102b32869a1dc107f0b7e0d180305f35b4fb128 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Mon, 12 May 2025 13:33:09 -0400 Subject: [PATCH 052/181] good results from collapse --- ma/maCollapse.cc | 2 +- ma/maSnap.cc | 2 +- ma/maSnapper.cc | 25 ++++++++++++++++++------- test/aniso_adapt.h | 1 + 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 0128a3529..495c6ee5e 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -77,7 +77,7 @@ bool Collapse::edgesGoodSize() { } } // printf("maxSize %f Ratio %f\n", maxSize, ratioAtMaxSize); - if (maxSize > 1.5 && ratioAtMaxSize > 1.44 ) return false; + if (maxSize > 1.6 && ratioAtMaxSize > 1.44 ) return false; return true; } diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 2b4e45161..065849a37 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -924,7 +924,7 @@ void trySnapping(Adapt* a, Tag* snapTag) while (refine->vtxToSnap.size() > 0) { - if (startSize-- == 0) break; //TEMP: Stop after one move + // if (startSize-- == 0) break; //TEMP: Stop after one move Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); snapper.setVert(vertex); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 093677205..9954c8a7d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -121,6 +121,9 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) } ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); + ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_Collapse", "FPP_Collapse"); + clearFlagFromDimension(a, CHECKED, 1); + for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); @@ -209,7 +212,10 @@ static bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* BestCollapse best; for (int i=0; imesh->getDownward(commEdges.e[i], 0, vertex); + for (int j=0; j<2; j++) + getBestQualityCollapse(a, commEdges.e[i], vertex[j], collapse, best); } for (int i=0; imesh->getDownward(pbEdges[i], 0, pbVert); if (pbVert[0] == v1 && pbVert[1] == v2) break; if (pbVert[1] == v1 && pbVert[0] == v2) break; - getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); + for (int j=0; j<2; j++) + getBestQualityCollapse(a, pbEdges[i], pbVert[j], collapse, best); } break; } case 3: { - for (int i=0; i<3; i++) - getBestQualityCollapse(a, pbEdges[i], 0, collapse, best); + for (int i=0; i<3; i++) { + Entity* pbVert[2]; + a->mesh->getDownward(pbEdges[i], 0, pbVert); + for (int j=0; j<2; j++) + getBestQualityCollapse(a, pbEdges[i], pbVert[j], collapse, best); + } break; } } @@ -331,7 +342,7 @@ bool Snapper::trySimpleSnap() return tryReposition(adapter, vert, snapTag, invalid); } -static int numFailed = 0; +static int numFailed = 0; //TODO: REMOVE bool Snapper::run() { @@ -348,9 +359,9 @@ bool Snapper::run() if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); // if (!success) success = tryReduceCommonEdges(adapter, collapse, FPP); - // if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); + if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); - if (!success && numFailed++ == 1) printFPP(adapter, FPP); + if (!success && ++numFailed == 1) printFPP(adapter, FPP); if (FPP) delete FPP; return success; diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index d514149a9..25d632906 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -47,6 +47,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) ma::Adapt* a = new ma::Adapt(in); for (int i = 0; i < 2; ++i) { + // ma::coarsen(a); ma::refine(a); ma::snap(a); } From 79538f790632fae2014486ee6ff17da57720443c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 15 May 2025 22:27:30 -0400 Subject: [PATCH 053/181] split in progress --- ma/maSnapper.cc | 85 ++++++++++++++++++++++++++++++++++++++++++++++++- ma/maSnapper.h | 6 ++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 9954c8a7d..d41730166 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -19,7 +19,7 @@ namespace ma { -Snapper::Snapper(Adapt* a, Tag* st, bool is) +Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a) { adapter = a; snapTag = st; @@ -141,6 +141,88 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemRegion, CHECKED); } +static Vector projOnTriPlane(Adapt* a, Entity* face, Entity* vert) +{ + Entity* faceVert[3]; + a->mesh->getDownward(face, 0, faceVert); + Vector facePos[3]; + for (int i=0; i < 3; ++i) + facePos[i] = getPosition(a->mesh,faceVert[i]); + + Vector normal = apf::cross((facePos[1]-facePos[0]),(facePos[2]-facePos[0])); + double magN = normal*normal; + Vector vertPos = getPosition(a->mesh, vert); + double magCP = (vertPos-facePos[0]) * normal; + double ratio=magCP/magN; + + Vector result; + for (int i=0; i<3; ++i) + result[i]=vertPos[i]-ratio*normal[i]; + + return result; +} + +static void GetTetStats(Adapt* a, FirstProblemPlane* FPP) +{ + Entity* faceEdges[3]; + a->mesh->getDownward(FPP->problemFace, 1, faceEdges); + + Entity* verts[3]; + a->mesh->getDownward(FPP->problemFace, 0, verts); + + Vector facePos[3]; + Entity* edges[6]; + for (int i=0; i<3; i++) { + edges[i]=faceEdges[i]; + facePos[i]=getPosition(a->mesh, verts[i]); + } + + Entity* faces[4]; + faces[0]=FPP->problemFace; + + Entity* problemFaces[4]; + a->mesh->getDownward(FPP->problemRegion, 2, problemFaces); + for (int i=0; i<4; i++) { + if (problemFaces[i] == FPP->problemFace ) continue; + else if (isLowInHigh(a->mesh, problemFaces[i], edges[0])) faces[1] = problemFaces[i]; + else if (isLowInHigh(a->mesh, problemFaces[i], edges[1])) faces[2] = problemFaces[i]; + else if (isLowInHigh(a->mesh, problemFaces[i], edges[2])) faces[3] = problemFaces[i]; + } + + for (int i=1; i<3; i++) { + Entity* problemEdges[3]; + a->mesh->getDownward(faces[i], 1, problemEdges); + for (int j=0; j<3; j++) { + if (problemEdges[j]==edges[i-1] ) continue; + else if (isLowInHigh(a->mesh, problemEdges[j], verts[0])) edges[3] = problemEdges[j]; + else if (isLowInHigh(a->mesh, problemEdges[j], verts[1])) edges[4] = problemEdges[j]; + else if (isLowInHigh(a->mesh, problemEdges[j], verts[2])) edges[5] = problemEdges[j]; + } + } +} + +bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) +{ + if (FPP->commEdges.n < 2) return false; + printf("SPLIT\n"); + double baseArea = apf::measure(a->mesh, FPP->problemFace); + double smallest = baseArea; + Entity* faces[4]; + a->mesh->getDownward(FPP->problemRegion, 2, faces); + for (int i=0; i<4; i++) { + double area = apf::measure(a->mesh, faces[i]); + if (area < smallest) + smallest = area; + } + + if (smallest == baseArea) { + PCU_ALWAYS_ASSERT(false); + } + + + return false; +} + static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); @@ -360,6 +442,7 @@ bool Snapper::run() if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); // if (!success) success = tryReduceCommonEdges(adapter, collapse, FPP); if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); + // if (!success) success = trySwapOrSplit(adapter, FPP); if (!success && ++numFailed == 1) printFPP(adapter, FPP); diff --git a/ma/maSnapper.h b/ma/maSnapper.h index c3da4c778..52610fe4d 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -11,6 +11,8 @@ #define MA_SNAPPER_H #include "maCollapse.h" +#include "maSingleSplitCollapse.h" +#include "maEdgeSwap.h" namespace apf { class CavityOp; @@ -40,7 +42,11 @@ class Snapper Tag* snapTag; Entity* vert; Collapse collapse; + SingleSplitCollapse splitCollapse; + EdgeSwap edgeSwap; bool isSimple; + + bool trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP); }; struct Ray{ From 875da60daeedf1ab4388a25de0dfcd2b8fe4836d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 16 May 2025 10:02:13 -0400 Subject: [PATCH 054/181] fixed compile error --- ma/maSnap.cc | 3 ++- ma/maSnapper.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 065849a37..f5067105f 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -953,7 +953,8 @@ void snap(Adapt* a) apf::writeVtkFiles("after_last_snap", a->mesh); ma_dbg::dumpMeshWithFlag(a, 0, 0, SNAP, "snap_tag", "after_last_snap_tag"); - + + clearFlagFromDimension(a, COLLAPSE, 1); //TODO: Figure out what is making this neccessary clearFlagFromDimension(a, SNAP, 0); a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 52610fe4d..352c42b0d 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -43,7 +43,7 @@ class Snapper Entity* vert; Collapse collapse; SingleSplitCollapse splitCollapse; - EdgeSwap edgeSwap; + // EdgeSwap edgeSwap; bool isSimple; bool trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP); From 0e3073f3de7c73a505bfaf9ab4fc025ecd2136fb Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 16 May 2025 19:31:47 -0400 Subject: [PATCH 055/181] split collapse skeleton --- ma/maSnap.cc | 2 +- ma/maSnapper.cc | 199 +++++++++++++++++++++++++++++++++++++++++++++--- ma/maSnapper.h | 3 +- 3 files changed, 191 insertions(+), 13 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index f5067105f..0dd0ab108 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -954,7 +954,7 @@ void snap(Adapt* a) apf::writeVtkFiles("after_last_snap", a->mesh); ma_dbg::dumpMeshWithFlag(a, 0, 0, SNAP, "snap_tag", "after_last_snap_tag"); - clearFlagFromDimension(a, COLLAPSE, 1); //TODO: Figure out what is making this neccessary + // clearFlagFromDimension(a, COLLAPSE, 1); //TODO: Figure out what is making this neccessary clearFlagFromDimension(a, SNAP, 0); a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index d41730166..b7549bc63 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -24,11 +24,17 @@ Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a) adapter = a; snapTag = st; collapse.Init(a); + edgeSwap = makeEdgeSwap(a); isSimple = is; dug = false; vert = 0; } +Snapper::~Snapper() +{ + delete edgeSwap; +} + void Snapper::setVert(Entity* v) { vert = v; @@ -141,6 +147,17 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) clearFlag(a, FPP->problemRegion, CHECKED); } +static int indexOfMin(double a0, double a1, double a2) +{ + int k; + double buf; + if( a0mesh->getDownward(FPP->problemFace, 1, faceEdges); @@ -199,26 +226,176 @@ static void GetTetStats(Adapt* a, FirstProblemPlane* FPP) else if (isLowInHigh(a->mesh, problemEdges[j], verts[2])) edges[5] = problemEdges[j]; } } + + Vector projection = projOnTriPlane(a, FPP->problemFace, FPP->vert); + //TODO: ERROR if projection = any point on problem face + + /* find normal to the plane */ + Vector v01 = facePos[1] - facePos[0]; + Vector v02 = facePos[2] - facePos[0]; + Vector norm = apf::cross(v01, v02); + + Vector ri = projection - facePos[0]; + Vector rj = projection - facePos[1]; + Vector rk = projection - facePos[2]; + + /* determine which side of the edges does the point R lie. + First get normal vectors */ + Vector normi = apf::cross(v01, ri); + Vector normj = apf::cross(facePos[2]-facePos[1], rj); + Vector normk = apf::cross(facePos[0]-facePos[2], rk); + + Vector mag; + mag[0]=normi*norm; + mag[1]=normj*norm; + mag[2]=normk*norm; + + area[0]=norm*norm; + area[1]=normi*normi; + area[2]=normj*normj; + area[3]=normk*normk; + + int filter[]={1,2,4}; + int bit=0; + /* examine signs of mag[0], mag[1] and mag[2] */ + for(int i=0; i<3; i++) + if(mag[i]>0.0) + bit = bit | filter[i]; + + /* + 010=2 | 011=3 / 001=1 + | / + ------------+--e2--+----------- + v0| /v2 + | 7 / + 110=6 e0 e1 + | / + | / 101=5 + |/ + v1+ + /| + / | + 4 + */ + + switch( bit ) { + case 1:{ + int Emap[]={0,4,3}; + int Fmap[]={0,2,3}; + ents[0]=faces[1]; + int i=indexOfMin(area[0],area[2],area[3]); + ents[1]=edges[Emap[i]]; + ents[2]=faces[Fmap[i]]; + break; + } + case 2: { + int Emap[]={1,4,5}; + int Fmap[]={0,1,3}; + ents[0]=faces[2]; + int i=indexOfMin(area[0],area[1],area[3]); + ents[1]=edges[Emap[i]]; + ents[2]=faces[Fmap[i]]; + break; + } + case 3: { + // double L1_xyz[2][3], L2_xyz[2][3]; + ents[0]=edges[2]; + ents[1]=edges[4]; + ents[2]=((area[0]commEdges.n < 2) return false; printf("SPLIT\n"); - double baseArea = apf::measure(a->mesh, FPP->problemFace); - double smallest = baseArea; - Entity* faces[4]; - a->mesh->getDownward(FPP->problemRegion, 2, faces); - for (int i=0; i<4; i++) { - double area = apf::measure(a->mesh, faces[i]); - if (area < smallest) - smallest = area; - } + Entity* ents[4]; + double area[4]; + int bit = getTetStats(a, FPP, ents, area); - if (smallest == baseArea) { + double min=area[0]; + for(int i=1; i<4; i++) + if( area[i] key problem: two mesh edges + if (bit==3 || bit==5 || bit==6) { + // // check edge swapping + // for (int i=0; i<2; i++) + // if (edgeSwap->run(ents[i])) //TODO: Select best + // return true; + + // // check split+collapse + // for (int i=0; i<2; i++) + // if (splitCollapse.run(ents[i], ents[i+2])) //TODO: Select best + // return true; + } + return false; } diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 352c42b0d..f660c84aa 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -30,6 +30,7 @@ class Snapper { public: Snapper(Adapt* a, Tag* st, bool is); + ~Snapper(); void setVert(Entity* v); Entity* getVert(); bool requestLocality(apf::CavityOp* o); @@ -43,7 +44,7 @@ class Snapper Entity* vert; Collapse collapse; SingleSplitCollapse splitCollapse; - // EdgeSwap edgeSwap; + EdgeSwap* edgeSwap; bool isSimple; bool trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP); From 101e49539a181cd622172b24a67e680b180c813d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Tue, 20 May 2025 23:51:21 -0400 Subject: [PATCH 056/181] split collapse working --- ma/maCollapse.cc | 2 +- ma/maSnapper.cc | 67 ++++++++++++++++++++++++++++------------------ test/aniso_adapt.h | 4 +-- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 495c6ee5e..246600750 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -77,7 +77,7 @@ bool Collapse::edgesGoodSize() { } } // printf("maxSize %f Ratio %f\n", maxSize, ratioAtMaxSize); - if (maxSize > 1.6 && ratioAtMaxSize > 1.44 ) return false; + if (maxSize > 1.52 && ratioAtMaxSize > 1.2 ) return false; return true; } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index b7549bc63..e735f433d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -118,6 +118,13 @@ static void updateVertexParametricCoords( m->setParam(vert, pBar); } +static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) +{ + setFlag(a, ent, CHECKED); + ma_dbg::dumpMeshWithFlag(a, 0, dim, CHECKED, name, name); + clearFlag(a, ent, CHECKED); +} + static void printFPP(Adapt* a, FirstProblemPlane* FPP) { apf::writeVtkFiles("FPP_Mesh", a->mesh); @@ -127,24 +134,13 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) } ma_dbg::createCavityMesh(a, invalid, "FPP_Invalid"); - ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_Collapse", "FPP_Collapse"); - clearFlagFromDimension(a, CHECKED, 1); - for (int i=0; icommEdges.n; i++) setFlag(a, FPP->commEdges.e[i], CHECKED); ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "FPP_CommEdges", "FPP_CommEdges"); for (int i=0; icommEdges.n; i++) clearFlag(a, FPP->commEdges.e[i], CHECKED); - setFlag(a, FPP->vert, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "FPP_Vertex", "FPP_Vertex"); - clearFlag(a, FPP->vert, CHECKED); - - setFlag(a, FPP->problemFace, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 2, CHECKED, "FPP_Face", "FPP_Face"); - clearFlag(a, FPP->problemFace, CHECKED); - - setFlag(a, FPP->problemRegion, CHECKED); - ma_dbg::dumpMeshWithFlag(a, 0, 3, CHECKED, "FPP_Region", "FPP_Region"); - clearFlag(a, FPP->problemRegion, CHECKED); + flagAndPrint(a, FPP->vert, 0, "FPP_Vertex"); + flagAndPrint(a, FPP->problemFace, 2, "FPP_Face"); + flagAndPrint(a, FPP->problemRegion, 3, "FPP_Region"); } static int indexOfMin(double a0, double a1, double a2) @@ -369,7 +365,6 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) { if (FPP->commEdges.n < 2) return false; - printf("SPLIT\n"); Entity* ents[4]; double area[4]; int bit = getTetStats(a, FPP, ents, area); @@ -382,18 +377,38 @@ bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) PCU_ALWAYS_ASSERT(false); } - printf("BIT %d\n", bit); // two large dihedral angles -> key problem: two mesh edges if (bit==3 || bit==5 || bit==6) { - // // check edge swapping - // for (int i=0; i<2; i++) - // if (edgeSwap->run(ents[i])) //TODO: Select best - // return true; - - // // check split+collapse - // for (int i=0; i<2; i++) - // if (splitCollapse.run(ents[i], ents[i+2])) //TODO: Select best - // return true; + // if (++reachedSwap == 1) { + // flagAndPrint(a, ents[2], 2, "FPP_SwapFace"); + // } + // check edge swapping + for (int i=0; i<2; i++) + if (edgeSwap->run(ents[i])) //TODO: Select best + return true; + + // check split+collapse + for (int i=0; i<2; i++) + if (splitCollapse.run(ents[i], FPP->vert)) //TODO: Select best + return true; + } + // three large dihedral angles -> key entity: a mesh face + else { + + // check edge swaps + Entity* edges[3]; + a->mesh->getDownward(ents[0], 1, edges); + for (int i=0; i<3; i++) { + if (edgeSwap->run(edges[i])) //TODO: Select best + return true; + } + + //TODO: IMPLEMENT FACE SWAP + + if (splitCollapse.run(ents[1], FPP->vert)); + return true; + + //TODO: USE DOUBLE SPLIT COLLAPSE } @@ -619,7 +634,7 @@ bool Snapper::run() if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); // if (!success) success = tryReduceCommonEdges(adapter, collapse, FPP); if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); - // if (!success) success = trySwapOrSplit(adapter, FPP); + if (!success) success = trySwapOrSplit(adapter, FPP); if (!success && ++numFailed == 1) printFPP(adapter, FPP); diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 25d632906..8d2bc63e7 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -45,9 +45,9 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < 2; ++i) + for (int i = 0; i < in->maximumIterations; ++i) { - // ma::coarsen(a); + ma::coarsen(a); ma::refine(a); ma::snap(a); } From 289170c0683e5081b1c7c759be25bdb50f3220bf Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 23 May 2025 15:17:33 -0400 Subject: [PATCH 057/181] clean up code --- ma/maMatch.cc | 3 +++ ma/maSnap.cc | 21 +++++++++++++-------- ma/maSnapper.cc | 11 ++++------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ma/maMatch.cc b/ma/maMatch.cc index c17ecdda5..7309f5c5c 100644 --- a/ma/maMatch.cc +++ b/ma/maMatch.cc @@ -75,6 +75,9 @@ void matchNewElements(Refine* r) print(m->getPCU(), "updated matching for %li faces", face_count); } +/* we are starting to support a few operations on matched +meshes, sincluding snapping+UR. this should prevent snapping +from modifying any matched entities */ void preventMatchedCavityMods(Adapt* a) { Mesh* m = a->mesh; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 0dd0ab108..4dc5a0cd7 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -920,11 +920,9 @@ void trySnapping(Adapt* a, Tag* snapTag) bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; int numFailed = 0; - int startSize = refine->vtxToSnap.size(); while (refine->vtxToSnap.size() > 0) { - // if (startSize-- == 0) break; //TEMP: Stop after one move Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); snapper.setVert(vertex); @@ -942,22 +940,29 @@ void snap(Adapt* a) { if (!a->input->shouldSnap) return; + double t0 = pcu::Time(); Tag* snapTag; + // preventMatchedCavityMods(a); tagVertsToSnap(a, snapTag); - ma_dbg::addTargetLocation(a, "snap_target"); - ma_dbg::addClassification(a, "classification"); - apf::writeVtkFiles("before_last_snap", a->mesh); + // ma_dbg::addTargetLocation(a, "snap_target"); + // ma_dbg::addClassification(a, "classification"); + // apf::writeVtkFiles("before_last_snap", a->mesh); trySnapping(a, snapTag); + // snapLayer(a, tag); - apf::writeVtkFiles("after_last_snap", a->mesh); - ma_dbg::dumpMeshWithFlag(a, 0, 0, SNAP, "snap_tag", "after_last_snap_tag"); + // apf::writeVtkFiles("after_last_snap", a->mesh); // clearFlagFromDimension(a, COLLAPSE, 1); //TODO: Figure out what is making this neccessary - clearFlagFromDimension(a, SNAP, 0); + clearFlagFromDimension(a, SNAP, 0); //TODO: should not be neccessary a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; + + double t1 = pcu::Time(); + print(a->mesh->getPCU(), "snapped in %f seconds\n", t1 - t0); + // if (a->hasLayer) + // checkLayerShape(a->mesh, "after snapping"); } void prevSnap(Adapt* a) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index e735f433d..fb030e913 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -305,7 +305,7 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double // L2_xyz[0][0]=fxyz[1][0]; L2_xyz[1][0]=pxyz[0]; // L2_xyz[0][1]=fxyz[1][1]; L2_xyz[1][1]=pxyz[1]; // L2_xyz[0][2]=fxyz[1][2]; L2_xyz[1][2]=pxyz[2]; - // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); + // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); //TODO: This logic is used for double split collapse break; } case 4: { @@ -329,7 +329,7 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double // L2_xyz[0][0]=fxyz[0][0]; L2_xyz[1][0]=pxyz[0]; // L2_xyz[0][1]=fxyz[0][1]; L2_xyz[1][1]=pxyz[1]; // L2_xyz[0][2]=fxyz[0][2]; L2_xyz[1][2]=pxyz[2]; - // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); + // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); //TODO: This logic is used for double split collapse break; } case 6: { @@ -344,7 +344,7 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double // L2_xyz[0][0]=fxyz[2][0]; L2_xyz[1][0]=pxyz[0]; // L2_xyz[0][1]=fxyz[2][1]; L2_xyz[1][1]=pxyz[1]; // L2_xyz[0][2]=fxyz[2][2]; L2_xyz[1][2]=pxyz[2]; - // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); + // fromMeshTools::MT_intLineLine2(L1_xyz,L2_xyz,&i,intXYZ); //TODO: This logic is used for double split collapse break; } case 7: { @@ -379,9 +379,6 @@ bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) // two large dihedral angles -> key problem: two mesh edges if (bit==3 || bit==5 || bit==6) { - // if (++reachedSwap == 1) { - // flagAndPrint(a, ents[2], 2, "FPP_SwapFace"); - // } // check edge swapping for (int i=0; i<2; i++) if (edgeSwap->run(ents[i])) //TODO: Select best @@ -636,7 +633,7 @@ bool Snapper::run() if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); if (!success) success = trySwapOrSplit(adapter, FPP); - if (!success && ++numFailed == 1) printFPP(adapter, FPP); + // if (!success && ++numFailed == 1) printFPP(adapter, FPP); if (FPP) delete FPP; return success; From 5f2bce85247f72a96183f3dca7f26cb2c67d4ab0 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 23 May 2025 16:34:53 -0400 Subject: [PATCH 058/181] simplify trySwapOrSplt --- ma/maSnapper.cc | 33 +++++++++++++++++---------------- ma/maSnapper.h | 5 +++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index fb030e913..b73fe8263 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -21,7 +21,8 @@ namespace ma { Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a) { - adapter = a; + adapt = a; + mesh = a->mesh; snapTag = st; collapse.Init(a); edgeSwap = makeEdgeSwap(a); @@ -54,11 +55,11 @@ bool Snapper::requestLocality(apf::CavityOp* o) edges have both vertices local. This is basically two layers of elements around the vertex */ apf::Up edges; - adapter->mesh->getUp(vert,edges); + mesh->getUp(vert,edges); apf::Up ovs; ovs.n = edges.n; for (int i = 0; i < edges.n; ++i) - ovs.e[i] = apf::getEdgeVertOppositeVert(adapter->mesh, edges.e[i], vert); + ovs.e[i] = apf::getEdgeVertOppositeVert(mesh, edges.e[i], vert); return o->requestLocality(&ovs.e[0], ovs.n); } @@ -362,12 +363,12 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double return bit; } -bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) +bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { if (FPP->commEdges.n < 2) return false; Entity* ents[4]; double area[4]; - int bit = getTetStats(a, FPP, ents, area); + int bit = getTetStats(adapt, FPP, ents, area); double min=area[0]; for(int i=1; i<4; i++) @@ -394,7 +395,7 @@ bool Snapper::trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP) // check edge swaps Entity* edges[3]; - a->mesh->getDownward(ents[0], 1, edges); + mesh->getDownward(ents[0], 1, edges); for (int i=0; i<3; i++) { if (edgeSwap->run(edges[i])) //TODO: Select best return true; @@ -610,7 +611,7 @@ static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& i bool Snapper::trySimpleSnap() { apf::Up invalid; - return tryReposition(adapter, vert, snapTag, invalid); + return tryReposition(adapt, vert, snapTag, invalid); } static int numFailed = 0; //TODO: REMOVE @@ -618,22 +619,22 @@ static int numFailed = 0; //TODO: REMOVE bool Snapper::run() { apf::Up invalid; - bool success = tryReposition(adapter, vert, snapTag, invalid); + bool success = tryReposition(adapt, vert, snapTag, invalid); if (success) { - adapter->mesh->removeTag(vert,snapTag); - clearFlag(adapter, vert, SNAP); + mesh->removeTag(vert,snapTag); + clearFlag(adapt, vert, SNAP); return true; } - FirstProblemPlane* FPP = getFPP(adapter, vert, snapTag, invalid); + FirstProblemPlane* FPP = getFPP(adapt, vert, snapTag, invalid); - if (!success) success = tryCollapseToVertex(adapter, collapse, FPP); - // if (!success) success = tryReduceCommonEdges(adapter, collapse, FPP); - if (!success) success = tryCollapseTetEdges(adapter, collapse, FPP); - if (!success) success = trySwapOrSplit(adapter, FPP); + if (!success) success = tryCollapseToVertex(adapt, collapse, FPP); + // if (!success) success = tryReduceCommonEdges(adapt, collapse, FPP); + if (!success) success = tryCollapseTetEdges(adapt, collapse, FPP); + if (!success) success = trySwapOrSplit(FPP); - // if (!success && ++numFailed == 1) printFPP(adapter, FPP); + // if (!success && ++numFailed == 1) printFPP(adapt, FPP); if (FPP) delete FPP; return success; diff --git a/ma/maSnapper.h b/ma/maSnapper.h index f660c84aa..0ae860bb6 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -39,7 +39,8 @@ class Snapper bool dug; bool moved; private: - Adapt* adapter; + Adapt* adapt; + Mesh* mesh; Tag* snapTag; Entity* vert; Collapse collapse; @@ -47,7 +48,7 @@ class Snapper EdgeSwap* edgeSwap; bool isSimple; - bool trySwapOrSplit(Adapt* a, FirstProblemPlane* FPP); + bool trySwapOrSplit(FirstProblemPlane* FPP); }; struct Ray{ From 0d588dfbc23306b5af57aef18ba28654723fd694 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 23 May 2025 16:46:52 -0400 Subject: [PATCH 059/181] moved snap operations to snap class --- ma/maSnapper.cc | 58 ++++++++++++++++++++++++------------------------- ma/maSnapper.h | 3 +++ 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index b73fe8263..f3c2dd559 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -478,96 +478,96 @@ static bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) return true; //same side of face } -static bool tryCollapseTetEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; BestCollapse best; for (int i=0; imesh->getDownward(commEdges.e[i], 0, vertex); + mesh->getDownward(commEdges.e[i], 0, vertex); for (int j=0; j<2; j++) - getBestQualityCollapse(a, commEdges.e[i], vertex[j], collapse, best); + getBestQualityCollapse(adapt, commEdges.e[i], vertex[j], collapse, best); } for (int i=0; imesh, edge, FPP->vert); + Entity* vertexFPP = getEdgeVertOppositeVert(mesh, edge, vert); apf::Up adjEdges; - a->mesh->getUp(vertexFPP, adjEdges); + mesh->getUp(vertexFPP, adjEdges); for (int j=0; jmesh, FPP->problemFace, edgeDel)) continue; - Entity* vertKeep = getEdgeVertOppositeVert(a->mesh, edgeDel, vertexFPP); - if (sameSide(a, vertKeep, FPP->vert, FPP->problemFace)) continue; - getBestQualityCollapse(a, edgeDel, vertKeep, collapse, best); + if (isLowInHigh(mesh, FPP->problemFace, edgeDel)) continue; + Entity* vertKeep = getEdgeVertOppositeVert(mesh, edgeDel, vertexFPP); + if (sameSide(adapt, vertKeep, vert, FPP->problemFace)) continue; + getBestQualityCollapse(adapt, edgeDel, vertKeep, collapse, best); } } if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); + return tryCollapseEdge(adapt, best.edge, best.keep, collapse); else return false; } -static bool tryReduceCommonEdges(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; BestCollapse best; Entity* pbEdges[3]; - a->mesh->getDownward(FPP->problemFace, 1, pbEdges); + mesh->getDownward(FPP->problemFace, 1, pbEdges); switch(commEdges.n) { case 2: { - Entity* v1 = getEdgeVertOppositeVert(a->mesh, commEdges.e[0], FPP->vert); - Entity* v2 = getEdgeVertOppositeVert(a->mesh, commEdges.e[1], FPP->vert); + Entity* v1 = getEdgeVertOppositeVert(mesh, commEdges.e[0], vert); + Entity* v2 = getEdgeVertOppositeVert(mesh, commEdges.e[1], vert); for (int i=0; i<3; i++) { Entity* pbVert[2]; - a->mesh->getDownward(pbEdges[i], 0, pbVert); + mesh->getDownward(pbEdges[i], 0, pbVert); if (pbVert[0] == v1 && pbVert[1] == v2) break; if (pbVert[1] == v1 && pbVert[0] == v2) break; for (int j=0; j<2; j++) - getBestQualityCollapse(a, pbEdges[i], pbVert[j], collapse, best); + getBestQualityCollapse(adapt, pbEdges[i], pbVert[j], collapse, best); } break; } case 3: { for (int i=0; i<3; i++) { Entity* pbVert[2]; - a->mesh->getDownward(pbEdges[i], 0, pbVert); + mesh->getDownward(pbEdges[i], 0, pbVert); for (int j=0; j<2; j++) - getBestQualityCollapse(a, pbEdges[i], pbVert[j], collapse, best); + getBestQualityCollapse(adapt, pbEdges[i], pbVert[j], collapse, best); } break; } } if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); + return tryCollapseEdge(adapt, best.edge, best.keep, collapse); else return false; } -static bool tryCollapseToVertex(Adapt* a, Collapse& collapse, FirstProblemPlane* FPP) +bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) { - Vector position = getPosition(a->mesh, FPP->vert); + Vector position = getPosition(mesh, vert); Vector target; - a->mesh->getDoubleTag(FPP->vert, FPP->snapTag, &target[0]); + mesh->getDoubleTag(vert, snapTag, &target[0]); double distTarget = (position - target).getLength(); BestCollapse best; for (size_t i = 0; i < FPP->commEdges.n; ++i) { Entity* edge = FPP->commEdges.e[i]; - Entity* vertexOnFPP = getEdgeVertOppositeVert(a->mesh, edge, FPP->vert); - Vector vFPPCoord = getPosition(a->mesh, vertexOnFPP); + Entity* vertexOnFPP = getEdgeVertOppositeVert(mesh, edge, vert); + Vector vFPPCoord = getPosition(mesh, vertexOnFPP); //TODO: add logic for boundary layers double distToFPPVert = (vFPPCoord - target).getLength(); if (distToFPPVert > distTarget) continue; - getBestQualityCollapse(a, edge, FPP->vert, collapse, best); + getBestQualityCollapse(adapt, edge, vert, collapse, best); } if (best.quality > 0) - return tryCollapseEdge(a, best.edge, best.keep, collapse); + return tryCollapseEdge(adapt, best.edge, best.keep, collapse); else return false; } @@ -629,9 +629,9 @@ bool Snapper::run() FirstProblemPlane* FPP = getFPP(adapt, vert, snapTag, invalid); - if (!success) success = tryCollapseToVertex(adapt, collapse, FPP); - // if (!success) success = tryReduceCommonEdges(adapt, collapse, FPP); - if (!success) success = tryCollapseTetEdges(adapt, collapse, FPP); + if (!success) success = tryCollapseToVertex(FPP); + // if (!success) success = tryReduceCommonEdges(FPP); + if (!success) success = tryCollapseTetEdges(FPP); if (!success) success = trySwapOrSplit(FPP); // if (!success && ++numFailed == 1) printFPP(adapt, FPP); diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 0ae860bb6..e2897f8af 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -48,6 +48,9 @@ class Snapper EdgeSwap* edgeSwap; bool isSimple; + bool tryCollapseToVertex(FirstProblemPlane* FPP); + bool tryCollapseTetEdges(FirstProblemPlane* FPP); + bool tryReduceCommonEdges(FirstProblemPlane* FPP); bool trySwapOrSplit(FirstProblemPlane* FPP); }; From 0843609691ee1c05037a8abbb14c4263c1bec2ae Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 24 May 2025 14:53:47 -0400 Subject: [PATCH 060/181] remove unused --- ma/maSnap.cc | 2 +- ma/maSnapper.cc | 2 -- ma/maSnapper.h | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 4dc5a0cd7..8c5114c81 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -770,7 +770,7 @@ class SnapAll : public Operator void apply() { bool snapped = snapper.run(); - didAnything = didAnything || snapped || snapper.dug; + didAnything = didAnything || snapped; if (snapped) ++successCount; clearFlag(adapter, vert, SNAP); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index f3c2dd559..481a9c3d9 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -26,8 +26,6 @@ Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a) snapTag = st; collapse.Init(a); edgeSwap = makeEdgeSwap(a); - isSimple = is; - dug = false; vert = 0; } diff --git a/ma/maSnapper.h b/ma/maSnapper.h index e2897f8af..f67861f4c 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -36,8 +36,6 @@ class Snapper bool requestLocality(apf::CavityOp* o); bool trySimpleSnap(); bool run(); - bool dug; - bool moved; private: Adapt* adapt; Mesh* mesh; @@ -46,7 +44,6 @@ class Snapper Collapse collapse; SingleSplitCollapse splitCollapse; EdgeSwap* edgeSwap; - bool isSimple; bool tryCollapseToVertex(FirstProblemPlane* FPP); bool tryCollapseTetEdges(FirstProblemPlane* FPP); From be2c1e60721c1c99975d0cd8a8e008465826462b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 24 May 2025 17:54:31 -0400 Subject: [PATCH 061/181] print values --- ma/maSnap.cc | 18 +++++++----------- ma/maSnapper.cc | 30 +++++++++++++++++++++--------- ma/maSnapper.h | 7 +++++++ 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 8c5114c81..2aecdfad6 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -912,28 +912,22 @@ long snapTaggedVerts(Adapt* a, Tag* tag) return successCount; } -void trySnapping(Adapt* a, Tag* snapTag) +void trySnapping(Adapt* a, Snapper& snapper) { - Snapper snapper(a, snapTag, false); Refine* refine = a->refine; - print(a->mesh->getPCU(), "Number of vertices be snapped %d\n", refine->vtxToSnap.size()); bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; - int numFailed = 0; while (refine->vtxToSnap.size() > 0) { Entity* vertex = refine->vtxToSnap.front(); refine->vtxToSnap.pop(); snapper.setVert(vertex); - if (!snapper.run()) - numFailed++; - else if (getFlag(a, vertex, SNAP)) + if (snapper.run() && getFlag(a, vertex, SNAP)) refine->vtxToSnap.push(vertex); } a->input->shouldForceAdaptation = shouldForce; - print(a->mesh->getPCU(), "Number of vertices failed %d\n", numFailed); } void snap(Adapt* a) @@ -943,13 +937,14 @@ void snap(Adapt* a) double t0 = pcu::Time(); Tag* snapTag; // preventMatchedCavityMods(a); - tagVertsToSnap(a, snapTag); + int toSnap = tagVertsToSnap(a, snapTag); // ma_dbg::addTargetLocation(a, "snap_target"); // ma_dbg::addClassification(a, "classification"); // apf::writeVtkFiles("before_last_snap", a->mesh); - trySnapping(a, snapTag); + Snapper snapper(a, snapTag, false); + trySnapping(a, snapper); // snapLayer(a, tag); // apf::writeVtkFiles("after_last_snap", a->mesh); @@ -960,7 +955,8 @@ void snap(Adapt* a) a->refine->vtxToSnap = {}; double t1 = pcu::Time(); - print(a->mesh->getPCU(), "snapped in %f seconds\n", t1 - t0); + print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds\n", + toSnap, snapper.numSnapped, snapper.numFailed, snapper.numCollapseToVtx, snapper.numCollapse, snapper.numSwap, snapper.numSplitCollapse, t1 - t0); // if (a->hasLayer) // checkLayerShape(a->mesh, "after snapping"); } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 481a9c3d9..7e2b19c7d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -380,13 +380,17 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) if (bit==3 || bit==5 || bit==6) { // check edge swapping for (int i=0; i<2; i++) - if (edgeSwap->run(ents[i])) //TODO: Select best + if (edgeSwap->run(ents[i])) { //TODO: Select best + numSwap++; return true; + } // check split+collapse for (int i=0; i<2; i++) - if (splitCollapse.run(ents[i], FPP->vert)) //TODO: Select best + if (splitCollapse.run(ents[i], FPP->vert)) { //TODO: Select best + numSplitCollapse++; return true; + } } // three large dihedral angles -> key entity: a mesh face else { @@ -395,14 +399,18 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); for (int i=0; i<3; i++) { - if (edgeSwap->run(edges[i])) //TODO: Select best + if (edgeSwap->run(edges[i])) { //TODO: Select best + numSwap++; return true; + } } //TODO: IMPLEMENT FACE SWAP - if (splitCollapse.run(ents[1], FPP->vert)); + if (splitCollapse.run(ents[1], FPP->vert)) { + numSplitCollapse++; return true; + } //TODO: USE DOUBLE SPLIT COLLAPSE } @@ -503,8 +511,10 @@ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) } } - if (best.quality > 0) + if (best.quality > 0) { + numCollapse++; return tryCollapseEdge(adapt, best.edge, best.keep, collapse); + } else return false; } @@ -564,8 +574,10 @@ bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) getBestQualityCollapse(adapt, edge, vert, collapse, best); } - if (best.quality > 0) + if (best.quality > 0) { + numCollapseToVtx++; return tryCollapseEdge(adapt, best.edge, best.keep, collapse); + } else return false; } @@ -612,14 +624,13 @@ bool Snapper::trySimpleSnap() return tryReposition(adapt, vert, snapTag, invalid); } -static int numFailed = 0; //TODO: REMOVE - bool Snapper::run() { apf::Up invalid; bool success = tryReposition(adapt, vert, snapTag, invalid); if (success) { + numSnapped++; mesh->removeTag(vert,snapTag); clearFlag(adapt, vert, SNAP); return true; @@ -632,7 +643,8 @@ bool Snapper::run() if (!success) success = tryCollapseTetEdges(FPP); if (!success) success = trySwapOrSplit(FPP); - // if (!success && ++numFailed == 1) printFPP(adapt, FPP); + if (!success) numFailed++; + // if (!success && numFailed == 1) printFPP(adapt, FPP); if (FPP) delete FPP; return success; diff --git a/ma/maSnapper.h b/ma/maSnapper.h index f67861f4c..469a2abcc 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -29,6 +29,13 @@ class FirstProblemPlane; class Snapper { public: + int numFailed = 0; + int numSnapped = 0; + int numCollapseToVtx = 0; + int numCollapse = 0; + int numSwap = 0; + int numSplitCollapse = 0; + Snapper(Adapt* a, Tag* st, bool is); ~Snapper(); void setVert(Entity* v); From fd8ba386ef5b56d34036841b95aa5eb186c2bb19 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sun, 25 May 2025 12:26:20 -0400 Subject: [PATCH 062/181] fixed collapse bug --- ma/maCollapse.cc | 53 ++++++++---------------------------------------- ma/maCollapse.h | 2 -- ma/maSnap.cc | 4 ---- ma/maSnapper.cc | 22 +++++++++++--------- 4 files changed, 21 insertions(+), 60 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 246600750..d12b4613d 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -77,30 +77,10 @@ bool Collapse::edgesGoodSize() { } } // printf("maxSize %f Ratio %f\n", maxSize, ratioAtMaxSize); - if (maxSize > 1.52 && ratioAtMaxSize > 1.2 ) return false; + if (maxSize > 1.5 && ratioAtMaxSize > 1.2 ) return false; return true; } -double Collapse::getQualityThisDirection() { - PCU_ALWAYS_ASSERT( ! adapt->mesh->isShared(vertToCollapse)); - rebuildElements(); - // check quality of linear t before fitting - if ((adapt->mesh->getDimension()==2) - &&( ! isGood2DMesh())) - return -1; - // check the linear quality of tets before fitting - // reject if one is negative - if(adapt->mesh->getDimension()==3 && cavity.shouldFit - && !areTetsValid(adapt->mesh,newElements)) - return -1; - // make sure we aren't undoing refinement - if(!edgesGoodSize()) - return -1; - // since they are okay in a linear sense, now fit and do a quality assessment - fitElements(); - return getWorstQuality(adapt, newElements); -} - bool Collapse::tryThisDirection(double qualityToBeat) { if (!tryThisDirectionNoCancel(qualityToBeat)) { @@ -123,34 +103,19 @@ bool Collapse::tryBothDirections(double qualityToBeat) if (tryThisDirectionNoCancel(qualityToBeat)) return true; - else - destroyNewElements(); - - if ( ! getFlag(adapt,vertToKeep,COLLAPSE)) - return false; - std::swap(vertToKeep,vertToCollapse); - computeElementSets(); - if (!adapt->input->shouldForceAdaptation) - qualityToBeat = std::min(adapt->input->goodQuality, - std::max(getOldQuality(),adapt->input->validQuality)); - - return tryThisDirection(qualityToBeat); -} - -double Collapse::getQualityFromCollapse() { - computeElementSets(); - double q = getQualityThisDirection(); + destroyNewElements(); - if (q == -1) { - if (!getFlag(adapt,vertToKeep,COLLAPSE)) - return false; + + if (getFlag(adapt,vertToKeep,COLLAPSE)) { std::swap(vertToKeep,vertToCollapse); computeElementSets(); - q = std::max(q, getQualityThisDirection()); - destroyNewElements(); + if (tryThisDirectionNoCancel(qualityToBeat)) + return true; } + + destroyNewElements(); unmark(); - return q; + return false; } bool Collapse::setEdge(Entity* e) diff --git a/ma/maCollapse.h b/ma/maCollapse.h index 2500e9b6f..d9a449adf 100644 --- a/ma/maCollapse.h +++ b/ma/maCollapse.h @@ -42,8 +42,6 @@ class Collapse bool tryBothDirections(double qualityToBeat); void getOldElements(EntityArray& oldElements); bool edgesGoodSize(); - double getQualityThisDirection(); - double getQualityFromCollapse(); double getOldQuality(); Adapt* adapt; Entity* edge; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 2aecdfad6..d8033b1ac 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -941,15 +941,11 @@ void snap(Adapt* a) // ma_dbg::addTargetLocation(a, "snap_target"); // ma_dbg::addClassification(a, "classification"); - // apf::writeVtkFiles("before_last_snap", a->mesh); Snapper snapper(a, snapTag, false); trySnapping(a, snapper); // snapLayer(a, tag); - // apf::writeVtkFiles("after_last_snap", a->mesh); - - // clearFlagFromDimension(a, COLLAPSE, 1); //TODO: Figure out what is making this neccessary clearFlagFromDimension(a, SNAP, 0); //TODO: should not be neccessary a->mesh->destroyTag(snapTag); a->refine->vtxToSnap = {}; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 7e2b19c7d..b1e35f810 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -372,7 +372,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) for(int i=1; i<4; i++) if( area[i] best.quality) { - best.quality = quality; - best.edge = edge; - best.keep = keep; - } + if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo()) { + collapse.computeElementSets(); + if (collapse.tryThisDirectionNoCancel(0) && collapse.edgesGoodSize()) { + double quality = getWorstQuality(a, collapse.newElements); + if (quality > best.quality) { + best.quality = quality; + best.edge = edge; + best.keep = keep; + } + } + collapse.cancel(); } if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); } From c2b3a30758d09fd0b43d0568f8692677217e53aa Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sun, 25 May 2025 13:25:58 -0400 Subject: [PATCH 063/181] max length --- ma/ma.cc | 2 +- ma/maCollapse.cc | 8 +++----- ma/maSize.cc | 4 ++-- ma/maSize.h | 2 ++ ma/maSnap.cc | 12 ++++++------ 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index 24c5100ce..b1aa8c3f9 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -100,7 +100,7 @@ void adaptVerbose(Input* in, bool verbose) int count = 0; double lMax = ma::getMaximumEdgeLength(a->mesh, a->sizeField); print(a->mesh->getPCU(), "Maximum (metric) edge length in the mesh is %f", lMax); - while (lMax > 1.5) { + while (lMax > MAXLENGTH) { print(a->mesh->getPCU(), "%dth additional refine-snap call", count); refine(a); snap(a); diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index d12b4613d..2eb9e3fcf 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -76,8 +76,7 @@ bool Collapse::edgesGoodSize() { } } } - // printf("maxSize %f Ratio %f\n", maxSize, ratioAtMaxSize); - if (maxSize > 1.5 && ratioAtMaxSize > 1.2 ) return false; + if (maxSize > MAXLENGTH && ratioAtMaxSize > 1.2 ) return false; return true; } @@ -103,17 +102,16 @@ bool Collapse::tryBothDirections(double qualityToBeat) if (tryThisDirectionNoCancel(qualityToBeat)) return true; - - destroyNewElements(); + else destroyNewElements(); if (getFlag(adapt,vertToKeep,COLLAPSE)) { std::swap(vertToKeep,vertToCollapse); computeElementSets(); if (tryThisDirectionNoCancel(qualityToBeat)) return true; + else destroyNewElements(); } - destroyNewElements(); unmark(); return false; } diff --git a/ma/maSize.cc b/ma/maSize.cc index 7f097d2eb..e596d0788 100644 --- a/ma/maSize.cc +++ b/ma/maSize.cc @@ -216,11 +216,11 @@ struct MetricSizeField : public SizeField } bool shouldSplit(Entity* edge) { - return this->measure(edge) > 1.5; + return this->measure(edge) > MAXLENGTH; } bool shouldCollapse(Entity* edge) { - return this->measure(edge) < 0.5; + return this->measure(edge) < MINLENGTH; } double getWeight(Entity* e) { diff --git a/ma/maSize.h b/ma/maSize.h index dd88dc643..da3c8b9a2 100644 --- a/ma/maSize.h +++ b/ma/maSize.h @@ -19,6 +19,8 @@ namespace ma { typedef apf::Matrix3x3 Matrix; +const double MAXLENGTH = 1.5; +const double MINLENGTH = 0.5; class SizeField { diff --git a/ma/maSnap.cc b/ma/maSnap.cc index d8033b1ac..9d72d6e37 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -914,17 +914,17 @@ long snapTaggedVerts(Adapt* a, Tag* tag) void trySnapping(Adapt* a, Snapper& snapper) { - Refine* refine = a->refine; + std::queue* vtxToSnap = &a->refine->vtxToSnap; bool shouldForce = a->input->shouldForceAdaptation; - a->input->shouldForceAdaptation = true; + a->input->shouldForceAdaptation = true; //Allows quality to decrease from snapping - while (refine->vtxToSnap.size() > 0) + while (vtxToSnap->size() > 0) { - Entity* vertex = refine->vtxToSnap.front(); - refine->vtxToSnap.pop(); + Entity* vertex = vtxToSnap->front(); + vtxToSnap->pop(); snapper.setVert(vertex); if (snapper.run() && getFlag(a, vertex, SNAP)) - refine->vtxToSnap.push(vertex); + vtxToSnap->push(vertex); } a->input->shouldForceAdaptation = shouldForce; From c283fe4a9ac6ea55e190c6205a8274514d4a5664 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sun, 25 May 2025 15:47:45 -0400 Subject: [PATCH 064/181] simplify code --- ma/maCollapse.cc | 1 - ma/maSnap.cc | 9 +++------ ma/maSnapper.cc | 6 +++++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 2eb9e3fcf..05ee1b873 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -89,7 +89,6 @@ bool Collapse::tryThisDirection(double qualityToBeat) return true; } -//TODO: Test this change bool Collapse::tryBothDirections(double qualityToBeat) { computeElementSets(); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 9d72d6e37..ccd1262a5 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -848,7 +848,6 @@ long tagVertsToSnap(Adapt* a, Tag*& tag) Mesh* m = a->mesh; Refine* refine = a->refine; int dim = m->getDimension(); - tag = m->createDoubleTag("ma_snap", 3); int notProcessed = refine->vtxToSnap.size(); int owned = 0; while (notProcessed > 0) @@ -928,6 +927,7 @@ void trySnapping(Adapt* a, Snapper& snapper) } a->input->shouldForceAdaptation = shouldForce; + a->refine->vtxToSnap = {}; } void snap(Adapt* a) @@ -935,7 +935,7 @@ void snap(Adapt* a) if (!a->input->shouldSnap) return; double t0 = pcu::Time(); - Tag* snapTag; + Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); // preventMatchedCavityMods(a); int toSnap = tagVertsToSnap(a, snapTag); @@ -946,15 +946,12 @@ void snap(Adapt* a) trySnapping(a, snapper); // snapLayer(a, tag); - clearFlagFromDimension(a, SNAP, 0); //TODO: should not be neccessary - a->mesh->destroyTag(snapTag); - a->refine->vtxToSnap = {}; - double t1 = pcu::Time(); print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds\n", toSnap, snapper.numSnapped, snapper.numFailed, snapper.numCollapseToVtx, snapper.numCollapse, snapper.numSwap, snapper.numSplitCollapse, t1 - t0); // if (a->hasLayer) // checkLayerShape(a->mesh, "after snapping"); + a->mesh->destroyTag(snapTag); } void prevSnap(Adapt* a) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index b1e35f810..e5e583070 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -645,7 +645,11 @@ bool Snapper::run() if (!success) success = tryCollapseTetEdges(FPP); if (!success) success = trySwapOrSplit(FPP); - if (!success) numFailed++; + if (!success) { + numFailed++; + mesh->removeTag(vert,snapTag); + clearFlag(adapt, vert, SNAP); + } // if (!success && numFailed == 1) printFPP(adapt, FPP); if (FPP) delete FPP; From 4cd294538e6056d2c3675585ca9d0c0c43e303e9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 29 May 2025 20:50:24 -0400 Subject: [PATCH 065/181] fixed split collapse bug --- ma/maCoarsen.cc | 63 ------------------------------------- ma/maSingleSplitCollapse.cc | 4 +-- ma/maSingleSplitCollapse.h | 2 +- ma/maSnapper.cc | 23 +++++++++----- ma/maSnapper.h | 2 ++ test/coarsen.cc | 2 +- 6 files changed, 22 insertions(+), 74 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 96872af5d..0014b1f90 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -254,69 +254,6 @@ bool coarsen(Adapt* a) return true; } -void printFields(Adapt* a, Mesh* m, std::string name) -{ - apf::Field* f = m->findField("collapse_edges"); - if (!f) - f = apf::createField(m, "collapse_edges", apf::SCALAR, apf::getConstant(1)); - apf::MeshIterator* it = m->begin(1); - apf::MeshEntity* e; - while ((e = m->iterate(it))) { - if (getFlag(a, e, COLLAPSE)) - apf::setScalar(f, e, 0, 1); - else - apf::setScalar(f, e, 0, 0); - } - m->end(it); - - f = m->findField("collapse_verts"); - if (!f) - f = apf::createFieldOn(m, "collapse_verts", apf::SCALAR); - it = m->begin(0); - while ((e = m->iterate(it))) { - if (getFlag(a, e, COLLAPSE)) - apf::setScalar(f, e, 0, 1); - else - apf::setScalar(f, e, 0, 0); - } - m->end(it); - - apf::writeVtkFiles(name.c_str(), m, 1); -} - -bool coarsenAndPrint(Adapt* a) -{ - if (!a->input->shouldCoarsen) - return false; - double t0 = pcu::Time(); - --(a->coarsensLeft); - long count = markEdgesToCollapse(a); - if ( ! count) - return false; - Mesh* m = a->mesh; - int maxDimension = m->getDimension(); - PCU_ALWAYS_ASSERT(checkFlagConsistency(a,1,COLLAPSE)); - long successCount = 0; - printFields(a, m, "flag_edges"); - - for (int modelDimension=1; modelDimension <= maxDimension; ++modelDimension) - { - checkAllEdgeCollapses(a,modelDimension); - std::string dim = std::to_string(modelDimension); - printFields(a, m, "flag_verts"+dim); - findIndependentSet(a); - printFields(a, m, "independent_set"+dim); - if (m->hasMatching()) - successCount += collapseMatchedEdges(a, modelDimension); - else - successCount += collapseAllEdges(a, modelDimension); - apf::writeVtkFiles(("after_collapse"+dim).c_str(), m, 1); - } - successCount = m->getPCU()->Add(successCount); - double t1 = pcu::Time(); - print(m->getPCU(), "coarsened %li edges in %f seconds", successCount,t1-t0); - return true; -} } diff --git a/ma/maSingleSplitCollapse.cc b/ma/maSingleSplitCollapse.cc index 824816d42..afc83e1cd 100644 --- a/ma/maSingleSplitCollapse.cc +++ b/ma/maSingleSplitCollapse.cc @@ -59,7 +59,7 @@ void SingleSplitCollapse::accept() collapse.destroyOldElements(); } -bool SingleSplitCollapse::run(Entity* edge, Entity* vert) +bool SingleSplitCollapse::run(Entity* edge, Entity* vert, double quality) { oldEdge = edge; oldVert = vert; @@ -67,7 +67,7 @@ bool SingleSplitCollapse::run(Entity* edge, Entity* vert) Mesh* m = a->mesh; if ( ! splits.setEdges(&edge,1)) return false; - oldQuality = getWorstQuality(a,splits.getTets()); + oldQuality = (quality == -1) ? getWorstQuality(a,splits.getTets()) : 0; splits.makeNewElements(); splits.transfer(); Entity* collVerts[2]; diff --git a/ma/maSingleSplitCollapse.h b/ma/maSingleSplitCollapse.h index a0dd30620..712e412ed 100644 --- a/ma/maSingleSplitCollapse.h +++ b/ma/maSingleSplitCollapse.h @@ -32,7 +32,7 @@ class SingleSplitCollapse bool tryThisCollapse(); bool tryBothCollapses(Entity* e); void accept(); - bool run(Entity* edge, Entity* vert); + bool run(Entity* edge, Entity* vert, double quality=-1); Adapt* getAdapt(); private: Entity *oldVert, *oldEdge; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index e5e583070..3c3a50d1d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -19,7 +19,7 @@ namespace ma { -Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a) +Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a), doubleSplitCollapse(a) { adapt = a; mesh = a->mesh; @@ -363,7 +363,10 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { - if (FPP->commEdges.n < 2) return false; + if (FPP->commEdges.n < 2) { + print(mesh->getPCU(), "Swap failed: consider more collapses before swap"); + return false; + } Entity* ents[4]; double area[4]; int bit = getTetStats(adapt, FPP, ents, area); @@ -373,7 +376,8 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) if( area[i]getPCU(), "Swap failed: small base area case not implemented"); + return false; } // two large dihedral angles -> key problem: two mesh edges @@ -407,15 +411,18 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) //TODO: IMPLEMENT FACE SWAP - if (splitCollapse.run(ents[1], FPP->vert)) { + if (splitCollapse.run(ents[1], FPP->vert, 0)) { numSplitCollapse++; return true; } - //TODO: USE DOUBLE SPLIT COLLAPSE + // if (doubleSplitCollapse.run(ents)) { //TODO: TEST DOUBLE SPLIT COLLAPSE + // numSplitCollapse++; + // return true; + // } } - + print(mesh->getPCU(), "Swap failed: face swap and double split collapse not implemented"); return false; } @@ -552,8 +559,10 @@ bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) break; } } - if (best.quality > 0) + if (best.quality > 0) { + numCollapse++; return tryCollapseEdge(adapt, best.edge, best.keep, collapse); + } else return false; } diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 469a2abcc..3d6c0d6b3 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -12,6 +12,7 @@ #include "maCollapse.h" #include "maSingleSplitCollapse.h" +#include "maDoubleSplitCollapse.h" #include "maEdgeSwap.h" namespace apf { @@ -50,6 +51,7 @@ class Snapper Entity* vert; Collapse collapse; SingleSplitCollapse splitCollapse; + DoubleSplitCollapse doubleSplitCollapse; EdgeSwap* edgeSwap; bool tryCollapseToVertex(FirstProblemPlane* FPP); diff --git a/test/coarsen.cc b/test/coarsen.cc index 6f6da4294..be359f83a 100644 --- a/test/coarsen.cc +++ b/test/coarsen.cc @@ -90,7 +90,7 @@ int main(int argc, char** argv) in->shouldCoarsen = true; validateInput(in); ma::Adapt* a = new ma::Adapt(in); - coarsenAndPrint(a); + coarsen(a); m->verify(); apf::writeVtkFiles("after_coarsen", m, 1); From c524541e0947b46420e63cc4bd78d6f02c7ba0e0 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 29 May 2025 23:07:57 -0400 Subject: [PATCH 066/181] fixed split collapse bug --- ma/maCoarsen.cc | 108 ++++++++++++++++++++++++++++++++++++ ma/maDoubleSplitCollapse.cc | 4 +- ma/maDoubleSplitCollapse.h | 2 +- ma/maSingleSplitCollapse.cc | 2 +- ma/maSnapper.cc | 4 +- 5 files changed, 114 insertions(+), 6 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 0014b1f90..0a0cd4e87 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -14,6 +14,7 @@ #include "maOperator.h" #include #include "apfShape.h" +#include namespace ma { @@ -255,5 +256,112 @@ bool coarsen(Adapt* a) } +static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + + bool result = false; + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo() && + collapse.tryBothDirections(0)) { + result = true; + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); + return result; +} + + +Entity* getAdjacentShortestEdge(Adapt* a, Entity* vertex) +{ + apf::Up edges; + a->mesh->getUp(vertex,edges); + double minLength = 999999; + Entity* minEdge; + for (int i=0; i < edges.n; i++) { + double length = a->sizeField->measure(edges.e[i]); + if (length < minLength) { + minLength = length; + minEdge = edges.e[i]; + } + } + return minEdge; +} + +void markAdjacentVerts(Adapt* a, Entity* vertex) +{ + apf::Up edges; + a->mesh->getUp(vertex,edges); + for (int i=0; i < edges.n; i++) { + Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); + setFlag(a, opposite, CHECKED); + } +} + +bool isIndependent(Adapt* a, Entity* vertex) +{ + if (getFlag(a, vertex, CHECKED)) return false; + apf::Up edges; + a->mesh->getUp(vertex,edges); + for (int i=0; i < edges.n; i++) { + Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); + if (getFlag(a, opposite, CHECKED)) return true; + } + return false; +} + + +bool newCoarsen(Adapt* a) +{ + std::queue shortEdgeVerts; + Iterator* it = a->mesh->begin(1); + Entity* edge; + while ((edge = a->mesh->iterate(it))) + { + if (!a->sizeField->shouldCollapse(edge)) continue; + Entity* vertices[2]; + a->mesh->getDownward(edge,0,vertices); + for (int i = 0; i < 2; i++) { + setFlag(a, vertices[i], COLLAPSE); + shortEdgeVerts.push(vertices[i]); + } + } + + Collapse collapse; + collapse.Init(a); + int success = 0; + int failed = 0; + bool independentSetStarted = false; + int proccessed = 0; + while (shortEdgeVerts.size() > 0) + { + Entity* vertex = shortEdgeVerts.front(); + shortEdgeVerts.pop(); + + if (independentSetStarted && !isIndependent(a, vertex)) { + shortEdgeVerts.push(vertex); + if (++processed == shortEdgeVerts.size()) + ma::clearFlagFromDimension(a, CHECKED, 0); + continue; + } + + Entity* shortEdge = getAdjacentShortestEdge(a, vertex); + if (!a->sizeField->shouldCollapse(shortEdge)) continue; + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); + if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { + markAdjacentVerts(a, vertex); + collapse.destroyOldElements(); + independentSetStarted = true; + success++; + } + else failed++; + } + + return true; +} + } diff --git a/ma/maDoubleSplitCollapse.cc b/ma/maDoubleSplitCollapse.cc index d0457e54c..dfd69f9c1 100644 --- a/ma/maDoubleSplitCollapse.cc +++ b/ma/maDoubleSplitCollapse.cc @@ -55,13 +55,13 @@ void DoubleSplitCollapse::accept() collapse.destroyOldElements(); } -bool DoubleSplitCollapse::run(Entity** edges) +bool DoubleSplitCollapse::run(Entity** edges, double quality) { Adapt* a = getAdapt(); Mesh* m = a->mesh; if ( ! splits.setEdges(edges,2)) return false; - oldQuality = getWorstQuality(a,splits.getTets()); + oldQuality = (quality >= 0) ? quality : getWorstQuality(a,splits.getTets()); splits.makeNewElements(); splits.transfer(); Entity* splitVerts[2]; diff --git a/ma/maDoubleSplitCollapse.h b/ma/maDoubleSplitCollapse.h index 52124378b..42c8a9f06 100644 --- a/ma/maDoubleSplitCollapse.h +++ b/ma/maDoubleSplitCollapse.h @@ -24,7 +24,7 @@ class DoubleSplitCollapse bool tryThisCollapse(); bool tryBothCollapses(Entity* e); void accept(); - bool run(Entity** edges); + bool run(Entity** edges, double quality = -1); Adapt* getAdapt(); private: Splits splits; diff --git a/ma/maSingleSplitCollapse.cc b/ma/maSingleSplitCollapse.cc index afc83e1cd..1c326db85 100644 --- a/ma/maSingleSplitCollapse.cc +++ b/ma/maSingleSplitCollapse.cc @@ -67,7 +67,7 @@ bool SingleSplitCollapse::run(Entity* edge, Entity* vert, double quality) Mesh* m = a->mesh; if ( ! splits.setEdges(&edge,1)) return false; - oldQuality = (quality == -1) ? getWorstQuality(a,splits.getTets()) : 0; + oldQuality = (quality >= 0 ) ? quality : getWorstQuality(a,splits.getTets()); splits.makeNewElements(); splits.transfer(); Entity* collVerts[2]; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 3c3a50d1d..e9eb8ced1 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -391,7 +391,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) // check split+collapse for (int i=0; i<2; i++) - if (splitCollapse.run(ents[i], FPP->vert)) { //TODO: Select best + if (splitCollapse.run(ents[i], FPP->vert, 0)) { //TODO: Select best numSplitCollapse++; return true; } @@ -416,7 +416,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) return true; } - // if (doubleSplitCollapse.run(ents)) { //TODO: TEST DOUBLE SPLIT COLLAPSE + // if (doubleSplitCollapse.run(ents, 0)) { //TODO: TEST DOUBLE SPLIT COLLAPSE // numSplitCollapse++; // return true; // } From c472fccd6879eb0ec05250784d0014cab93cdf25 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 30 May 2025 09:00:14 -0400 Subject: [PATCH 067/181] refactor aniso ma test --- test/aniso_ma_test.cc | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/test/aniso_ma_test.cc b/test/aniso_ma_test.cc index f1d99a360..9fc9d6d19 100644 --- a/test/aniso_ma_test.cc +++ b/test/aniso_ma_test.cc @@ -8,42 +8,11 @@ #include -class AnIso : public ma::AnisotropicFunction -{ - public: - AnIso(ma::Mesh* m) - { - mesh = m; - average = ma::getAverageEdgeLength(m); - ma::getBoundingBox(m,lower,upper); - } - virtual void getValue(ma::Entity* v, ma::Matrix& R, ma::Vector& H) - { - ma::Vector p = ma::getPosition(mesh,v); - double x = (p[0] - lower[0])/(upper[0] - lower[0]); - double sizeFactor = 2.; - if (x < 0.5) - sizeFactor = 3.; - ma::Vector h(average, average/sizeFactor, average/sizeFactor); - ma::Matrix r(1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0); - H = h; - R = r; - } - private: - ma::Mesh* mesh; - double average; - ma::Vector lower; - ma::Vector upper; -}; - int main(int argc, char** argv) { PCU_ALWAYS_ASSERT(argc==4); const char* modelFile = argv[1]; const char* meshFile = argv[2]; - bool logInterpolation = atoi(argv[3]) > 0 ? true : false; pcu::Init(&argc,&argv); { pcu::PCU PCUObj; @@ -54,10 +23,6 @@ int main(int argc, char** argv) apf::writeVtkFiles("aniso_before",m); AnIso sf(m); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf, 0, logInterpolation)); - in->shouldRunPreZoltan = true; - in->shouldRunMidParma = true; - in->shouldRunPostParma = true; - in->shouldRefineLayer = true; in->goodQuality = 0.2; ma::adapt(in); m->verify(); From 1e72aa9791eea598e67d1f466483801527cdf3bc Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 30 May 2025 13:07:14 -0400 Subject: [PATCH 068/181] prepare to test coarsen --- ma/maCoarsen.cc | 6 +++--- test/aniso_adapt.h | 10 +++++----- test/aniso_ma_test.cc | 16 +++------------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 0a0cd4e87..66dc0a2f5 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -227,7 +227,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool coarsen(Adapt* a) +bool oldCoarsen(Adapt* a) { if (!a->input->shouldCoarsen) return false; @@ -314,7 +314,7 @@ bool isIndependent(Adapt* a, Entity* vertex) } -bool newCoarsen(Adapt* a) +bool coarsen(Adapt* a) { std::queue shortEdgeVerts; Iterator* it = a->mesh->begin(1); @@ -343,7 +343,7 @@ bool newCoarsen(Adapt* a) if (independentSetStarted && !isIndependent(a, vertex)) { shortEdgeVerts.push(vertex); - if (++processed == shortEdgeVerts.size()) + if (++proccessed == shortEdgeVerts.size()) ma::clearFlagFromDimension(a, CHECKED, 0); continue; } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 8d2bc63e7..9645376e0 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -41,16 +41,16 @@ class AnIso : public ma::AnisotropicFunction void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) { m->verify(); - apf::writeVtkFiles("before_refine_snap",m); + apf::writeVtkFiles("before_adapt",m); AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < in->maximumIterations; ++i) + for (int i = 0; i < 1; ++i) { ma::coarsen(a); - ma::refine(a); - ma::snap(a); + // ma::refine(a); + // ma::snap(a); } m->verify(); - apf::writeVtkFiles("after_refine_snap",m); + apf::writeVtkFiles("after_adapt",m); } \ No newline at end of file diff --git a/test/aniso_ma_test.cc b/test/aniso_ma_test.cc index 9fc9d6d19..fab5aca87 100644 --- a/test/aniso_ma_test.cc +++ b/test/aniso_ma_test.cc @@ -5,12 +5,12 @@ #include #include #include - #include +#include "aniso_adapt.h" int main(int argc, char** argv) { - PCU_ALWAYS_ASSERT(argc==4); + PCU_ALWAYS_ASSERT(argc==3); const char* modelFile = argv[1]; const char* meshFile = argv[2]; pcu::Init(&argc,&argv); @@ -19,17 +19,7 @@ int main(int argc, char** argv) lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - m->verify(); - apf::writeVtkFiles("aniso_before",m); - AnIso sf(m); - ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf, 0, logInterpolation)); - in->goodQuality = 0.2; - ma::adapt(in); - m->verify(); - if (logInterpolation) - apf::writeVtkFiles("aniso_log_interpolation_after",m); - else - apf::writeVtkFiles("aniso_after",m); + refineSnapTest(m, 0.5, 1); m->destroyNative(); apf::destroyMesh(m); } From 1b8991c94c4773059eb504ff28b02e19945d8404 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 30 May 2025 16:39:00 -0400 Subject: [PATCH 069/181] extract adjacent edges --- ma/maCoarsen.cc | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 66dc0a2f5..74e89548c 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -12,6 +12,7 @@ #include "maCollapse.h" #include "maMatchedCollapse.h" #include "maOperator.h" +#include "maDBG.h" #include #include "apfShape.h" #include @@ -255,6 +256,11 @@ bool oldCoarsen(Adapt* a) return true; } +void printIndependentSet(Adapt* a) { + apf::writeVtkFiles("independentMesh", a->mesh); + ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "independentVerts", "independentVerts"); + exit(0); +} static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) { @@ -275,10 +281,8 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll } -Entity* getAdjacentShortestEdge(Adapt* a, Entity* vertex) +Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) { - apf::Up edges; - a->mesh->getUp(vertex,edges); double minLength = 999999; Entity* minEdge; for (int i=0; i < edges.n; i++) { @@ -291,13 +295,13 @@ Entity* getAdjacentShortestEdge(Adapt* a, Entity* vertex) return minEdge; } -void markAdjacentVerts(Adapt* a, Entity* vertex) +void markDependent(Adapt* a, apf::Up& edges) { - apf::Up edges; - a->mesh->getUp(vertex,edges); for (int i=0; i < edges.n; i++) { - Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); - setFlag(a, opposite, CHECKED); + Entity* vertices[2]; + a->mesh->getDownward(edges.e[i],0, vertices); + setFlag(a, vertices[0], CHECKED); + setFlag(a, vertices[1], CHECKED); } } @@ -305,7 +309,7 @@ bool isIndependent(Adapt* a, Entity* vertex) { if (getFlag(a, vertex, CHECKED)) return false; apf::Up edges; - a->mesh->getUp(vertex,edges); + a->mesh->getUp(vertex, edges); for (int i=0; i < edges.n; i++) { Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); if (getFlag(a, opposite, CHECKED)) return true; @@ -313,7 +317,6 @@ bool isIndependent(Adapt* a, Entity* vertex) return false; } - bool coarsen(Adapt* a) { std::queue shortEdgeVerts; @@ -333,7 +336,6 @@ bool coarsen(Adapt* a) Collapse collapse; collapse.Init(a); int success = 0; - int failed = 0; bool independentSetStarted = false; int proccessed = 0; while (shortEdgeVerts.size() > 0) @@ -348,16 +350,17 @@ bool coarsen(Adapt* a) continue; } - Entity* shortEdge = getAdjacentShortestEdge(a, vertex); + apf::Up edges; + a->mesh->getUp(vertex, edges); + Entity* shortEdge = getAdjacentShortestEdge(a, edges); if (!a->sizeField->shouldCollapse(shortEdge)) continue; Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { - markAdjacentVerts(a, vertex); + markDependent(a, edges); collapse.destroyOldElements(); independentSetStarted = true; success++; } - else failed++; } return true; From ad8615a435e8124000be091fadb505c37c2f25f4 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 30 May 2025 17:47:15 -0400 Subject: [PATCH 070/181] new coarsen passing --- ma/maCoarsen.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 74e89548c..d57c1deb6 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -319,6 +319,8 @@ bool isIndependent(Adapt* a, Entity* vertex) bool coarsen(Adapt* a) { + //Assert that there arent any vertices marked CHECKED + ma::clearFlagFromDimension(a, CHECKED, 0); std::queue shortEdgeVerts; Iterator* it = a->mesh->begin(1); Entity* edge; @@ -328,25 +330,32 @@ bool coarsen(Adapt* a) Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { - setFlag(a, vertices[i], COLLAPSE); + if (getFlag(a, vertices[i], CHECKED)) continue; + setFlag(a, vertices[i], CHECKED); shortEdgeVerts.push(vertices[i]); } } + ma::clearFlagFromDimension(a, CHECKED, 0); Collapse collapse; collapse.Init(a); int success = 0; bool independentSetStarted = false; - int proccessed = 0; + int numChecked = 0; while (shortEdgeVerts.size() > 0) { Entity* vertex = shortEdgeVerts.front(); shortEdgeVerts.pop(); + if (getFlag(a, vertex, CHECKED)) ++numChecked; + if (numChecked == shortEdgeVerts.size()) { + numChecked = 0; + independentSetStarted = false; + ma::clearFlagFromDimension(a, CHECKED, 0); //TODO: maybe only has to be cleared from list + } + if (independentSetStarted && !isIndependent(a, vertex)) { shortEdgeVerts.push(vertex); - if (++proccessed == shortEdgeVerts.size()) - ma::clearFlagFromDimension(a, CHECKED, 0); continue; } From f300a532baa036f7ff9a9357a837483950a92d05 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 30 May 2025 23:27:42 -0400 Subject: [PATCH 071/181] coarsen running --- ma/maCoarsen.cc | 56 ++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index d57c1deb6..e70dd1315 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -15,7 +15,7 @@ #include "maDBG.h" #include #include "apfShape.h" -#include +#include namespace ma { @@ -273,7 +273,7 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo() && - collapse.tryBothDirections(0)) { + collapse.tryBothDirections(a->input->validQuality)) { result = true; } if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); @@ -319,9 +319,8 @@ bool isIndependent(Adapt* a, Entity* vertex) bool coarsen(Adapt* a) { - //Assert that there arent any vertices marked CHECKED ma::clearFlagFromDimension(a, CHECKED, 0); - std::queue shortEdgeVerts; + std::list shortEdgeVerts; Iterator* it = a->mesh->begin(1); Entity* edge; while ((edge = a->mesh->iterate(it))) @@ -332,43 +331,38 @@ bool coarsen(Adapt* a) for (int i = 0; i < 2; i++) { if (getFlag(a, vertices[i], CHECKED)) continue; setFlag(a, vertices[i], CHECKED); - shortEdgeVerts.push(vertices[i]); + shortEdgeVerts.push_back(vertices[i]); } } - ma::clearFlagFromDimension(a, CHECKED, 0); Collapse collapse; collapse.Init(a); int success = 0; - bool independentSetStarted = false; - int numChecked = 0; while (shortEdgeVerts.size() > 0) { - Entity* vertex = shortEdgeVerts.front(); - shortEdgeVerts.pop(); - - if (getFlag(a, vertex, CHECKED)) ++numChecked; - if (numChecked == shortEdgeVerts.size()) { - numChecked = 0; - independentSetStarted = false; - ma::clearFlagFromDimension(a, CHECKED, 0); //TODO: maybe only has to be cleared from list - } + ma::clearFlagFromDimension(a, CHECKED, 0); //TODO: maybe only has to be cleared from list + std::list::iterator i = shortEdgeVerts.begin(); + bool independentSetStarted = false; + while (i != shortEdgeVerts.end()) + { + Entity* vertex = *i++; + if (independentSetStarted && !isIndependent(a, vertex)) + continue; - if (independentSetStarted && !isIndependent(a, vertex)) { - shortEdgeVerts.push(vertex); - continue; - } + apf::Up edges; + a->mesh->getUp(vertex, edges); + Entity* shortEdge = getAdjacentShortestEdge(a, edges); + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - apf::Up edges; - a->mesh->getUp(vertex, edges); - Entity* shortEdge = getAdjacentShortestEdge(a, edges); - if (!a->sizeField->shouldCollapse(shortEdge)) continue; - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { - markDependent(a, edges); - collapse.destroyOldElements(); - independentSetStarted = true; - success++; + if (a->sizeField->shouldCollapse(shortEdge) && + tryCollapseEdge(a, shortEdge, keepVertex, collapse)) //add short edge check + { + markDependent(a, edges); + collapse.destroyOldElements(); + independentSetStarted = true; + success++; + } + i = shortEdgeVerts.erase(--i); } } From 47b3c9729e8db51156e4a35b39e9a863dd4fbf1e Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 31 May 2025 02:04:10 -0400 Subject: [PATCH 072/181] print time --- ma/maCoarsen.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index e70dd1315..07e773754 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -317,8 +317,18 @@ bool isIndependent(Adapt* a, Entity* vertex) return false; } +void clearListFlag(Adapt* a, std::list list, int flag) +{ + auto i = list.begin(); + while (i != list.end()) + clearFlag(a, *i++, flag); +} + bool coarsen(Adapt* a) { + if (!a->input->shouldCoarsen) + return false; + double t0 = pcu::Time(); ma::clearFlagFromDimension(a, CHECKED, 0); std::list shortEdgeVerts; Iterator* it = a->mesh->begin(1); @@ -340,7 +350,7 @@ bool coarsen(Adapt* a) int success = 0; while (shortEdgeVerts.size() > 0) { - ma::clearFlagFromDimension(a, CHECKED, 0); //TODO: maybe only has to be cleared from list + clearListFlag(a, shortEdgeVerts, CHECKED); std::list::iterator i = shortEdgeVerts.begin(); bool independentSetStarted = false; while (i != shortEdgeVerts.end()) @@ -365,7 +375,9 @@ bool coarsen(Adapt* a) i = shortEdgeVerts.erase(--i); } } - + ma::clearFlagFromDimension(a, CHECKED, 0); + double t1 = pcu::Time(); + print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; } From 9bf9bcc34a483602d9d65bc7c05ae19dee8c63dc Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 31 May 2025 17:17:02 -0400 Subject: [PATCH 073/181] small coarsen speedup --- ma/maCoarsen.cc | 15 +++++++++++---- ma/maSnapper.cc | 30 +----------------------------- 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 07e773754..3a37ae113 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -284,8 +284,9 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) { double minLength = 999999; - Entity* minEdge; + Entity* minEdge = 0; for (int i=0; i < edges.n; i++) { + if (!getFlag(a, edges.e[i], CHECKED)) continue; //Used to reduce calls to measure double length = a->sizeField->measure(edges.e[i]); if (length < minLength) { minLength = length; @@ -335,7 +336,8 @@ bool coarsen(Adapt* a) Entity* edge; while ((edge = a->mesh->iterate(it))) { - if (!a->sizeField->shouldCollapse(edge)) continue; + if (!a->sizeField->shouldCollapse(edge)) continue; //TODO: speedup + setFlag(a, edge, CHECKED); //Used to reduce measure calls Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { @@ -362,10 +364,14 @@ bool coarsen(Adapt* a) apf::Up edges; a->mesh->getUp(vertex, edges); Entity* shortEdge = getAdjacentShortestEdge(a, edges); - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); + if (shortEdge == 0) { + i = shortEdgeVerts.erase(--i); + continue; + } + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); if (a->sizeField->shouldCollapse(shortEdge) && - tryCollapseEdge(a, shortEdge, keepVertex, collapse)) //add short edge check + tryCollapseEdge(a, shortEdge, keepVertex, collapse)) //TODO: add short edge check { markDependent(a, edges); collapse.destroyOldElements(); @@ -376,6 +382,7 @@ bool coarsen(Adapt* a) } } ma::clearFlagFromDimension(a, CHECKED, 0); + ma::clearFlagFromDimension(a, CHECKED, 1); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index e9eb8ced1..b012b50fc 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -293,18 +293,10 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double break; } case 3: { - // double L1_xyz[2][3], L2_xyz[2][3]; ents[0]=edges[2]; ents[1]=edges[4]; ents[2]=((area[0] key problem: two mesh edges if (bit==3 || bit==5 || bit==6) { - // check edge swapping for (int i=0; i<2; i++) if (edgeSwap->run(ents[i])) { //TODO: Select best numSwap++; return true; } - // check split+collapse for (int i=0; i<2; i++) if (splitCollapse.run(ents[i], FPP->vert, 0)) { //TODO: Select best numSplitCollapse++; return true; } } - // three large dihedral angles -> key entity: a mesh face + // three large dihedral angles -> key entity: a mesh face else { - - // check edge swaps Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); for (int i=0; i<3; i++) { From c9e14974bb9cfe68a5777b174e42b3370154797c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 4 Jun 2025 18:37:00 -0400 Subject: [PATCH 074/181] get short edge verts --- ma/maCoarsen.cc | 15 ++++++++++----- test/aniso_ma_test.cc | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 3a37ae113..bcd2ca46f 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -325,12 +325,8 @@ void clearListFlag(Adapt* a, std::list list, int flag) clearFlag(a, *i++, flag); } -bool coarsen(Adapt* a) +std::list getShortEdgeVerts(Adapt* a) { - if (!a->input->shouldCoarsen) - return false; - double t0 = pcu::Time(); - ma::clearFlagFromDimension(a, CHECKED, 0); std::list shortEdgeVerts; Iterator* it = a->mesh->begin(1); Entity* edge; @@ -346,6 +342,15 @@ bool coarsen(Adapt* a) shortEdgeVerts.push_back(vertices[i]); } } + return shortEdgeVerts; +} + +bool coarsen(Adapt* a) +{ + if (!a->input->shouldCoarsen) + return false; + double t0 = pcu::Time(); + std::list shortEdgeVerts = getShortEdgeVerts(a); Collapse collapse; collapse.Init(a); diff --git a/test/aniso_ma_test.cc b/test/aniso_ma_test.cc index fab5aca87..77f820712 100644 --- a/test/aniso_ma_test.cc +++ b/test/aniso_ma_test.cc @@ -19,7 +19,7 @@ int main(int argc, char** argv) lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - refineSnapTest(m, 0.5, 1); + refineSnapTest(m, 0.4, 1); m->destroyNative(); apf::destroyMesh(m); } From 0b1a03506c2c1de8076ff9d19e1385ef3adf6aea Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 4 Jun 2025 22:49:58 -0400 Subject: [PATCH 075/181] new coarsen algo --- ma/maAdapt.h | 3 +- ma/maCoarsen.cc | 113 +++++++++++++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 46 deletions(-) diff --git a/ma/maAdapt.h b/ma/maAdapt.h index 0b7a0324d..15d6a48d2 100644 --- a/ma/maAdapt.h +++ b/ma/maAdapt.h @@ -33,7 +33,8 @@ enum { LAYER_UNSNAP = (1<<15), DONT_MOVE = (1<<16), NEED_NOT_SPLIT = (1<<17), - NEED_NOT_COLLAPSE = (1<<18) + NEED_NOT_COLLAPSE = (1<<18), + COARSEN = (1<<19), }; class DeleteCallback; diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index bcd2ca46f..a8537c471 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -256,7 +256,8 @@ bool oldCoarsen(Adapt* a) return true; } -void printIndependentSet(Adapt* a) { +void printIndependentSet(Adapt* a) +{ apf::writeVtkFiles("independentMesh", a->mesh); ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "independentVerts", "independentVerts"); exit(0); @@ -284,9 +285,9 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) { double minLength = 999999; - Entity* minEdge = 0; + Entity* minEdge = edges.e[0]; for (int i=0; i < edges.n; i++) { - if (!getFlag(a, edges.e[i], CHECKED)) continue; //Used to reduce calls to measure + if (!getFlag(a, edges.e[i], COARSEN)) continue; double length = a->sizeField->measure(edges.e[i]); if (length < minLength) { minLength = length; @@ -296,33 +297,54 @@ Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) return minEdge; } -void markDependent(Adapt* a, apf::Up& edges) +void flagAdjacent(Adapt* a, apf::Up& edges, int& checked) { for (int i=0; i < edges.n; i++) { Entity* vertices[2]; a->mesh->getDownward(edges.e[i],0, vertices); - setFlag(a, vertices[0], CHECKED); - setFlag(a, vertices[1], CHECKED); + for (int i = 0; i < 2; i++) { + setFlag(a, vertices[i], NEED_NOT_COLLAPSE); + if (getFlag(a, vertices[i], COARSEN) && getFlag(a, vertices[i], CHECKED)){ + clearFlag(a, vertices[i], CHECKED); + checked--; + } + } } } +void clearListFlag(Adapt* a, std::list list, int flag) +{ + auto i = list.begin(); + while (i != list.end()) + clearFlag(a, *i++, flag); +} + bool isIndependent(Adapt* a, Entity* vertex) { - if (getFlag(a, vertex, CHECKED)) return false; + if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) return false; apf::Up edges; a->mesh->getUp(vertex, edges); for (int i=0; i < edges.n; i++) { Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); - if (getFlag(a, opposite, CHECKED)) return true; + if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return true; } return false; } -void clearListFlag(Adapt* a, std::list list, int flag) +Entity* getNextIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted) { - auto i = list.begin(); - while (i != list.end()) - clearFlag(a, *i++, flag); + while (i != shortEdgeVerts.end()) + { + Entity* vertex = *i; + if (getFlag(a, vertex, CHECKED)) {i++; continue;} + if (!independentSetStarted || isIndependent(a, vertex)) + return vertex; + i++; + } + clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); + independentSetStarted = false; + i = shortEdgeVerts.begin(); + return 0; } std::list getShortEdgeVerts(Adapt* a) @@ -333,15 +355,16 @@ std::list getShortEdgeVerts(Adapt* a) while ((edge = a->mesh->iterate(it))) { if (!a->sizeField->shouldCollapse(edge)) continue; //TODO: speedup - setFlag(a, edge, CHECKED); //Used to reduce measure calls + setFlag(a, edge, COARSEN); Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { - if (getFlag(a, vertices[i], CHECKED)) continue; - setFlag(a, vertices[i], CHECKED); + if (getFlag(a, vertices[i], COARSEN)) continue; + setFlag(a, vertices[i], COARSEN); shortEdgeVerts.push_back(vertices[i]); } } + // ma_dbg::dumpMeshWithFlag(a, 0, 1, COARSEN, "shortEdges", "shortEdges"); return shortEdgeVerts; } @@ -355,39 +378,39 @@ bool coarsen(Adapt* a) Collapse collapse; collapse.Init(a); int success = 0; - while (shortEdgeVerts.size() > 0) + int checked = 0; + bool independentSetStarted = false; + std::list::iterator i = shortEdgeVerts.begin(); + while (checked < shortEdgeVerts.size()) { - clearListFlag(a, shortEdgeVerts, CHECKED); - std::list::iterator i = shortEdgeVerts.begin(); - bool independentSetStarted = false; - while (i != shortEdgeVerts.end()) - { - Entity* vertex = *i++; - if (independentSetStarted && !isIndependent(a, vertex)) - continue; - - apf::Up edges; - a->mesh->getUp(vertex, edges); - Entity* shortEdge = getAdjacentShortestEdge(a, edges); - if (shortEdge == 0) { - i = shortEdgeVerts.erase(--i); - continue; - } - - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (a->sizeField->shouldCollapse(shortEdge) && - tryCollapseEdge(a, shortEdge, keepVertex, collapse)) //TODO: add short edge check - { - markDependent(a, edges); - collapse.destroyOldElements(); - independentSetStarted = true; - success++; - } - i = shortEdgeVerts.erase(--i); + Entity* vertex = getNextIndependentVert(a, shortEdgeVerts, i, independentSetStarted); + if (vertex == 0) continue; + // printf("%d of %d\n", std::distance(shortEdgeVerts.begin(), i), shortEdgeVerts.size()); + apf::Up edges; + a->mesh->getUp(vertex, edges); + Entity* shortEdge = getAdjacentShortestEdge(a, edges); + if (!a->sizeField->shouldCollapse(shortEdge)) { + if (getFlag(a, vertex, CHECKED)) checked--; + i = shortEdgeVerts.erase(i); + continue; + } + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); + if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { //TODO: add short edge check + flagAdjacent(a, edges, checked); + i = shortEdgeVerts.erase(i); + if (getFlag(a, vertex, CHECKED)) checked--; + independentSetStarted = true; + success++; + collapse.destroyOldElements(); + } + else { + setFlag(a, vertex, CHECKED); + checked++; } } - ma::clearFlagFromDimension(a, CHECKED, 0); - ma::clearFlagFromDimension(a, CHECKED, 1); + // printIndependentSet(a); + // ma::clearFlagFromDimension(a, CHECKED, 0); + // ma::clearFlagFromDimension(a, COARSEN, 1); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; From 0443dcc136c16526ebd321c7ebf2c20eaeed0400 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 15:12:14 -0400 Subject: [PATCH 076/181] clear flags once done --- ma/maCoarsen.cc | 21 +++++++++++++++------ test/aniso_adapt.h | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index a8537c471..b16c2e89d 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -304,7 +304,7 @@ void flagAdjacent(Adapt* a, apf::Up& edges, int& checked) a->mesh->getDownward(edges.e[i],0, vertices); for (int i = 0; i < 2; i++) { setFlag(a, vertices[i], NEED_NOT_COLLAPSE); - if (getFlag(a, vertices[i], COARSEN) && getFlag(a, vertices[i], CHECKED)){ + if (getFlag(a, vertices[i], CHECKED)){ clearFlag(a, vertices[i], CHECKED); checked--; } @@ -365,16 +365,25 @@ std::list getShortEdgeVerts(Adapt* a) } } // ma_dbg::dumpMeshWithFlag(a, 0, 1, COARSEN, "shortEdges", "shortEdges"); + clearListFlag(a, shortEdgeVerts, COARSEN); return shortEdgeVerts; } +void assertChecked(Adapt* a, std::list& shortEdgeVerts, const int currChecked) +{ + int realChecked = 0; + std::list::iterator i = shortEdgeVerts.begin(); + while (i != shortEdgeVerts.end()) + if (getFlag(a, *i++, CHECKED)) realChecked++; + PCU_ALWAYS_ASSERT(realChecked == currChecked); +} + bool coarsen(Adapt* a) { if (!a->input->shouldCoarsen) return false; double t0 = pcu::Time(); std::list shortEdgeVerts = getShortEdgeVerts(a); - Collapse collapse; collapse.Init(a); int success = 0; @@ -383,9 +392,9 @@ bool coarsen(Adapt* a) std::list::iterator i = shortEdgeVerts.begin(); while (checked < shortEdgeVerts.size()) { + // assertChecked(a, shortEdgeVerts, checked); Entity* vertex = getNextIndependentVert(a, shortEdgeVerts, i, independentSetStarted); if (vertex == 0) continue; - // printf("%d of %d\n", std::distance(shortEdgeVerts.begin(), i), shortEdgeVerts.size()); apf::Up edges; a->mesh->getUp(vertex, edges); Entity* shortEdge = getAdjacentShortestEdge(a, edges); @@ -408,9 +417,9 @@ bool coarsen(Adapt* a) checked++; } } - // printIndependentSet(a); - // ma::clearFlagFromDimension(a, CHECKED, 0); - // ma::clearFlagFromDimension(a, COARSEN, 1); + clearListFlag(a, shortEdgeVerts, CHECKED); + ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE, 0); + ma::clearFlagFromDimension(a, COARSEN, 1); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 9645376e0..37862d272 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -45,7 +45,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < 1; ++i) + for (int i = 0; i < 2; ++i) { ma::coarsen(a); // ma::refine(a); From 7c2abc64b03ee72a877e8bc0fe1606759822377a Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 16:04:26 -0400 Subject: [PATCH 077/181] max length check --- ma/maCoarsen.cc | 11 +++++++---- ma/maCollapse.cc | 19 +++++++++++++++++++ ma/maCollapse.h | 1 + test/aniso_adapt.h | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index b16c2e89d..d058cac53 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -274,8 +274,12 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo() && - collapse.tryBothDirections(a->input->validQuality)) { - result = true; + collapse.tryBothDirections(a->input->goodQuality)) { + if (collapse.edgeGrewPastMaxLength()) { + result = false; + collapse.cancel(); + } + else result = true; } if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); return result; @@ -404,10 +408,9 @@ bool coarsen(Adapt* a) continue; } Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { //TODO: add short edge check + if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { flagAdjacent(a, edges, checked); i = shortEdgeVerts.erase(i); - if (getFlag(a, vertex, CHECKED)) checked--; independentSetStarted = true; success++; collapse.destroyOldElements(); diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 05ee1b873..68303dc87 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -80,6 +80,25 @@ bool Collapse::edgesGoodSize() { return true; } +bool Collapse::edgeGrewPastMaxLength() { + PCU_ALWAYS_ASSERT(elementsToKeep.size()); + PCU_ALWAYS_ASSERT(elementsToKeep.size() == newElements.size()); + size_t i=0; + APF_ITERATE(EntitySet,elementsToKeep,it) { + Entity* edgesBefore[6]; + adapt->mesh->getDownward(*it,1,edgesBefore); + Entity* edgesAfter[6]; + adapt->mesh->getDownward(newElements[i++],1,edgesAfter); + for (int j=0; j<6; j++) { + double sizeBefore = adapt->sizeField->measure(edgesBefore[j]); + double sizeAfter = adapt->sizeField->measure(edgesAfter[j]); + if (sizeAfter > sizeBefore && sizeAfter > MAXLENGTH) + return true; + } + } + return false; +} + bool Collapse::tryThisDirection(double qualityToBeat) { if (!tryThisDirectionNoCancel(qualityToBeat)) { diff --git a/ma/maCollapse.h b/ma/maCollapse.h index d9a449adf..096bdea8d 100644 --- a/ma/maCollapse.h +++ b/ma/maCollapse.h @@ -42,6 +42,7 @@ class Collapse bool tryBothDirections(double qualityToBeat); void getOldElements(EntityArray& oldElements); bool edgesGoodSize(); + bool edgeGrewPastMaxLength(); double getOldQuality(); Adapt* adapt; Entity* edge; diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 37862d272..e8e94ae47 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -48,7 +48,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) for (int i = 0; i < 2; ++i) { ma::coarsen(a); - // ma::refine(a); + ma::refine(a); // ma::snap(a); } m->verify(); From 89f6c034b5edf5ef018a85c9486c909adb2ab47f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 16:10:31 -0400 Subject: [PATCH 078/181] rename adjacent edges --- ma/maCoarsen.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index d058cac53..ba4797b86 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -286,7 +286,7 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll } -Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) +Entity* getShortestEdge(Adapt* a, apf::Up& edges) { double minLength = 999999; Entity* minEdge = edges.e[0]; @@ -301,7 +301,7 @@ Entity* getAdjacentShortestEdge(Adapt* a, apf::Up& edges) return minEdge; } -void flagAdjacent(Adapt* a, apf::Up& edges, int& checked) +void flagIndependent(Adapt* a, apf::Up& edges, int& checked) { for (int i=0; i < edges.n; i++) { Entity* vertices[2]; @@ -399,9 +399,9 @@ bool coarsen(Adapt* a) // assertChecked(a, shortEdgeVerts, checked); Entity* vertex = getNextIndependentVert(a, shortEdgeVerts, i, independentSetStarted); if (vertex == 0) continue; - apf::Up edges; - a->mesh->getUp(vertex, edges); - Entity* shortEdge = getAdjacentShortestEdge(a, edges); + apf::Up adjacent; + a->mesh->getUp(vertex, adjacent); + Entity* shortEdge = getShortestEdge(a, adjacent); if (!a->sizeField->shouldCollapse(shortEdge)) { if (getFlag(a, vertex, CHECKED)) checked--; i = shortEdgeVerts.erase(i); @@ -409,7 +409,7 @@ bool coarsen(Adapt* a) } Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { - flagAdjacent(a, edges, checked); + flagIndependent(a, adjacent, checked); i = shortEdgeVerts.erase(i); independentSetStarted = true; success++; From 0c5d2a1ede71c07468316527e4779a5cb7cfeb30 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 16:15:20 -0400 Subject: [PATCH 079/181] simplify code --- ma/maCoarsen.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index ba4797b86..dc0dc3404 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -335,7 +335,7 @@ bool isIndependent(Adapt* a, Entity* vertex) return false; } -Entity* getNextIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted) +Entity* getClosestIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted) { while (i != shortEdgeVerts.end()) { @@ -397,18 +397,16 @@ bool coarsen(Adapt* a) while (checked < shortEdgeVerts.size()) { // assertChecked(a, shortEdgeVerts, checked); - Entity* vertex = getNextIndependentVert(a, shortEdgeVerts, i, independentSetStarted); + Entity* vertex = getClosestIndependentVert(a, shortEdgeVerts, i, independentSetStarted); if (vertex == 0) continue; apf::Up adjacent; a->mesh->getUp(vertex, adjacent); Entity* shortEdge = getShortestEdge(a, adjacent); + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); if (!a->sizeField->shouldCollapse(shortEdge)) { - if (getFlag(a, vertex, CHECKED)) checked--; i = shortEdgeVerts.erase(i); - continue; } - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { + else if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { flagIndependent(a, adjacent, checked); i = shortEdgeVerts.erase(i); independentSetStarted = true; From e6904550403de2a47e0abd3a1f94b0ec5abc6f41 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 16:19:57 -0400 Subject: [PATCH 080/181] rename flag independent set --- ma/maCoarsen.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index dc0dc3404..860ae1f16 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -301,7 +301,7 @@ Entity* getShortestEdge(Adapt* a, apf::Up& edges) return minEdge; } -void flagIndependent(Adapt* a, apf::Up& edges, int& checked) +void flagIndependentSet(Adapt* a, apf::Up& edges, int& checked) { for (int i=0; i < edges.n; i++) { Entity* vertices[2]; @@ -407,7 +407,7 @@ bool coarsen(Adapt* a) i = shortEdgeVerts.erase(i); } else if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { - flagIndependent(a, adjacent, checked); + flagIndependentSet(a, adjacent, checked); i = shortEdgeVerts.erase(i); independentSetStarted = true; success++; From 42d2ed19fce02d765161d5c6ed6737bb660916cb Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 17:11:43 -0400 Subject: [PATCH 081/181] independent set goes through full list --- ma/maCoarsen.cc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 860ae1f16..1109d89cb 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -228,7 +228,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool oldCoarsen(Adapt* a) +bool oldcoarsen(Adapt* a) { if (!a->input->shouldCoarsen) return false; @@ -335,19 +335,22 @@ bool isIndependent(Adapt* a, Entity* vertex) return false; } -Entity* getClosestIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted) +Entity* getClosestIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked) { - while (i != shortEdgeVerts.end()) + while (checked < shortEdgeVerts.size()) { - Entity* vertex = *i; - if (getFlag(a, vertex, CHECKED)) {i++; continue;} - if (!independentSetStarted || isIndependent(a, vertex)) - return vertex; - i++; + i = shortEdgeVerts.begin(); + while (i != shortEdgeVerts.end()) + { + Entity* vertex = *i; + if (getFlag(a, vertex, CHECKED)) {i++; continue;} + if (!independentSetStarted || isIndependent(a, vertex)) + return vertex; + i++; + } + clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); + independentSetStarted = false; } - clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); - independentSetStarted = false; - i = shortEdgeVerts.begin(); return 0; } @@ -397,7 +400,7 @@ bool coarsen(Adapt* a) while (checked < shortEdgeVerts.size()) { // assertChecked(a, shortEdgeVerts, checked); - Entity* vertex = getClosestIndependentVert(a, shortEdgeVerts, i, independentSetStarted); + Entity* vertex = getClosestIndependentVert(a, shortEdgeVerts, i, independentSetStarted, checked); if (vertex == 0) continue; apf::Up adjacent; a->mesh->getUp(vertex, adjacent); From 965629af485af5f0890a94579d0a01575a12a2d5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 5 Jun 2025 21:29:48 -0400 Subject: [PATCH 082/181] new min length --- ma/maSize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/maSize.h b/ma/maSize.h index da3c8b9a2..f1358cb51 100644 --- a/ma/maSize.h +++ b/ma/maSize.h @@ -20,7 +20,7 @@ namespace ma { typedef apf::Matrix3x3 Matrix; const double MAXLENGTH = 1.5; -const double MINLENGTH = 0.5; +const double MINLENGTH = .75; class SizeField { From 846f72765aa1becef7554f0e85dd0467b7408189 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 16:57:57 -0400 Subject: [PATCH 083/181] rename get touching independent set --- ma/maCoarsen.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 1109d89cb..cd4fa4732 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -335,7 +335,7 @@ bool isIndependent(Adapt* a, Entity* vertex) return false; } -Entity* getClosestIndependentVert(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked) +Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked) { while (checked < shortEdgeVerts.size()) { @@ -400,7 +400,7 @@ bool coarsen(Adapt* a) while (checked < shortEdgeVerts.size()) { // assertChecked(a, shortEdgeVerts, checked); - Entity* vertex = getClosestIndependentVert(a, shortEdgeVerts, i, independentSetStarted, checked); + Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked); if (vertex == 0) continue; apf::Up adjacent; a->mesh->getUp(vertex, adjacent); From bdef2387385eb64027297185a21c324dcd491262 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 17:35:12 -0400 Subject: [PATCH 084/181] combined touching independent set --- ma/maCoarsen.cc | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index cd4fa4732..d481c781e 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -323,19 +323,7 @@ void clearListFlag(Adapt* a, std::list list, int flag) clearFlag(a, *i++, flag); } -bool isIndependent(Adapt* a, Entity* vertex) -{ - if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) return false; - apf::Up edges; - a->mesh->getUp(vertex, edges); - for (int i=0; i < edges.n; i++) { - Entity* opposite = getEdgeVertOppositeVert(a->mesh, edges.e[i], vertex); - if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return true; - } - return false; -} - -Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked) +Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked, apf::Up& adjacent) { while (checked < shortEdgeVerts.size()) { @@ -343,9 +331,15 @@ Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, while (i != shortEdgeVerts.end()) { Entity* vertex = *i; - if (getFlag(a, vertex, CHECKED)) {i++; continue;} - if (!independentSetStarted || isIndependent(a, vertex)) - return vertex; + if (getFlag(a, vertex, CHECKED)) {i++; continue;} //Already tried to collapse + a->mesh->getUp(vertex, adjacent); + if (!independentSetStarted) return vertex; + if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) {i++; continue;} //Too close to last collapse + for (int i=0; i < adjacent.n; i++) + { + Entity* opposite = getEdgeVertOppositeVert(a->mesh, adjacent.e[i], vertex); + if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return vertex; //Touching independent set + } i++; } clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); @@ -400,10 +394,9 @@ bool coarsen(Adapt* a) while (checked < shortEdgeVerts.size()) { // assertChecked(a, shortEdgeVerts, checked); - Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked); - if (vertex == 0) continue; apf::Up adjacent; - a->mesh->getUp(vertex, adjacent); + Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); + if (vertex == 0) continue; Entity* shortEdge = getShortestEdge(a, adjacent); Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); if (!a->sizeField->shouldCollapse(shortEdge)) { From 9f0be1e9a7183c60d79aa64fd7cb57d9e5d305a5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 17:57:54 -0400 Subject: [PATCH 085/181] fixed get length --- ma/maAdapt.h | 3 +-- ma/maCoarsen.cc | 17 +++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ma/maAdapt.h b/ma/maAdapt.h index 15d6a48d2..0b7a0324d 100644 --- a/ma/maAdapt.h +++ b/ma/maAdapt.h @@ -33,8 +33,7 @@ enum { LAYER_UNSNAP = (1<<15), DONT_MOVE = (1<<16), NEED_NOT_SPLIT = (1<<17), - NEED_NOT_COLLAPSE = (1<<18), - COARSEN = (1<<19), + NEED_NOT_COLLAPSE = (1<<18) }; class DeleteCallback; diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index d481c781e..2c0a7179d 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -291,8 +291,11 @@ Entity* getShortestEdge(Adapt* a, apf::Up& edges) double minLength = 999999; Entity* minEdge = edges.e[0]; for (int i=0; i < edges.n; i++) { - if (!getFlag(a, edges.e[i], COARSEN)) continue; - double length = a->sizeField->measure(edges.e[i]); + Entity* vertices[2]; + a->mesh->getDownward(edges.e[i], 0, vertices); + Vector x = getPosition(a->mesh, vertices[0]); + Vector y = getPosition(a->mesh, vertices[1]); + double length = (x-y).getLength(); if (length < minLength) { minLength = length; minEdge = edges.e[i]; @@ -356,17 +359,16 @@ std::list getShortEdgeVerts(Adapt* a) while ((edge = a->mesh->iterate(it))) { if (!a->sizeField->shouldCollapse(edge)) continue; //TODO: speedup - setFlag(a, edge, COARSEN); Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { - if (getFlag(a, vertices[i], COARSEN)) continue; - setFlag(a, vertices[i], COARSEN); + if (getFlag(a, vertices[i], CHECKED)) continue; + setFlag(a, vertices[i], CHECKED); shortEdgeVerts.push_back(vertices[i]); } } - // ma_dbg::dumpMeshWithFlag(a, 0, 1, COARSEN, "shortEdges", "shortEdges"); - clearListFlag(a, shortEdgeVerts, COARSEN); + // ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "shortEdges", "shortEdges"); + clearListFlag(a, shortEdgeVerts, CHECKED); return shortEdgeVerts; } @@ -416,7 +418,6 @@ bool coarsen(Adapt* a) } clearListFlag(a, shortEdgeVerts, CHECKED); ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE, 0); - ma::clearFlagFromDimension(a, COARSEN, 1); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; From dc62761a343f29d65d0386f6a6db81bb911d93b5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 20:46:45 -0400 Subject: [PATCH 086/181] fixed typo --- ma/maCoarsen.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 2c0a7179d..bcdcbad06 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -309,10 +309,10 @@ void flagIndependentSet(Adapt* a, apf::Up& edges, int& checked) for (int i=0; i < edges.n; i++) { Entity* vertices[2]; a->mesh->getDownward(edges.e[i],0, vertices); - for (int i = 0; i < 2; i++) { - setFlag(a, vertices[i], NEED_NOT_COLLAPSE); - if (getFlag(a, vertices[i], CHECKED)){ - clearFlag(a, vertices[i], CHECKED); + for (int k = 0; k < 2; k++) { + setFlag(a, vertices[k], NEED_NOT_COLLAPSE); + if (getFlag(a, vertices[k], CHECKED)){ + clearFlag(a, vertices[k], CHECKED); checked--; } } From e21ead2f12d64d386cfa3c7d1e39d879384e1dd6 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 20:59:58 -0400 Subject: [PATCH 087/181] simplify touching independent set --- ma/maCoarsen.cc | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index bcdcbad06..b9bb0df24 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -328,26 +328,23 @@ void clearListFlag(Adapt* a, std::list list, int flag) Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked, apf::Up& adjacent) { - while (checked < shortEdgeVerts.size()) + i = shortEdgeVerts.begin(); + while (i != shortEdgeVerts.end()) { - i = shortEdgeVerts.begin(); - while (i != shortEdgeVerts.end()) + Entity* vertex = *i; + if (getFlag(a, vertex, CHECKED)) {i++; continue;} //Already tried to collapse + a->mesh->getUp(vertex, adjacent); + if (!independentSetStarted) return vertex; + if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) {i++; continue;} //Too close to last collapse + for (int i=0; i < adjacent.n; i++) { - Entity* vertex = *i; - if (getFlag(a, vertex, CHECKED)) {i++; continue;} //Already tried to collapse - a->mesh->getUp(vertex, adjacent); - if (!independentSetStarted) return vertex; - if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) {i++; continue;} //Too close to last collapse - for (int i=0; i < adjacent.n; i++) - { - Entity* opposite = getEdgeVertOppositeVert(a->mesh, adjacent.e[i], vertex); - if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return vertex; //Touching independent set - } - i++; + Entity* opposite = getEdgeVertOppositeVert(a->mesh, adjacent.e[i], vertex); + if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return vertex; //Touching independent set } - clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); - independentSetStarted = false; + i++; } + clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); + independentSetStarted = false; return 0; } From 02158f99aad2cf826a6590a12c5a7f7f0847163e Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 21:03:11 -0400 Subject: [PATCH 088/181] rename variable and comment --- ma/maCoarsen.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index b9bb0df24..a33f65210 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -304,15 +304,16 @@ Entity* getShortestEdge(Adapt* a, apf::Up& edges) return minEdge; } -void flagIndependentSet(Adapt* a, apf::Up& edges, int& checked) +//Prevent adjacent vertices from collapsing to create indepedent set +void flagIndependentSet(Adapt* a, apf::Up& adjacent, int& checked) { - for (int i=0; i < edges.n; i++) { + for (int a=0; a < adjacent.n; a++) { Entity* vertices[2]; - a->mesh->getDownward(edges.e[i],0, vertices); - for (int k = 0; k < 2; k++) { - setFlag(a, vertices[k], NEED_NOT_COLLAPSE); - if (getFlag(a, vertices[k], CHECKED)){ - clearFlag(a, vertices[k], CHECKED); + a->mesh->getDownward(adjacent.e[a],0, vertices); + for (int v = 0; v < 2; v++) { + setFlag(a, vertices[v], NEED_NOT_COLLAPSE); + if (getFlag(a, vertices[v], CHECKED)){ + clearFlag(a, vertices[v], CHECKED); //needs to be checked again in next independent set checked--; } } From 35a0b0e60f041986bb4806b06e1696cedd279844 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 21:08:46 -0400 Subject: [PATCH 089/181] calculate edge length --- ma/maCoarsen.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index a33f65210..49cedcdc3 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -285,17 +285,21 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll return result; } +double calcLength(Adapt* a, Entity* edge) +{ + Entity* vertices[2]; + a->mesh->getDownward(edge, 0, vertices); + Vector x = getPosition(a->mesh, vertices[0]); + Vector y = getPosition(a->mesh, vertices[1]); + return (x - y).getLength(); +} Entity* getShortestEdge(Adapt* a, apf::Up& edges) { - double minLength = 999999; Entity* minEdge = edges.e[0]; + double minLength = calcLength(a, minEdge); for (int i=0; i < edges.n; i++) { - Entity* vertices[2]; - a->mesh->getDownward(edges.e[i], 0, vertices); - Vector x = getPosition(a->mesh, vertices[0]); - Vector y = getPosition(a->mesh, vertices[1]); - double length = (x-y).getLength(); + double length = calcLength(a, edges.e[i]); if (length < minLength) { minLength = length; minEdge = edges.e[i]; @@ -307,9 +311,9 @@ Entity* getShortestEdge(Adapt* a, apf::Up& edges) //Prevent adjacent vertices from collapsing to create indepedent set void flagIndependentSet(Adapt* a, apf::Up& adjacent, int& checked) { - for (int a=0; a < adjacent.n; a++) { + for (int adj=0; adj < adjacent.n; adj++) { Entity* vertices[2]; - a->mesh->getDownward(adjacent.e[a],0, vertices); + a->mesh->getDownward(adjacent.e[adj],0, vertices); for (int v = 0; v < 2; v++) { setFlag(a, vertices[v], NEED_NOT_COLLAPSE); if (getFlag(a, vertices[v], CHECKED)){ From 001decc09f8d1d10de9044e49a040846419823f5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 22:33:55 -0400 Subject: [PATCH 090/181] check shortest collapsable edge --- ma/maCoarsen.cc | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 49cedcdc3..9cdfb3fae 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -294,16 +294,19 @@ double calcLength(Adapt* a, Entity* edge) return (x - y).getLength(); } -Entity* getShortestEdge(Adapt* a, apf::Up& edges) +Entity* getShortestCollapsable(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* vertex) { - Entity* minEdge = edges.e[0]; - double minLength = calcLength(a, minEdge); - for (int i=0; i < edges.n; i++) { - double length = calcLength(a, edges.e[i]); - if (length < minLength) { - minLength = length; - minEdge = edges.e[i]; - } + Entity* minEdge = 0; + double minLength = 99999; + for (int i=0; i < adjacent.n; i++) { + Entity* edge = adjacent.e[i]; + double length = calcLength(a, edge); + if (length >= minLength) continue; + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); + if (!tryCollapseEdge(a, edge, keepVertex, collapse)) continue; + minLength = length; + minEdge = adjacent.e[i]; + collapse.cancel();//TODO: reuse collapse } return minEdge; } @@ -401,12 +404,14 @@ bool coarsen(Adapt* a) apf::Up adjacent; Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); if (vertex == 0) continue; - Entity* shortEdge = getShortestEdge(a, adjacent); - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (!a->sizeField->shouldCollapse(shortEdge)) { - i = shortEdgeVerts.erase(i); + Entity* shortEdge = getShortestCollapsable(a, collapse, adjacent, vertex); + if (shortEdge == 0) { + setFlag(a, vertex, CHECKED); + checked++; + continue; } - else if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); + if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { flagIndependentSet(a, adjacent, checked); i = shortEdgeVerts.erase(i); independentSetStarted = true; From f65350a41114fcce1414c448aa8f2507fe051577 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 6 Jun 2025 23:59:30 -0400 Subject: [PATCH 091/181] smaller factor --- test/aniso_ma_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/aniso_ma_test.cc b/test/aniso_ma_test.cc index 77f820712..fab5aca87 100644 --- a/test/aniso_ma_test.cc +++ b/test/aniso_ma_test.cc @@ -19,7 +19,7 @@ int main(int argc, char** argv) lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - refineSnapTest(m, 0.4, 1); + refineSnapTest(m, 0.5, 1); m->destroyNative(); apf::destroyMesh(m); } From 2a5f0f96e94367e51e306d23048618efd984a728 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 11 Jun 2025 14:47:31 -0400 Subject: [PATCH 092/181] collapse only shortest edges --- ma/maCoarsen.cc | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 9cdfb3fae..aed6eafe5 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -15,6 +15,7 @@ #include "maDBG.h" #include #include "apfShape.h" +#include #include namespace ma { @@ -294,21 +295,37 @@ double calcLength(Adapt* a, Entity* edge) return (x - y).getLength(); } +struct EdgeLength +{ + Entity* edge; + double length; + + bool operator<(const EdgeLength& other) const { + return length < other.length; // Descending order + } +}; + +bool compareLength(const EdgeLength& a, const EdgeLength& b) +{ + return a.length > b.length; +} + Entity* getShortestCollapsable(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* vertex) { - Entity* minEdge = 0; - double minLength = 99999; + std::vector sorted; for (int i=0; i < adjacent.n; i++) { - Entity* edge = adjacent.e[i]; - double length = calcLength(a, edge); - if (length >= minLength) continue; + EdgeLength measured{adjacent.e[i], a->sizeField->measure(adjacent.e[i])}; + auto pos = std::lower_bound(sorted.begin(), sorted.end(), measured); + sorted.insert(pos, measured); + } + for (int i=0; i < sorted.size(); i++) { + Entity* edge = sorted[i].edge; Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); if (!tryCollapseEdge(a, edge, keepVertex, collapse)) continue; - minLength = length; - minEdge = adjacent.e[i]; - collapse.cancel();//TODO: reuse collapse + collapse.cancel(); + return edge; } - return minEdge; + return 0; } //Prevent adjacent vertices from collapsing to create indepedent set From ea5fcb8c142a1bc2263d6e81efbe1f3765890873 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 11 Jun 2025 15:00:51 -0400 Subject: [PATCH 093/181] only collapse once --- ma/maCoarsen.cc | 53 ++++++------------------------------------------- 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index aed6eafe5..eb5c00957 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -257,13 +257,6 @@ bool oldcoarsen(Adapt* a) return true; } -void printIndependentSet(Adapt* a) -{ - apf::writeVtkFiles("independentMesh", a->mesh); - ma_dbg::dumpMeshWithFlag(a, 0, 0, CHECKED, "independentVerts", "independentVerts"); - exit(0); -} - static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); @@ -286,31 +279,16 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll return result; } -double calcLength(Adapt* a, Entity* edge) -{ - Entity* vertices[2]; - a->mesh->getDownward(edge, 0, vertices); - Vector x = getPosition(a->mesh, vertices[0]); - Vector y = getPosition(a->mesh, vertices[1]); - return (x - y).getLength(); -} - struct EdgeLength { Entity* edge; double length; - bool operator<(const EdgeLength& other) const { - return length < other.length; // Descending order + return length < other.length; } }; -bool compareLength(const EdgeLength& a, const EdgeLength& b) -{ - return a.length > b.length; -} - -Entity* getShortestCollapsable(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* vertex) +bool collapseShortest(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* vertex) { std::vector sorted; for (int i=0; i < adjacent.n; i++) { @@ -321,11 +299,9 @@ Entity* getShortestCollapsable(Adapt* a, Collapse& collapse, apf::Up& adjacent, for (int i=0; i < sorted.size(); i++) { Entity* edge = sorted[i].edge; Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); - if (!tryCollapseEdge(a, edge, keepVertex, collapse)) continue; - collapse.cancel(); - return edge; + if (tryCollapseEdge(a, edge, keepVertex, collapse)) return true; } - return 0; + return false; } //Prevent adjacent vertices from collapsing to create indepedent set @@ -394,15 +370,6 @@ std::list getShortEdgeVerts(Adapt* a) return shortEdgeVerts; } -void assertChecked(Adapt* a, std::list& shortEdgeVerts, const int currChecked) -{ - int realChecked = 0; - std::list::iterator i = shortEdgeVerts.begin(); - while (i != shortEdgeVerts.end()) - if (getFlag(a, *i++, CHECKED)) realChecked++; - PCU_ALWAYS_ASSERT(realChecked == currChecked); -} - bool coarsen(Adapt* a) { if (!a->input->shouldCoarsen) @@ -417,23 +384,15 @@ bool coarsen(Adapt* a) std::list::iterator i = shortEdgeVerts.begin(); while (checked < shortEdgeVerts.size()) { - // assertChecked(a, shortEdgeVerts, checked); apf::Up adjacent; Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); if (vertex == 0) continue; - Entity* shortEdge = getShortestCollapsable(a, collapse, adjacent, vertex); - if (shortEdge == 0) { - setFlag(a, vertex, CHECKED); - checked++; - continue; - } - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, shortEdge, vertex); - if (tryCollapseEdge(a, shortEdge, keepVertex, collapse)) { + if (collapseShortest(a, collapse, adjacent, vertex)) { flagIndependentSet(a, adjacent, checked); i = shortEdgeVerts.erase(i); independentSetStarted = true; - success++; collapse.destroyOldElements(); + success++; } else { setFlag(a, vertex, CHECKED); From b7ac7a422443b3bc6c27b1671ea00aadc63a698c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 11 Jun 2025 15:51:46 -0400 Subject: [PATCH 094/181] don't try to collapse long edges --- ma/maCoarsen.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index eb5c00957..1a1419db8 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -298,6 +298,7 @@ bool collapseShortest(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* v } for (int i=0; i < sorted.size(); i++) { Entity* edge = sorted[i].edge; + if (!a->sizeField->shouldCollapse(edge)) return false; Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); if (tryCollapseEdge(a, edge, keepVertex, collapse)) return true; } From 931ab03ce1a8af6ae75f208cda72f59491c6ca4d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 11 Jun 2025 17:33:33 -0400 Subject: [PATCH 095/181] iterate from current position --- ma/maCoarsen.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 1a1419db8..a152e6411 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -328,11 +328,12 @@ void clearListFlag(Adapt* a, std::list list, int flag) clearFlag(a, *i++, flag); } -Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked, apf::Up& adjacent) +//Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an independent set +Entity* getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked, apf::Up& adjacent) { - i = shortEdgeVerts.begin(); - while (i != shortEdgeVerts.end()) - { + auto start = i; + do { + if (i == shortEdgeVerts.end()) i = shortEdgeVerts.begin(); Entity* vertex = *i; if (getFlag(a, vertex, CHECKED)) {i++; continue;} //Already tried to collapse a->mesh->getUp(vertex, adjacent); @@ -344,7 +345,7 @@ Entity* getTouchingIndependentSet(Adapt* a, std::list& shortEdgeVerts, if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return vertex; //Touching independent set } i++; - } + } while (i != start); clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); independentSetStarted = false; return 0; @@ -357,7 +358,7 @@ std::list getShortEdgeVerts(Adapt* a) Entity* edge; while ((edge = a->mesh->iterate(it))) { - if (!a->sizeField->shouldCollapse(edge)) continue; //TODO: speedup + if (!a->sizeField->shouldCollapse(edge)) continue; Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { @@ -366,7 +367,6 @@ std::list getShortEdgeVerts(Adapt* a) shortEdgeVerts.push_back(vertices[i]); } } - // ma_dbg::dumpMeshWithFlag(a, 0, 1, CHECKED, "shortEdges", "shortEdges"); clearListFlag(a, shortEdgeVerts, CHECKED); return shortEdgeVerts; } @@ -386,7 +386,7 @@ bool coarsen(Adapt* a) while (checked < shortEdgeVerts.size()) { apf::Up adjacent; - Entity* vertex = getTouchingIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); + Entity* vertex = getAdjIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); if (vertex == 0) continue; if (collapseShortest(a, collapse, adjacent, vertex)) { flagIndependentSet(a, adjacent, checked); From 98b6f45d4ffd3134d548805cf2ef04f0c1b8b225 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 12 Jun 2025 16:05:22 -0400 Subject: [PATCH 096/181] small base area case --- ma/maSnapper.cc | 24 +++++++++++++++++------- test/aniso_adapt.h | 6 ++++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index b012b50fc..28b7ce35d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -339,10 +339,6 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { - if (FPP->commEdges.n < 2) { - print(mesh->getPCU(), "Swap failed: consider more collapses before swap"); - return false; - } Entity* ents[4]; double area[4]; int bit = getTetStats(adapt, FPP, ents, area); @@ -351,9 +347,23 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) for(int i=1; i<4; i++) if( area[i]getPCU(), "Swap failed: small base area case not implemented"); - return false; + if (area[0]==min) { + Entity* edges[3]; + mesh->getDownward(FPP->problemFace, 1, edges); + Entity* longest = edges[0]; + for (int i=1; i<3; i++) + if (adapt->sizeField->measure(edges[i]) > adapt->sizeField->measure(longest)) + longest = edges[i]; + + if (edgeSwap->run(longest)) { + numSwap++; + return true; + } + + if (splitCollapse.run(longest, FPP->vert, 0)) { + numSplitCollapse++; + return true; + } } // two large dihedral angles -> key problem: two mesh edges diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index e8e94ae47..3505e0340 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -11,6 +11,7 @@ #include "maCoarsen.h" #include "maAdapt.h" #include "maRefine.h" +#include "maShape.h" #include "maSnap.h" class AnIso : public ma::AnisotropicFunction @@ -45,12 +46,13 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - for (int i = 0; i < 2; ++i) + for (int i = 0; i < in->maximumIterations; ++i) { ma::coarsen(a); ma::refine(a); - // ma::snap(a); + ma::snap(a); } + // ma::fixElementShapes(a); m->verify(); apf::writeVtkFiles("after_adapt",m); } \ No newline at end of file From 136b423a0ed329af3bd27d68c1c94b1f568316ad Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 12 Jun 2025 22:17:29 -0400 Subject: [PATCH 097/181] enable split collapse --- ma/maSnapper.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 28b7ce35d..91c7775dc 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -398,10 +398,10 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) return true; } - // if (doubleSplitCollapse.run(ents, 0)) { //TODO: TEST DOUBLE SPLIT COLLAPSE - // numSplitCollapse++; - // return true; - // } + if (doubleSplitCollapse.run(ents, 0)) { + numSplitCollapse++; + return true; + } } print(mesh->getPCU(), "Swap failed: face swap and double split collapse not implemented"); From 49cef8a1472fd84426b41168d83336936671f3b6 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 12 Jun 2025 23:20:21 -0400 Subject: [PATCH 098/181] aggressive coarsen --- ma/maCoarsen.cc | 7 ++++++- ma/maCoarsen.h | 2 +- test/aniso_adapt.h | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index a152e6411..41e65c142 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -371,12 +371,16 @@ std::list getShortEdgeVerts(Adapt* a) return shortEdgeVerts; } -bool coarsen(Adapt* a) +bool coarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; double t0 = pcu::Time(); std::list shortEdgeVerts = getShortEdgeVerts(a); + bool oldShouldForce = a->input->shouldForceAdaptation; + if (aggressive) + a->input->shouldForceAdaptation = true; + Collapse collapse; collapse.Init(a); int success = 0; @@ -402,6 +406,7 @@ bool coarsen(Adapt* a) } clearListFlag(a, shortEdgeVerts, CHECKED); ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE, 0); + a->input->shouldForceAdaptation = oldShouldForce; double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; diff --git a/ma/maCoarsen.h b/ma/maCoarsen.h index b0ebc435e..c8bc5b5f4 100644 --- a/ma/maCoarsen.h +++ b/ma/maCoarsen.h @@ -14,7 +14,7 @@ namespace ma { class Adapt; -bool coarsen(Adapt* a); +bool coarsen(Adapt* a, bool aggressive=false); bool coarsenLayer(Adapt* a); bool coarsenAndPrint(Adapt* a); diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 3505e0340..6ba07ed59 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -46,11 +46,13 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) AnIso sf(m, sizeFactor1, sizeFactor2); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); + + ma::coarsen(a, true); for (int i = 0; i < in->maximumIterations; ++i) { - ma::coarsen(a); ma::refine(a); ma::snap(a); + ma::coarsen(a); } // ma::fixElementShapes(a); m->verify(); From 9aa4b878c5d7dd51e26a9526e2cc18821e7caad6 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 13 Jun 2025 21:38:49 -0400 Subject: [PATCH 099/181] fixed base condition --- ma/maCoarsen.cc | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 41e65c142..d3846424d 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -329,26 +329,27 @@ void clearListFlag(Adapt* a, std::list list, int flag) } //Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an independent set -Entity* getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& i, bool& independentSetStarted, const int checked, apf::Up& adjacent) +bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& itr, bool& independentSetStarted, const int checked, apf::Up& adjacent) { - auto start = i; + int numItr=0; do { - if (i == shortEdgeVerts.end()) i = shortEdgeVerts.begin(); - Entity* vertex = *i; - if (getFlag(a, vertex, CHECKED)) {i++; continue;} //Already tried to collapse + numItr++; + if (itr == shortEdgeVerts.end()) itr = shortEdgeVerts.begin(); + Entity* vertex = *itr; + if (getFlag(a, vertex, CHECKED)) {itr++; continue;} //Already tried to collapse a->mesh->getUp(vertex, adjacent); - if (!independentSetStarted) return vertex; - if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) {i++; continue;} //Too close to last collapse + if (!independentSetStarted) return true; + if (getFlag(a, vertex, NEED_NOT_COLLAPSE)) {itr++; continue;} //Too close to last collapse for (int i=0; i < adjacent.n; i++) { Entity* opposite = getEdgeVertOppositeVert(a->mesh, adjacent.e[i], vertex); - if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return vertex; //Touching independent set + if (getFlag(a, opposite, NEED_NOT_COLLAPSE)) return true; //Touching independent set } - i++; - } while (i != start); + itr++; + } while (numItr < shortEdgeVerts.size()); clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); independentSetStarted = false; - return 0; + return false; } std::list getShortEdgeVerts(Adapt* a) @@ -386,21 +387,20 @@ bool coarsen(Adapt* a, bool aggressive) int success = 0; int checked = 0; bool independentSetStarted = false; - std::list::iterator i = shortEdgeVerts.begin(); + std::list::iterator itr = shortEdgeVerts.begin(); while (checked < shortEdgeVerts.size()) { apf::Up adjacent; - Entity* vertex = getAdjIndependentSet(a, shortEdgeVerts, i, independentSetStarted, checked, adjacent); - if (vertex == 0) continue; - if (collapseShortest(a, collapse, adjacent, vertex)) { + if (!getAdjIndependentSet(a, shortEdgeVerts, itr, independentSetStarted, checked, adjacent)) continue; + if (collapseShortest(a, collapse, adjacent, *itr)) { flagIndependentSet(a, adjacent, checked); - i = shortEdgeVerts.erase(i); + itr = shortEdgeVerts.erase(itr); independentSetStarted = true; collapse.destroyOldElements(); success++; } else { - setFlag(a, vertex, CHECKED); + setFlag(a, *itr, CHECKED); checked++; } } From 9a8d56e00fed382b0bd4388671ff06b27721a8fa Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 14 Jun 2025 11:53:11 -0400 Subject: [PATCH 100/181] fix snap bug --- ma/maSnapper.cc | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 91c7775dc..aac18179a 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -354,12 +354,11 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) for (int i=1; i<3; i++) if (adapt->sizeField->measure(edges[i]) > adapt->sizeField->measure(longest)) longest = edges[i]; - + if (edgeSwap->run(longest)) { numSwap++; return true; } - if (splitCollapse.run(longest, FPP->vert, 0)) { numSplitCollapse++; return true; @@ -373,12 +372,15 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) numSwap++; return true; } - for (int i=0; i<2; i++) if (splitCollapse.run(ents[i], FPP->vert, 0)) { //TODO: Select best numSplitCollapse++; return true; } + if (doubleSplitCollapse.run(ents, 0)) { + numSplitCollapse++; + return true; + } } // three large dihedral angles -> key entity: a mesh face else { @@ -390,18 +392,11 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) return true; } } - //TODO: IMPLEMENT FACE SWAP - if (splitCollapse.run(ents[1], FPP->vert, 0)) { numSplitCollapse++; return true; } - - if (doubleSplitCollapse.run(ents, 0)) { - numSplitCollapse++; - return true; - } } print(mesh->getPCU(), "Swap failed: face swap and double split collapse not implemented"); @@ -524,8 +519,8 @@ bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) for (int i=0; i<3; i++) { Entity* pbVert[2]; mesh->getDownward(pbEdges[i], 0, pbVert); - if (pbVert[0] == v1 && pbVert[1] == v2) break; - if (pbVert[1] == v1 && pbVert[0] == v2) break; + if (pbVert[0] == v1 && pbVert[1] == v2) continue; + if (pbVert[1] == v1 && pbVert[0] == v2) continue; for (int j=0; j<2; j++) getBestQualityCollapse(adapt, pbEdges[i], pbVert[j], collapse, best); } From 9f33614648b968c0aa34cde08ecade00919270ac Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 14 Jun 2025 15:52:46 -0400 Subject: [PATCH 101/181] moved snap queue to adapt --- ma/maAdapt.h | 2 ++ ma/maRefine.cc | 2 +- ma/maRefine.h | 1 - ma/maSnap.cc | 21 ++++++++++----------- ma/maSnapper.cc | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ma/maAdapt.h b/ma/maAdapt.h index 0b7a0324d..335ee79e4 100644 --- a/ma/maAdapt.h +++ b/ma/maAdapt.h @@ -11,6 +11,7 @@ #define MA_ADAPT_H #include "maInput.h" +#include namespace ma { @@ -54,6 +55,7 @@ class Adapt apf::BuildCallback* buildCallback; SizeField* sizeField; SolutionTransfer* solutionTransfer; + std::queue vtxToSnap; Refine* refine; ShapeHandler* shape; int coarsensLeft; diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 1fb055fc7..03e7151d6 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -134,7 +134,7 @@ void AddVertexToSnap(Refine* r, Entity* vert) int dim = m->getDimension(); int md = m->getModelType(m->toModel(vert)); if (dim == md) return; - r->vtxToSnap.push(vert); + a->vtxToSnap.push(vert); setFlag(a, vert, SNAP); } diff --git a/ma/maRefine.h b/ma/maRefine.h index acca94c8f..7553b9551 100644 --- a/ma/maRefine.h +++ b/ma/maRefine.h @@ -27,7 +27,6 @@ class Refine Tag* numberTag; EntityArray toSplit[4]; apf::DynamicArray newEntities[4]; - std::queue vtxToSnap; bool shouldCollect[4]; }; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index ccd1262a5..90d821cd5 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -846,15 +846,15 @@ bool snapMatchedVerts(Adapt* a, Tag* t, bool isSimple, long& successCount) long tagVertsToSnap(Adapt* a, Tag*& tag) { Mesh* m = a->mesh; - Refine* refine = a->refine; int dim = m->getDimension(); - int notProcessed = refine->vtxToSnap.size(); + int notProcessed = a->vtxToSnap.size(); int owned = 0; + printf("size %d\n", notProcessed); while (notProcessed > 0) { notProcessed--; - Entity* vertex = refine->vtxToSnap.front(); - refine->vtxToSnap.pop(); + Entity* vertex = a->vtxToSnap.front(); + a->vtxToSnap.pop(); PCU_ALWAYS_ASSERT(getFlag(a, vertex, SNAP)); Vector target; @@ -868,7 +868,7 @@ long tagVertsToSnap(Adapt* a, Tag*& tag) m->setDoubleTag(vertex, tag, &target[0]); if (m->isOwned(vertex)) ++owned; - refine->vtxToSnap.push(vertex); + a->vtxToSnap.push(vertex); } return m->getPCU()->Add(owned); } @@ -913,21 +913,20 @@ long snapTaggedVerts(Adapt* a, Tag* tag) void trySnapping(Adapt* a, Snapper& snapper) { - std::queue* vtxToSnap = &a->refine->vtxToSnap; bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; //Allows quality to decrease from snapping - while (vtxToSnap->size() > 0) + while (a->vtxToSnap.size() > 0) { - Entity* vertex = vtxToSnap->front(); - vtxToSnap->pop(); + Entity* vertex = a->vtxToSnap.front(); + a->vtxToSnap.pop(); snapper.setVert(vertex); if (snapper.run() && getFlag(a, vertex, SNAP)) - vtxToSnap->push(vertex); + a->vtxToSnap.push(vertex); } a->input->shouldForceAdaptation = shouldForce; - a->refine->vtxToSnap = {}; + a->vtxToSnap = {}; } void snap(Adapt* a) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index aac18179a..337e19d79 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -381,6 +381,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) numSplitCollapse++; return true; } + print(mesh->getPCU(), "Swap failed: Consider better swap/spltClps"); } // three large dihedral angles -> key entity: a mesh face else { @@ -397,9 +398,8 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) numSplitCollapse++; return true; } + print(mesh->getPCU(), "Swap failed: face swap not implemented"); } - - print(mesh->getPCU(), "Swap failed: face swap and double split collapse not implemented"); return false; } @@ -627,7 +627,7 @@ bool Snapper::run() FirstProblemPlane* FPP = getFPP(adapt, vert, snapTag, invalid); if (!success) success = tryCollapseToVertex(FPP); - // if (!success) success = tryReduceCommonEdges(FPP); + if (!success) success = tryReduceCommonEdges(FPP); if (!success) success = tryCollapseTetEdges(FPP); if (!success) success = trySwapOrSplit(FPP); From 50df0263fb89b222d751bf80d311dcf35db080f5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 14 Jun 2025 16:25:47 -0400 Subject: [PATCH 102/181] fixed splt-collapse snap bug --- ma/maRefine.cc | 13 +++---------- ma/maSnap.cc | 8 +++----- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 03e7151d6..4e2b72a94 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -129,13 +129,12 @@ Refine::~Refine() void AddVertexToSnap(Refine* r, Entity* vert) { - Adapt* a = r->adapt; - Mesh* m = a->mesh; + Mesh* m = r->adapt->mesh; int dim = m->getDimension(); int md = m->getModelType(m->toModel(vert)); if (dim == md) return; - a->vtxToSnap.push(vert); - setFlag(a, vert, SNAP); + r->adapt->vtxToSnap.push(vert); + setFlag(r->adapt, vert, SNAP); } Entity* makeSplitVert(Refine* r, Entity* edge) @@ -150,12 +149,6 @@ Entity* makeSplitVert(Refine* r, Entity* edge) apf::MeshElement* me = apf::createMeshElement(m,edge); Vector point; apf::mapLocalToGlobal(me,xi,point); - - // Vector failed(-0.279880, -0.093306, 0.132892); - // if (apf::areClose(point, failed, 1e-5)){ - // printf("===FAILED FOUND\n"); - // } - Vector param(0,0,0); //prevents uninitialized values if (a->input->shouldTransferParametric) transferParametricOnEdgeSplit(m,edge,0.5,param); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 90d821cd5..dbfd58590 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -849,19 +849,17 @@ long tagVertsToSnap(Adapt* a, Tag*& tag) int dim = m->getDimension(); int notProcessed = a->vtxToSnap.size(); int owned = 0; - printf("size %d\n", notProcessed); while (notProcessed > 0) { notProcessed--; Entity* vertex = a->vtxToSnap.front(); a->vtxToSnap.pop(); - PCU_ALWAYS_ASSERT(getFlag(a, vertex, SNAP)); - + if (!getFlag(a, vertex, SNAP)) //This means the vertex was deleted + continue; Vector target; getSnapPoint(m, vertex, target); Vector prev = getPosition(m, vertex); - if (apf::areClose(prev, target, 1e-12)) - { + if (apf::areClose(prev, target, 1e-12)) { clearFlag(a, vertex, SNAP); continue; } From 4e8b0f8ecd9895a683246682e79b61dc3349da97 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Mon, 16 Jun 2025 19:06:32 -0400 Subject: [PATCH 103/181] better snap warnings --- ma/maSnapper.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 337e19d79..938823964 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -332,14 +332,14 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double break; } default: - PCU_ALWAYS_ASSERT(false); //TODO: ADD ERROR + print(a->mesh->getPCU(), "Swap warning: This swap/splt may not work consider more collapses"); } return bit; } bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { - Entity* ents[4]; + Entity* ents[4] = {0}; double area[4]; int bit = getTetStats(adapt, FPP, ents, area); @@ -365,15 +365,18 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) } } + if (ents[0] == 0) + return false; + // two large dihedral angles -> key problem: two mesh edges if (bit==3 || bit==5 || bit==6) { for (int i=0; i<2; i++) - if (edgeSwap->run(ents[i])) { //TODO: Select best + if (edgeSwap->run(ents[i])) { numSwap++; return true; } for (int i=0; i<2; i++) - if (splitCollapse.run(ents[i], FPP->vert, 0)) { //TODO: Select best + if (splitCollapse.run(ents[i], FPP->vert, 0)) { numSplitCollapse++; return true; } @@ -381,19 +384,19 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) numSplitCollapse++; return true; } - print(mesh->getPCU(), "Swap failed: Consider better swap/spltClps"); + print(mesh->getPCU(), "Swap failed: Consider more collapses"); } // three large dihedral angles -> key entity: a mesh face else { Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); for (int i=0; i<3; i++) { - if (edgeSwap->run(edges[i])) { //TODO: Select best + if (edgeSwap->run(edges[i])) { numSwap++; return true; } } - //TODO: IMPLEMENT FACE SWAP + //TODO: RUN FACE SWAP HERE if (splitCollapse.run(ents[1], FPP->vert, 0)) { numSplitCollapse++; return true; @@ -414,7 +417,7 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo() && - collapse.tryBothDirections(0)) { + collapse.tryBothDirections(a->input->validQuality)) { collapse.destroyOldElements(); result = true; } @@ -437,7 +440,7 @@ static void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collaps if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo()) { collapse.computeElementSets(); - if (collapse.tryThisDirectionNoCancel(0) && collapse.edgesGoodSize()) { + if (collapse.tryThisDirectionNoCancel(a->input->validQuality) && collapse.edgesGoodSize()) { double quality = getWorstQuality(a, collapse.newElements); if (quality > best.quality) { best.quality = quality; From 995290a3acd8964626374aa4c29b0a76b1879b80 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 18 Jun 2025 13:50:59 -0400 Subject: [PATCH 104/181] using old coarsen --- ma/maCoarsen.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index d3846424d..3a1dc0475 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -229,7 +229,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool oldcoarsen(Adapt* a) +bool coarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; @@ -372,7 +372,7 @@ std::list getShortEdgeVerts(Adapt* a) return shortEdgeVerts; } -bool coarsen(Adapt* a, bool aggressive) +bool newcoarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; From ba9dba12735ed6215b1bd3d9bc3316a3036bba4a Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 19 Jun 2025 12:03:44 -0400 Subject: [PATCH 105/181] fixed coarsen bug --- ma/maCoarsen.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 3a1dc0475..65c4389ac 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -229,7 +229,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool coarsen(Adapt* a, bool aggressive) +bool oldcoarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; @@ -264,11 +264,14 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + double quality = a->input->shouldForceAdaptation ? a->input->validQuality + : a->input->goodQuality; + bool result = false; if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo() && - collapse.tryBothDirections(a->input->goodQuality)) { + collapse.tryBothDirections(quality)) { if (collapse.edgeGrewPastMaxLength()) { result = false; collapse.cancel(); @@ -372,7 +375,7 @@ std::list getShortEdgeVerts(Adapt* a) return shortEdgeVerts; } -bool newcoarsen(Adapt* a, bool aggressive) +bool coarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; From 45672e388f2c27dc4459cddb9e96c5bfd2c55a6c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 19 Jun 2025 15:10:51 -0400 Subject: [PATCH 106/181] combined collapse shortest --- ma/maCoarsen.cc | 55 ++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 65c4389ac..8fd562425 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -282,6 +282,22 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll return result; } +//Prevent adjacent vertices from collapsing to create indepedent set +void flagIndependentSet(Adapt* a, apf::Up& adjacent, int& checked) +{ + for (int adj=0; adj < adjacent.n; adj++) { + Entity* vertices[2]; + a->mesh->getDownward(adjacent.e[adj],0, vertices); + for (int v = 0; v < 2; v++) { + setFlag(a, vertices[v], NEED_NOT_COLLAPSE); + if (getFlag(a, vertices[v], CHECKED)){ + clearFlag(a, vertices[v], CHECKED); //needs to be checked again in next independent set + checked--; + } + } + } +} + struct EdgeLength { Entity* edge; @@ -291,37 +307,28 @@ struct EdgeLength } }; -bool collapseShortest(Adapt* a, Collapse& collapse, apf::Up& adjacent, Entity* vertex) +bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, int& checked, apf::Up& adjacent) { + Entity* vertex = *itr; std::vector sorted; for (int i=0; i < adjacent.n; i++) { EdgeLength measured{adjacent.e[i], a->sizeField->measure(adjacent.e[i])}; auto pos = std::lower_bound(sorted.begin(), sorted.end(), measured); sorted.insert(pos, measured); } + bool collapsed = false; for (int i=0; i < sorted.size(); i++) { Entity* edge = sorted[i].edge; - if (!a->sizeField->shouldCollapse(edge)) return false; + if (!a->sizeField->shouldCollapse(edge)) break; Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); - if (tryCollapseEdge(a, edge, keepVertex, collapse)) return true; + if (tryCollapseEdge(a, edge, keepVertex, collapse)) { collapsed = true; break; } } - return false; -} - -//Prevent adjacent vertices from collapsing to create indepedent set -void flagIndependentSet(Adapt* a, apf::Up& adjacent, int& checked) -{ - for (int adj=0; adj < adjacent.n; adj++) { - Entity* vertices[2]; - a->mesh->getDownward(adjacent.e[adj],0, vertices); - for (int v = 0; v < 2; v++) { - setFlag(a, vertices[v], NEED_NOT_COLLAPSE); - if (getFlag(a, vertices[v], CHECKED)){ - clearFlag(a, vertices[v], CHECKED); //needs to be checked again in next independent set - checked--; - } - } + if (collapsed) { + flagIndependentSet(a, adjacent, checked); + itr = shortEdgeVerts.erase(itr); + collapse.destroyOldElements(); } + return collapsed; } void clearListFlag(Adapt* a, std::list list, int flag) @@ -395,11 +402,8 @@ bool coarsen(Adapt* a, bool aggressive) { apf::Up adjacent; if (!getAdjIndependentSet(a, shortEdgeVerts, itr, independentSetStarted, checked, adjacent)) continue; - if (collapseShortest(a, collapse, adjacent, *itr)) { - flagIndependentSet(a, adjacent, checked); - itr = shortEdgeVerts.erase(itr); - independentSetStarted = true; - collapse.destroyOldElements(); + if (collapseShortest(a, collapse, shortEdgeVerts, itr, checked, adjacent)) { + independentSetStarted=true; success++; } else { @@ -407,8 +411,7 @@ bool coarsen(Adapt* a, bool aggressive) checked++; } } - clearListFlag(a, shortEdgeVerts, CHECKED); - ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE, 0); + ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE | CHECKED, 0); a->input->shouldForceAdaptation = oldShouldForce; double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); From bf420a97823b204a2956db5deacc45a22465e454 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 19 Jun 2025 19:53:58 -0400 Subject: [PATCH 107/181] small performance fix --- ma/maCoarsen.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 8fd562425..6667e3897 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -313,22 +313,25 @@ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdg std::vector sorted; for (int i=0; i < adjacent.n; i++) { EdgeLength measured{adjacent.e[i], a->sizeField->measure(adjacent.e[i])}; + if (measured.length > MINLENGTH) continue; auto pos = std::lower_bound(sorted.begin(), sorted.end(), measured); sorted.insert(pos, measured); } - bool collapsed = false; - for (int i=0; i < sorted.size(); i++) { - Entity* edge = sorted[i].edge; - if (!a->sizeField->shouldCollapse(edge)) break; - Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, edge, vertex); - if (tryCollapseEdge(a, edge, keepVertex, collapse)) { collapsed = true; break; } + if (sorted.size() == 0) { //performance optimization, will rarely result in a missed edge + itr = shortEdgeVerts.erase(itr); + return false; } - if (collapsed) { + for (int i=0; i < sorted.size(); i++) { + Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, sorted[i].edge, vertex); + if (!tryCollapseEdge(a, sorted[i].edge, keepVertex, collapse)) continue; flagIndependentSet(a, adjacent, checked); itr = shortEdgeVerts.erase(itr); collapse.destroyOldElements(); + return true; } - return collapsed; + setFlag(a, vertex, CHECKED); + checked++; + return false; } void clearListFlag(Adapt* a, std::list list, int flag) @@ -406,10 +409,6 @@ bool coarsen(Adapt* a, bool aggressive) independentSetStarted=true; success++; } - else { - setFlag(a, *itr, CHECKED); - checked++; - } } ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE | CHECKED, 0); a->input->shouldForceAdaptation = oldShouldForce; From 5132e3479bed5597e2b7d05b691fad175e0462c7 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 25 Jun 2025 19:08:41 -0400 Subject: [PATCH 108/181] run multiple coarsen once --- ma/ma.cc | 5 ++- ma/maCoarsen.cc | 4 +- ma/maCoarsen.h | 1 + ma/maSnapper.cc | 12 +++--- test/CMakeLists.txt | 1 - test/aniso_adapt.h | 4 +- test/coarsen.cc | 103 -------------------------------------------- 7 files changed, 14 insertions(+), 116 deletions(-) delete mode 100644 test/coarsen.cc diff --git a/ma/ma.cc b/ma/ma.cc index b1aa8c3f9..c770478f7 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,14 +27,15 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); + coarsenMultiple(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); - coarsen(a); - coarsenLayer(a); midBalance(a); refine(a); snap(a); + coarsen(a); + coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); fixElementShapes(a); diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 6667e3897..54c554ae4 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -229,7 +229,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool oldcoarsen(Adapt* a, bool aggressive) +bool coarsen(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; @@ -385,7 +385,7 @@ std::list getShortEdgeVerts(Adapt* a) return shortEdgeVerts; } -bool coarsen(Adapt* a, bool aggressive) +bool coarsenMultiple(Adapt* a, bool aggressive) { if (!a->input->shouldCoarsen) return false; diff --git a/ma/maCoarsen.h b/ma/maCoarsen.h index c8bc5b5f4..8af51122c 100644 --- a/ma/maCoarsen.h +++ b/ma/maCoarsen.h @@ -14,6 +14,7 @@ namespace ma { class Adapt; +bool coarsenMultiple(Adapt* a, bool aggressive=false); bool coarsen(Adapt* a, bool aggressive=false); bool coarsenLayer(Adapt* a); bool coarsenAndPrint(Adapt* a); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 938823964..9da6cbec4 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -390,12 +390,12 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) else { Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); - for (int i=0; i<3; i++) { - if (edgeSwap->run(edges[i])) { - numSwap++; - return true; - } - } + // for (int i=0; i<3; i++) { + // if (edgeSwap->run(edges[i])) { + // numSwap++; + // return true; + // } + // } //TODO: RUN FACE SWAP HERE if (splitCollapse.run(ents[1], FPP->vert, 0)) { numSplitCollapse++; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 99823a016..d5a12a86a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -178,7 +178,6 @@ test_exe_func(newdim newdim.cc) test_exe_func(construct construct.cc) test_exe_func(constructThenGhost constructThenGhost.cc) test_exe_func(construct_bottom_up construct_bottom_up.cc) -test_exe_func(coarsen coarsen.cc) test_exe_func(embedded_edges embedded_edges.cc) test_exe_func(test_scaling test_scaling.cc) test_exe_func(mixedNumbering mixedNumbering.cc) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 6ba07ed59..fef6dc755 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -47,12 +47,12 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - ma::coarsen(a, true); + ma::coarsenMultiple(a, true); for (int i = 0; i < in->maximumIterations; ++i) { ma::refine(a); ma::snap(a); - ma::coarsen(a); + ma::coarsenMultiple(a); } // ma::fixElementShapes(a); m->verify(); diff --git a/test/coarsen.cc b/test/coarsen.cc deleted file mode 100644 index be359f83a..000000000 --- a/test/coarsen.cc +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "maAdapt.h" -#include "maCoarsen.h" -#include "apfShape.h" - -double vtx_coords[6][3] = { - {1.0, 0.0, 0.0}, - {1.0, 0.5, 0.0}, - {1.0, 1.0, 0.0}, - {0.5, 0.5, 0.0}, - {0.0, 0.0, 0.0}, - {0.0, 1.0, 0.0} -}; - -apf::Gid triangles[5][3] = { - {0, 1, 3}, - {1, 2, 3}, - {0, 3, 4}, - {3, 2, 5}, - {3, 5, 4}, -}; - -class AnIso : public ma::AnisotropicFunction -{ - public: - AnIso(ma::Mesh* m, double sf1, double sf2) : - mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) - { - average = ma::getAverageEdgeLength(m); - ma::getBoundingBox(m, lower, upper); - } - virtual void getValue(ma::Entity*, ma::Matrix& R, ma::Vector& H) - { - double h = average/sizeFactor1; - H = ma::Vector(h, h, h/sizeFactor2); - R = ma::Matrix( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0 - ); - } - private: - ma::Mesh* mesh; - double sizeFactor1, sizeFactor2, average; - ma::Vector lower, upper; -}; - - -int main(int argc, char** argv) -{ - MPI_Init(&argc,&argv); - { - pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); - lion_set_verbosity(1); - gmi_register_mesh(); - gmi_register_null(); - - apf::Gid* conn = &triangles[0][0]; - double* coords = &vtx_coords[0][0]; - - int nelem=5; - int etype=2; - int nverts=6; - int dim=2; - - //Create mesh - gmi_model* model = gmi_load(".null"); - apf::Mesh2* m = apf::makeEmptyMdsMesh(model, dim, false, &PCUObj); - apf::GlobalToVert outMap; - apf::construct(m, conn, nelem, etype, outMap); - apf::alignMdsRemotes(m); - apf::deriveMdsModel(m); - apf::setCoords(m, coords, nverts, outMap); - outMap.clear(); - m->verify(); - apf::writeVtkFiles("before_coarsen", m); - - //Coarsen - AnIso sf(m, 0.7, 1); - ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); - in->maximumIterations = 1; - in->shouldCoarsen = true; - validateInput(in); - ma::Adapt* a = new ma::Adapt(in); - coarsen(a); - m->verify(); - - apf::writeVtkFiles("after_coarsen", m, 1); - - m->destroyNative(); - apf::destroyMesh(m); - } - MPI_Finalize(); -} - From ef38ec5cace424a056d5b0aa60e968496de03b2e Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 26 Jun 2025 12:17:05 -0400 Subject: [PATCH 109/181] reduced min size --- ma/maSize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/maSize.h b/ma/maSize.h index f1358cb51..f83021a30 100644 --- a/ma/maSize.h +++ b/ma/maSize.h @@ -20,7 +20,7 @@ namespace ma { typedef apf::Matrix3x3 Matrix; const double MAXLENGTH = 1.5; -const double MINLENGTH = .75; +const double MINLENGTH = .5; class SizeField { From 08c63d47a2286e5f18825c45157a395dacdaf1f7 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 27 Jun 2025 13:15:11 -0400 Subject: [PATCH 110/181] single step coarsen --- ma/ma.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/ma.cc b/ma/ma.cc index c770478f7..b831237db 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,7 +27,7 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - coarsenMultiple(a); + // coarsenMultiple(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); From 7d9b960048bd2c68c33e6b6a3d777814a274cdcf Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 27 Jun 2025 13:29:44 -0400 Subject: [PATCH 111/181] multiple step coarsen --- ma/ma.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/ma.cc b/ma/ma.cc index b831237db..f751b2d5b 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -34,7 +34,7 @@ void adapt(Input* in) midBalance(a); refine(a); snap(a); - coarsen(a); + coarsenMultiple(a); coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); From ff096dc45aeb9307de8b92e02804c0cb85b51718 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 27 Jun 2025 13:34:24 -0400 Subject: [PATCH 112/181] coarsen multiple --- ma/ma.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/ma.cc b/ma/ma.cc index f751b2d5b..4b8102136 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,7 +27,7 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - // coarsenMultiple(a); + coarsenMultiple(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); From 25aa8b2b6748d5971ee70dd29629ce24fd7f946b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 27 Jun 2025 13:35:52 -0400 Subject: [PATCH 113/181] single step coarsen --- ma/ma.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index 4b8102136..97c80456e 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,14 +27,14 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - coarsenMultiple(a); + coarsen(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); midBalance(a); refine(a); snap(a); - coarsenMultiple(a); + coarsen(a); coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); From 541e88048a6c264189decf4cbf4d0e99cef6fabd Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 27 Jun 2025 17:48:37 -0400 Subject: [PATCH 114/181] cache length --- ma/ma.cc | 4 ++-- ma/maCoarsen.cc | 30 ++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index 97c80456e..4b8102136 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,14 +27,14 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - coarsen(a); + coarsenMultiple(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); midBalance(a); refine(a); snap(a); - coarsen(a); + coarsenMultiple(a); coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 54c554ae4..529900d86 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -257,6 +257,20 @@ bool coarsen(Adapt* a, bool aggressive) return true; } +static double getLength(Adapt* a, Tag* lengthTag, Entity* edge) +{ + double length = 0; + length = a->sizeField->measure(edge); + if (a->mesh->hasTag(edge, lengthTag)) + a->mesh->getDoubleTag(edge, lengthTag, &length); + else { + length = a->sizeField->measure(edge); + a->mesh->setDoubleTag(edge, lengthTag, &length); + } + return length; + +} + static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); @@ -307,12 +321,13 @@ struct EdgeLength } }; -bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, int& checked, apf::Up& adjacent) +bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, int& checked, apf::Up& adjacent, Tag* lengthTag) { Entity* vertex = *itr; std::vector sorted; for (int i=0; i < adjacent.n; i++) { - EdgeLength measured{adjacent.e[i], a->sizeField->measure(adjacent.e[i])}; + double length = getLength(a, lengthTag, adjacent.e[i]); + EdgeLength measured{adjacent.e[i], length}; if (measured.length > MINLENGTH) continue; auto pos = std::lower_bound(sorted.begin(), sorted.end(), measured); sorted.insert(pos, measured); @@ -365,14 +380,15 @@ bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::lis return false; } -std::list getShortEdgeVerts(Adapt* a) +std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) { std::list shortEdgeVerts; Iterator* it = a->mesh->begin(1); Entity* edge; while ((edge = a->mesh->iterate(it))) { - if (!a->sizeField->shouldCollapse(edge)) continue; + double length = getLength(a, lengthTag, edge); + if (length > MINLENGTH) continue; Entity* vertices[2]; a->mesh->getDownward(edge,0,vertices); for (int i = 0; i < 2; i++) { @@ -390,7 +406,8 @@ bool coarsenMultiple(Adapt* a, bool aggressive) if (!a->input->shouldCoarsen) return false; double t0 = pcu::Time(); - std::list shortEdgeVerts = getShortEdgeVerts(a); + Tag* lengthTag = a->mesh->createDoubleTag("edge_length", 1); + std::list shortEdgeVerts = getShortEdgeVerts(a, lengthTag); bool oldShouldForce = a->input->shouldForceAdaptation; if (aggressive) a->input->shouldForceAdaptation = true; @@ -405,13 +422,14 @@ bool coarsenMultiple(Adapt* a, bool aggressive) { apf::Up adjacent; if (!getAdjIndependentSet(a, shortEdgeVerts, itr, independentSetStarted, checked, adjacent)) continue; - if (collapseShortest(a, collapse, shortEdgeVerts, itr, checked, adjacent)) { + if (collapseShortest(a, collapse, shortEdgeVerts, itr, checked, adjacent, lengthTag)) { independentSetStarted=true; success++; } } ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE | CHECKED, 0); a->input->shouldForceAdaptation = oldShouldForce; + a->mesh->destroyTag(lengthTag); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); return true; From a4efa3ad59272b02ae7cd95efc6e9d709eb19806 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Tue, 1 Jul 2025 09:56:53 -0400 Subject: [PATCH 115/181] check collapse size check --- ma/maCoarsen.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 529900d86..475d79c42 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -271,7 +271,20 @@ static double getLength(Adapt* a, Tag* lengthTag, Entity* edge) } -static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse) +bool collapseSizeCheck(Adapt* a, Entity* vertex, Entity* edge, apf::Up& adjacent) +{ + Entity* vCollapse = getEdgeVertOppositeVert(a->mesh, edge, vertex); + for (int i=0; imesh, adjacent.e[i], vCollapse)}; + Entity* newEdge = a->mesh->createEntity(apf::Mesh::EDGE, 0, newEdgeVerts); + double length = a->sizeField->measure(newEdge); + destroyElement(a, newEdge); + if (length > MAXLENGTH) return false; + } + return true; +} + +static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, apf::Up& adjacent) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); bool alreadyFlagged = true; @@ -285,12 +298,9 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll if (collapse.setEdge(edge) && collapse.checkClass() && collapse.checkTopo() && + collapseSizeCheck(a, keep, edge, adjacent) && collapse.tryBothDirections(quality)) { - if (collapse.edgeGrewPastMaxLength()) { - result = false; - collapse.cancel(); - } - else result = true; + result = true; } if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); return result; @@ -338,7 +348,7 @@ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdg } for (int i=0; i < sorted.size(); i++) { Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, sorted[i].edge, vertex); - if (!tryCollapseEdge(a, sorted[i].edge, keepVertex, collapse)) continue; + if (!tryCollapseEdge(a, sorted[i].edge, keepVertex, collapse, adjacent)) continue; flagIndependentSet(a, adjacent, checked); itr = shortEdgeVerts.erase(itr); collapse.destroyOldElements(); From 13b8cc0229ef765ddd0f7197bc80c225ce7f7b60 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 2 Jul 2025 16:23:44 -0400 Subject: [PATCH 116/181] remove cap adapt --- ma/ma.cc | 2 +- test/aniso_adapt_cap.cc | 146 ---------------------------------------- 2 files changed, 1 insertion(+), 147 deletions(-) delete mode 100644 test/aniso_adapt_cap.cc diff --git a/ma/ma.cc b/ma/ma.cc index 4b8102136..c770478f7 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -34,7 +34,7 @@ void adapt(Input* in) midBalance(a); refine(a); snap(a); - coarsenMultiple(a); + coarsen(a); coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc deleted file mode 100644 index f20c811a5..000000000 --- a/test/aniso_adapt_cap.cc +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "maAdapt.h" -#include "maCoarsen.h" -#include "maRefine.h" -#include "maSnap.h" -#include "lionPrint.h" -#include "aniso_adapt.h" - -#include "CapstoneModule.h" -#include "CreateMG_Framework_Core.h" -#include "CreateMG_Framework_Analysis.h" -#include "CreateMG_Framework_Application.h" -#include "CreateMG_Framework_Attributes.h" -#include "CreateMG_Framework_Core.h" -#include "CreateMG_Framework_Geometry.h" -#include "CreateMG_Framework_Mesh.h" - -using namespace CreateMG; -using namespace CreateMG::Attribution; -using namespace CreateMG::Mesh; -using namespace CreateMG::Geometry; - -int main(int argc, char** argv) -{ - MPI_Init(&argc, &argv); - { - pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); - - if (argc < 2) { - if(PCUObj.Self()==0) - std::cerr << "usage: " << argv[0] - << " <.cre file> or\n" - << " <.smb file> \n"; - return EXIT_FAILURE; - } - - - gmi_register_mesh(); - gmi_register_null(); - - const char* meshFile = argv[1]; - // load capstone mesh - // create an instance of the Capstone Module activating CREATE/CREATE/CREATE - // for the Geometry/Mesh/Attribution databases - /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ - const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD - const std::string mdbName("Mesh Database : Create"); - const std::string adbName("Attribution Database : Create"); - - CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); - - GeometryDatabaseInterface *g = cs.get_geometry(); - MeshDatabaseInterface *m = cs.get_mesh(); - AppContext *c = cs.get_context(); - - PCU_ALWAYS_ASSERT(g); - PCU_ALWAYS_ASSERT(m); - PCU_ALWAYS_ASSERT(c); - - v_string filenames; - filenames.push_back(meshFile); - - M_GModel gmodel = cs.load_files(filenames); - - int numbreps = 0; - MG_CALL(g->get_num_breps(numbreps)); - std::cout << "number of b reps is " << numbreps << std::endl; - if(numbreps == 0) - error(HERE, ERR_INVALID_INPUT, "Model is empty"); - - M_MModel mmodel; - // Pick the volume mesh model from associated mesh models to this geom model - std::vector mmodels; - MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); - for(std::size_t i = 0; i < mmodels.size(); ++i) - { - M_MModel ammodel = mmodels[i]; - std::size_t numregs = 0; - std::size_t numfaces = 0; - std::size_t numedges = 0; - std::size_t numverts = 0; - MG_API_CALL(m, set_current_model(ammodel)); - MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); - MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); - MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); - MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); - std::cout << "num regions is " << numregs << std::endl; - std::cout << "num faces is " << numfaces << std::endl; - std::cout << "num edges is " << numedges << std::endl; - std::cout << "num verts is " << numverts << std::endl; - std::cout << "-----------" << std::endl; - if(numregs > 0) - { - mmodel = ammodel; - break; - } - } - - /* SET THE ADJACENCIES */ - MG_API_CALL(m, set_adjacency_state(REGION2FACE| - REGION2EDGE| - REGION2VERTEX| - FACE2EDGE| - FACE2VERTEX)); - MG_API_CALL(m, set_reverse_states()); - MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); - MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); - MG_API_CALL(m, compute_adjacency()); - - gmi_cap_start(); - gmi_register_cap(); - - // convert the mesh to apf/mds mesh - - apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); - lion_set_verbosity(1); - - //Adapt - refineSnapTest(mesh, 2, 1); - - gmi_cap_stop(); - } - MPI_Finalize(); -} From 9b8244482301fac24f27184f542731646156dcfe Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 2 Jul 2025 16:47:19 -0400 Subject: [PATCH 117/181] fix compile error --- test/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 72034e2be..d2630398c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -176,7 +176,6 @@ test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) test_exe_func(aniso_adapt_sim aniso_adapt_sim.cc) -test_exe_func(aniso_adapt_cap aniso_adapt_cap.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) From 19aee8ea24f56f4f3b380afa26b5e7bea615415d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 2 Jul 2025 19:58:13 -0400 Subject: [PATCH 118/181] single coarsen --- ma/ma.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ma/ma.cc b/ma/ma.cc index c770478f7..97c80456e 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,7 +27,7 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - coarsenMultiple(a); + coarsen(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); From 827e7bda8f45de028b74cd26f257275ee805dee2 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 3 Jul 2025 15:29:44 -0400 Subject: [PATCH 119/181] fixed snap bug --- ma/maAdapt.h | 1 - ma/maRefine.cc | 11 ---- ma/maSnap.cc | 143 +++++++++++++----------------------------------- ma/maSnapper.cc | 8 +-- 4 files changed, 42 insertions(+), 121 deletions(-) diff --git a/ma/maAdapt.h b/ma/maAdapt.h index 335ee79e4..e4daa9246 100644 --- a/ma/maAdapt.h +++ b/ma/maAdapt.h @@ -55,7 +55,6 @@ class Adapt apf::BuildCallback* buildCallback; SizeField* sizeField; SolutionTransfer* solutionTransfer; - std::queue vtxToSnap; Refine* refine; ShapeHandler* shape; int coarsensLeft; diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 4e2b72a94..10dea7d95 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -127,16 +127,6 @@ Refine::~Refine() m->destroyTag(numberTag); } -void AddVertexToSnap(Refine* r, Entity* vert) -{ - Mesh* m = r->adapt->mesh; - int dim = m->getDimension(); - int md = m->getModelType(m->toModel(vert)); - if (dim == md) return; - r->adapt->vtxToSnap.push(vert); - setFlag(r->adapt, vert, SNAP); -} - Entity* makeSplitVert(Refine* r, Entity* edge) { Adapt* a = r->adapt; @@ -155,7 +145,6 @@ Entity* makeSplitVert(Refine* r, Entity* edge) if (a->input->shouldTransferToClosestPoint) transferToClosestPointOnEdgeSplit(m,edge,0.5,param); Entity* vert = buildVertex(a,c,point,param); - AddVertexToSnap(r, vert); st->onVertex(me,xi,vert); sf->interpolate(me,xi,vert); apf::destroyMeshElement(me); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index dbfd58590..42108c260 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -745,12 +745,11 @@ static void getSnapPoint(Mesh* m, Entity* v, Vector& x) class SnapAll : public Operator { public: - SnapAll(Adapt* a, Tag* t, bool simple): - snapper(a, t, simple) + SnapAll(Adapt* a, Tag* t, Snapper& snapperIn) { adapter = a; tag = t; - successCount = 0; + snapper = &snapperIn; didAnything = false; vert = 0; } @@ -760,20 +759,17 @@ class SnapAll : public Operator if ( ! getFlag(adapter, e, SNAP)) return false; vert = e; - snapper.setVert(e); + snapper->setVert(e); return true; } bool requestLocality(apf::CavityOp* o) { - return snapper.requestLocality(o); + return snapper->requestLocality(o); } void apply() { - bool snapped = snapper.run(); + bool snapped = snapper->run(); didAnything = didAnything || snapped; - if (snapped) - ++successCount; - clearFlag(adapter, vert, SNAP); } int successCount; bool didAnything; @@ -781,14 +777,13 @@ class SnapAll : public Operator Adapt* adapter; Tag* tag; Entity* vert; - Snapper snapper; + Snapper* snapper; }; -bool snapAllVerts(Adapt* a, Tag* t, bool isSimple, long& successCount) +bool snapAllVerts(Adapt* a, Tag* t, Snapper& snapper) { - SnapAll op(a, t, isSimple); + SnapAll op(a, t, snapper); applyOperator(a, &op); - successCount += a->mesh->getPCU()->Add(op.successCount); return a->mesh->getPCU()->Or(op.didAnything); } @@ -847,84 +842,44 @@ long tagVertsToSnap(Adapt* a, Tag*& tag) { Mesh* m = a->mesh; int dim = m->getDimension(); - int notProcessed = a->vtxToSnap.size(); - int owned = 0; - while (notProcessed > 0) - { - notProcessed--; - Entity* vertex = a->vtxToSnap.front(); - a->vtxToSnap.pop(); - if (!getFlag(a, vertex, SNAP)) //This means the vertex was deleted + Entity* v; + long n = 0; + Iterator* it = m->begin(0); + while ((v = m->iterate(it))) { + int md = m->getModelType(m->toModel(v)); + if (dim == 3 && md == 3) continue; - Vector target; - getSnapPoint(m, vertex, target); - Vector prev = getPosition(m, vertex); - if (apf::areClose(prev, target, 1e-12)) { - clearFlag(a, vertex, SNAP); + Vector s; + getSnapPoint(m, v, s); + Vector x = getPosition(m, v); + if (apf::areClose(s, x, 1e-12)) continue; - } - m->setDoubleTag(vertex, tag, &target[0]); - if (m->isOwned(vertex)) - ++owned; - a->vtxToSnap.push(vertex); + m->setDoubleTag(v, tag, &s[0]); + setFlag(a, v, SNAP); + if (m->isOwned(v)) + ++n; } - return m->getPCU()->Add(owned); + m->end(it); + return m->getPCU()->Add(n); } -static void markVertsToSnap(Adapt* a, Tag* t) -{ - HasTag p(a->mesh, t); - markEntities(a, 0, p, SNAP, DONT_SNAP); -} - -bool snapOneRound(Adapt* a, Tag* t, bool isSimple, long& successCount) -{ - markVertsToSnap(a, t); - if (a->mesh->hasMatching()) - return snapMatchedVerts(a, t, isSimple, successCount); - else - return snapAllVerts(a, t, isSimple, successCount); -} - -long snapTaggedVerts(Adapt* a, Tag* tag) -{ - long successCount = 0; - /* there are two approaches possible here: - * 1- first snap all the vertices we can without any additional - * operation such as digging (simple snap). And then try snapping - * the remaining vertices that will need extra modifications (non- - * simple snap). - * 2- first do the non-simple snaps and then the simple snaps. - * - * Here we choose approach 2 for the following reasons - * (a) approach 2 is approximately as fast as approach 1 - * (b) the problematic snaps will be attempted as soon as possible. - * This is extremely helpful because if we wait until later on - * bringing the vert to-be-snapped to the boundary might become more - * difficult due to the change in location of neighboring verticies - * that will be snapped before the problematic vert to-be-snapped. - */ - while (snapOneRound(a, tag, false, successCount)); - while (snapOneRound(a, tag, true, successCount)); - return successCount; -} - -void trySnapping(Adapt* a, Snapper& snapper) +long snapTaggedVerts(Adapt* a, Tag* tag, Snapper& snapper) { bool shouldForce = a->input->shouldForceAdaptation; a->input->shouldForceAdaptation = true; //Allows quality to decrease from snapping - while (a->vtxToSnap.size() > 0) - { - Entity* vertex = a->vtxToSnap.front(); - a->vtxToSnap.pop(); - snapper.setVert(vertex); - if (snapper.run() && getFlag(a, vertex, SNAP)) - a->vtxToSnap.push(vertex); + long successCount = 0; + bool snapped = true; + while (snapped) { + tagVertsToSnap(a, tag); + if (a->mesh->hasMatching()) + snapped = snapMatchedVerts(a, tag, false, successCount); + else + snapped = snapAllVerts(a, tag, snapper); } a->input->shouldForceAdaptation = shouldForce; - a->vtxToSnap = {}; + return successCount; } void snap(Adapt* a) @@ -933,43 +888,21 @@ void snap(Adapt* a) return; double t0 = pcu::Time(); Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); - // preventMatchedCavityMods(a); + preventMatchedCavityMods(a); int toSnap = tagVertsToSnap(a, snapTag); // ma_dbg::addTargetLocation(a, "snap_target"); // ma_dbg::addClassification(a, "classification"); Snapper snapper(a, snapTag, false); - trySnapping(a, snapper); - // snapLayer(a, tag); + snapTaggedVerts(a, snapTag, snapper); + snapLayer(a, snapTag); double t1 = pcu::Time(); print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds\n", toSnap, snapper.numSnapped, snapper.numFailed, snapper.numCollapseToVtx, snapper.numCollapse, snapper.numSwap, snapper.numSplitCollapse, t1 - t0); - // if (a->hasLayer) - // checkLayerShape(a->mesh, "after snapping"); - a->mesh->destroyTag(snapTag); -} - -void prevSnap(Adapt* a) -{ - if ( ! a->input->shouldSnap) - return; - double t0 = pcu::Time(); - Tag* tag; - /* we are starting to support a few operations on matched - meshes, including snapping+UR. this should prevent snapping - from modifying any matched entities */ - preventMatchedCavityMods(a); - long targets = tagVertsToSnap(a, tag); - long success = snapTaggedVerts(a, tag); - snapLayer(a, tag); - apf::removeTagFromDimension(a->mesh, tag, 0); - a->mesh->destroyTag(tag); - double t1 = pcu::Time(); - print(a->mesh->getPCU(), "snapped in %f seconds: %ld targets, %ld non-layer snaps", - t1 - t0, targets, success); if (a->hasLayer) checkLayerShape(a->mesh, "after snapping"); + a->mesh->destroyTag(snapTag); } } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 9da6cbec4..7a7dfbbe4 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -397,10 +397,10 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) // } // } //TODO: RUN FACE SWAP HERE - if (splitCollapse.run(ents[1], FPP->vert, 0)) { - numSplitCollapse++; - return true; - } + // if (splitCollapse.run(ents[1], FPP->vert, 0)) { + // numSplitCollapse++; + // return true; + // } print(mesh->getPCU(), "Swap failed: face swap not implemented"); } return false; From d27737f33424407176e50278a863d217d10c28b8 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 3 Jul 2025 17:15:27 -0400 Subject: [PATCH 120/181] add up snap values --- ma/maSnap.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 42108c260..6f7b19c3d 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -882,6 +882,10 @@ long snapTaggedVerts(Adapt* a, Tag* tag, Snapper& snapper) return successCount; } +int collect(Adapt* a, int val) { + return a->mesh->getPCU()->Add(val); +} + void snap(Adapt* a) { if (!a->input->shouldSnap) @@ -900,7 +904,7 @@ void snap(Adapt* a) double t1 = pcu::Time(); print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds\n", - toSnap, snapper.numSnapped, snapper.numFailed, snapper.numCollapseToVtx, snapper.numCollapse, snapper.numSwap, snapper.numSplitCollapse, t1 - t0); + toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); if (a->hasLayer) checkLayerShape(a->mesh, "after snapping"); a->mesh->destroyTag(snapTag); From b15f7e204a98a50ec719c8ca40aff99ea8337d5d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 3 Jul 2025 19:21:25 -0400 Subject: [PATCH 121/181] fixed bug caused by shared edge verts --- ma/maCollapse.cc | 4 ++-- ma/maSnapper.cc | 1 + test/aniso_adapt.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 68303dc87..cf492249b 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -174,8 +174,8 @@ bool checkEdgeCollapseEdgeRings(Adapt* a, Entity* edge) Mesh* m = a->mesh; Entity* v[2]; m->getDownward(edge,0,v); - PCU_ALWAYS_ASSERT( ! m->isShared(v[0])); - PCU_ALWAYS_ASSERT( ! m->isShared(v[1])); + if (!getFlag(a, v[0], DONT_COLLAPSE)) PCU_ALWAYS_ASSERT( ! m->isShared(v[0])); + if (!getFlag(a, v[1], DONT_COLLAPSE)) PCU_ALWAYS_ASSERT( ! m->isShared(v[1])); apf::Up ve[2]; m->getUp(v[0],ve[0]); m->getUp(v[1],ve[1]); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 7a7dfbbe4..d7a215370 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -390,6 +390,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) else { Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); + // Commented until faceswap, other wise can run into infinite loop // for (int i=0; i<3; i++) { // if (edgeSwap->run(edges[i])) { // numSwap++; diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index fef6dc755..42cf39d8e 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -54,7 +54,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) ma::snap(a); ma::coarsenMultiple(a); } - // ma::fixElementShapes(a); + ma::fixElementShapes(a); m->verify(); apf::writeVtkFiles("after_adapt",m); } \ No newline at end of file From 4a2c1caf09e2d58079ce29d131a71c6a9abc1d7e Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 16 Jul 2025 19:22:54 -0400 Subject: [PATCH 122/181] prevent infinite loop --- ma/maSnap.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 6f7b19c3d..90cd87c70 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -870,8 +870,11 @@ long snapTaggedVerts(Adapt* a, Tag* tag, Snapper& snapper) long successCount = 0; bool snapped = true; + int prevTagged = 0; while (snapped) { - tagVertsToSnap(a, tag); + int tagged = tagVertsToSnap(a, tag); + if (tagged == prevTagged) break; + prevTagged = tagged; if (a->mesh->hasMatching()) snapped = snapMatchedVerts(a, tag, false, successCount); else From 235ddfa04605f19fab01fa7ff3737a2be59f4e04 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Jul 2025 13:31:42 -0400 Subject: [PATCH 123/181] bring back eswap spltclps --- ma/maSnapper.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index d7a215370..938823964 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -390,18 +390,17 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) else { Entity* edges[3]; mesh->getDownward(ents[0], 1, edges); - // Commented until faceswap, other wise can run into infinite loop - // for (int i=0; i<3; i++) { - // if (edgeSwap->run(edges[i])) { - // numSwap++; - // return true; - // } - // } + for (int i=0; i<3; i++) { + if (edgeSwap->run(edges[i])) { + numSwap++; + return true; + } + } //TODO: RUN FACE SWAP HERE - // if (splitCollapse.run(ents[1], FPP->vert, 0)) { - // numSplitCollapse++; - // return true; - // } + if (splitCollapse.run(ents[1], FPP->vert, 0)) { + numSplitCollapse++; + return true; + } print(mesh->getPCU(), "Swap failed: face swap not implemented"); } return false; From 6cf04550be9b5ef58f0f41856c7738d61b0482da Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Jul 2025 14:10:24 -0400 Subject: [PATCH 124/181] generalize getTetStats --- ma/maSnapper.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 938823964..a2511f845 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -184,13 +184,13 @@ static Vector projOnTriPlane(Adapt* a, Entity* face, Entity* vert) return 0 : if an edge is degenerated 1-7 : the index indicating the location of projection point */ -static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double area[4]) +static int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* ents[4], double area[4]) { Entity* faceEdges[3]; - a->mesh->getDownward(FPP->problemFace, 1, faceEdges); + a->mesh->getDownward(face, 1, faceEdges); Entity* verts[3]; - a->mesh->getDownward(FPP->problemFace, 0, verts); + a->mesh->getDownward(face, 0, verts); Vector facePos[3]; Entity* edges[6]; @@ -200,12 +200,12 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double } Entity* faces[4]; - faces[0]=FPP->problemFace; + faces[0]=face; Entity* problemFaces[4]; - a->mesh->getDownward(FPP->problemRegion, 2, problemFaces); + a->mesh->getDownward(region, 2, problemFaces); for (int i=0; i<4; i++) { - if (problemFaces[i] == FPP->problemFace ) continue; + if (problemFaces[i] == face ) continue; else if (isLowInHigh(a->mesh, problemFaces[i], edges[0])) faces[1] = problemFaces[i]; else if (isLowInHigh(a->mesh, problemFaces[i], edges[1])) faces[2] = problemFaces[i]; else if (isLowInHigh(a->mesh, problemFaces[i], edges[2])) faces[3] = problemFaces[i]; @@ -222,7 +222,7 @@ static int getTetStats(Adapt* a, FirstProblemPlane* FPP, Entity* ents[4], double } } - Vector projection = projOnTriPlane(a, FPP->problemFace, FPP->vert); + Vector projection = projOnTriPlane(a, face, vert); //TODO: ERROR if projection = any point on problem face /* find normal to the plane */ @@ -341,7 +341,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { Entity* ents[4] = {0}; double area[4]; - int bit = getTetStats(adapt, FPP, ents, area); + int bit = getTetStats(adapt, FPP->vert, FPP->problemFace, FPP->problemRegion, ents, area); double min=area[0]; for(int i=1; i<4; i++) From 9104ce1c362e2e92e2618f26e4510bc5eda8c8d7 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 17 Jul 2025 20:20:49 -0400 Subject: [PATCH 125/181] new fixed shape --- ma/ma.cc | 3 +- ma/maShape.cc | 650 +++--------------------------------------------- ma/maSnap.cc | 2 +- ma/maSnapper.cc | 2 +- ma/maSnapper.h | 1 + 5 files changed, 44 insertions(+), 614 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index 97c80456e..e27809368 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -28,6 +28,7 @@ void adapt(Input* in) Adapt* a = new Adapt(in); preBalance(a); coarsen(a); + fixElementShapes(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); @@ -36,9 +37,9 @@ void adapt(Input* in) snap(a); coarsen(a); coarsenLayer(a); + fixElementShapes(a); } allowSplitCollapseOutsideLayer(a); - fixElementShapes(a); cleanupLayer(a); tetrahedronize(a); printQuality(a); diff --git a/ma/maShape.cc b/ma/maShape.cc index f34ebcc29..40a8d52fe 100644 --- a/ma/maShape.cc +++ b/ma/maShape.cc @@ -12,6 +12,7 @@ #include "maSize.h" #include "maAdapt.h" #include "maSnap.h" +#include "maSnapper.h" #include "maOperator.h" #include "maEdgeSwap.h" #include "maDoubleSplitCollapse.h" @@ -25,100 +26,6 @@ namespace ma { -/* projects vertex 3 onto the plane - of the bottom triangle and returns - the zone in which it lands as a bit code. - Each bit indicates whether the area coordinate - of that vertex is positive. -*/ - -int getSliverCode( - Adapt* a, - Entity* tet) -{ - SizeField* sf = a->sizeField; - Mesh* m = a->mesh; - Matrix J,Q; - apf::MeshElement* me = apf::createMeshElement(m,tet); - Vector center(.25,.25,.25); - apf::getJacobian(me,center,J); - sf->getTransform(me,center,Q); - J = J*Q; //Jacobian in metric space - apf::destroyMeshElement(me); - int code = 0; - // check first face - Entity* fs[4]; - m->getDownward(tet, 2, fs); - double f0Qual = a->shape->getQuality(fs[0]); - if ((f0Qual*f0Qual*f0Qual > a->input->goodQuality*a->input->goodQuality)) { - // if its okay, use it for projection - Vector v03 = J[2]; - J[2] = apf::cross(J[0],J[1]); //face normal towards v[3] - Vector projected = v03 - apf::project(v03,J[2]); //v[3] projected to face - Matrix inverseMap = apf::invert(apf::transpose(J)); - Vector basisPoint = inverseMap * projected; - Vector areaPoint(1-basisPoint[0]-basisPoint[1], - basisPoint[0], - basisPoint[1]); - for (int i=0; i < 3; ++i) - if (areaPoint[i] > 0) - code |= (1< -0.10 && areaPoint[i] < 0.10) - code |= ((1< 0) - code |= ((1< -0.20 && areaPoint[i] < 0.20) - code |= ((1<> 6) & 1) - return table2d[(code >> 7) & 3][(code >> 9) & 3]; - else - return table[code & 7][(code >> 3) & 7]; -} - struct IsBadQuality : public Predicate { IsBadQuality(Adapt* a_):a(a_) {} @@ -168,459 +75,6 @@ double getMinQuality(Adapt* a) return m->getPCU()->Min(minqual); } -class ShortEdgeFixer : public Operator -{ - public: - ShortEdgeFixer(Adapt* a): - remover(a) - { - adapter = a; - mesh = a->mesh; - sizeField = a->sizeField; - shortEdgeRatio = a->input->maximumEdgeRatio; - nr = nf = 0; - element = 0; - } - virtual ~ShortEdgeFixer() - { - } - virtual int getTargetDimension() {return mesh->getDimension();} - virtual bool shouldApply(Entity* e) - { - if ( ! getFlag(adapter,e,BAD_QUALITY)) - return false; - element = e; - Downward edges; - int n = mesh->getDownward(element,1,edges); - double l[6] = {}; - for (int i=0; i < n; ++i) - l[i] = sizeField->measure(edges[i]); - double maxLength; - double minLength; - Entity* shortEdge; - maxLength = minLength = l[0]; - shortEdge = edges[0]; - for (int i=1; i < n; ++i) - { - if (l[i] > maxLength) maxLength = l[i]; - if (l[i] < minLength) - { - minLength = l[i]; - shortEdge = edges[i]; - } - } - if ((maxLength/minLength) < shortEdgeRatio) - { - clearFlag(adapter,element,BAD_QUALITY); - return false; - } - remover.setEdge(shortEdge); - return true; - } - virtual bool requestLocality(apf::CavityOp* o) - { - return remover.requestLocality(o); - } - virtual void apply() - { - if (remover.run()) - ++nr; - else - { - ++nf; - clearFlag(adapter,element,BAD_QUALITY); - } - } - private: - Adapt* adapter; - Mesh* mesh; - Entity* element; - SizeField* sizeField; - ShortEdgeRemover remover; - double shortEdgeRatio; - public: - int nr; - int nf; -}; - -class TetFixerBase -{ - public: - virtual void setTet(Entity** v) = 0; - virtual bool requestLocality(apf::CavityOp* o) = 0; - virtual bool run() = 0; -}; - -class FixBySwap : public TetFixerBase -{ - public: - FixBySwap(Adapt* a): - adapter(a) - { - mesh = a->mesh; - edgeSwap = makeEdgeSwap(a); - nes = nf = numToTry = 0; - edges[0] = 0; - edges[1] = 0; - edges[2] = 0; - } - ~FixBySwap() - { - delete edgeSwap; - } - virtual void setTet(Entity** v) - { - Entity* tet = apf::findElement(mesh, apf::Mesh::TET, v); - PCU_ALWAYS_ASSERT(tet); - match = matchSliver(adapter, tet); - Entity* dv[4]; - mesh->getDownward(tet, 0, dv); - Entity* rv[4]; - rotateTet(dv,match.rotation,rv); - - enum { EDGE_EDGE, FACE_VERT }; - if (match.code_index==EDGE_EDGE) { - Entity* ev[2]; - ev[0] = rv[0]; ev[1] = rv[2]; - edges[0] = findUpward(mesh, apf::Mesh::EDGE, ev); - ev[0] = rv[1]; ev[1] = rv[3]; - edges[1] = findUpward(mesh, apf::Mesh::EDGE, ev); - numToTry = 2; - } - else - { - PCU_ALWAYS_ASSERT(match.code_index==FACE_VERT); - apf::findTriDown(mesh,rv,edges); - numToTry = 3; - } - } - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(edges, numToTry); - } - virtual bool run() - { - for (int i=0; i < numToTry; ++i) - if (edgeSwap->run(edges[i])) - { - ++nes; - return true; - } - ++nf; - return false; - } - private: - Adapt* adapter; - Mesh* mesh; - Entity* edges[3]; - EdgeSwap* edgeSwap; - CodeMatch match; - int numToTry; - int nes; - int nf; -}; - -class EdgeVertFixer : public TetFixerBase -{ -public: - EdgeVertFixer(Adapt* a): - singleSplitCollapse(a) - { - mesh = a->mesh; - edgeSwap = makeEdgeSwap(a); - nes = nssc = nf = 0; - edge = 0; - oppVert = 0; - } - ~EdgeVertFixer() - { - delete edgeSwap; - } - virtual void setTet(Entity** v) - { - /* In this template, the edge v[0]--v[1] and vert v[3] - are too close*/ - edge = apf::findElement(mesh, apf::Mesh::EDGE, v); - oppVert = v[3]; - verts[0] = v[0]; - verts[1] = v[1]; - verts[2] = v[3]; - } - virtual bool requestLocality(apf::CavityOp* o) - { - /* by requesting locality for all the verts we can be sure - * that all the desired entities for this operator are local */ - return o->requestLocality(verts,3); - } - virtual bool run() { - if (edgeSwap->run(edge)) { - ++nes; - return true; - } - if (singleSplitCollapse.run(edge, oppVert)) - { - ++nssc; - return true; - } - ++nf; - return false; - } -private: - Mesh* mesh; - Entity* verts[3]; - Entity *edge, *oppVert; - SingleSplitCollapse singleSplitCollapse; - EdgeSwap* edgeSwap; -public: - int nes; /* number of edge swaps done */ - int nssc; /* number of SSCs done */ - int nf; /* number of failures */ -}; - -class FaceVertFixer : public TetFixerBase -{ - public: - FaceVertFixer(Adapt* a): - faceSplitCollapse(a) - { - mesh = a->mesh; - edgeSwap = makeEdgeSwap(a); - nes = nf = nfsc = 0; - edges[0] = 0; - edges[1] = 0; - edges[2] = 0; - verts[0] = 0; - verts[1] = 0; - verts[2] = 0; - verts[3] = 0; - face = 0; - oppVert = 0; - tet = 0; - } - ~FaceVertFixer() - { - delete edgeSwap; - } - virtual void setTet(Entity** v) - { -/* in this template, the bottom face and v[3] - are too close, the key edges are those that bound - face v(0,1,2) */ - apf::findTriDown(mesh,v,edges); - tet = apf::findElement(mesh, apf::Mesh::TET, v); - oppVert = v[3]; - verts[0] = v[0]; - verts[1] = v[1]; - verts[2] = v[2]; - verts[3] = v[3]; - } - virtual bool requestLocality(apf::CavityOp* o) - { - /* by requesting locality for all the verts we can be sure - * that all the desired entities for this operator are local */ - return o->requestLocality(verts,4); - } - virtual bool run() - { - for (int i=0; i < 3; ++i) - if (edgeSwap->run(edges[i])) - { - ++nes; - return true; - } - face = apf::findUpward(mesh, apf::Mesh::TRIANGLE, edges); - if (faceSplitCollapse.run(face, tet)) - { - ++nfsc; - return true; - } - ++nf; - return false; - } - private: - Mesh* mesh; - Entity* edges[3]; - Entity* verts[4]; - Entity *face, *oppVert; - Entity* tet; - FaceSplitCollapse faceSplitCollapse; - EdgeSwap* edgeSwap; - public: - int nes; /* number of edge swaps done */ - int nfsc; /* number of FSCs done */ - int nf; /* number of failures */ -}; - -class EdgeEdgeFixer : public TetFixerBase -{ - public: - EdgeEdgeFixer(Adapt* a): - doubleSplitCollapse(a) - { - mesh = a->mesh; - edgeSwap = makeEdgeSwap(a); - nes = ndsc = nf = 0; - sf = a->sizeField; - edges[0] = 0; - edges[1] = 0; - } - ~EdgeEdgeFixer() - { - delete edgeSwap; - } - virtual void setTet(Entity** v) - { -/* in this template, the v[0]-v[2] amd v[1]-v[3] - edges are too close. */ - Entity* ev[2]; - ev[0] = v[0]; ev[1] = v[2]; - edges[0] = findUpward(mesh, apf::Mesh::EDGE, ev); - ev[0] = v[1]; ev[1] = v[3]; - edges[1] = findUpward(mesh, apf::Mesh::EDGE, ev); - } - virtual bool requestLocality(apf::CavityOp* o) - { - return o->requestLocality(edges,2); - } - virtual bool run() - { - for (int i=0; i < 2; ++i) - if (edgeSwap->run(edges[i])) - { - ++nes; - return true; - } - if (doubleSplitCollapse.run(edges)) - { - ++ndsc; - return true; - } - ++nf; - return false; - } - private: - Mesh* mesh; - Entity* edges[2]; - EdgeSwap* edgeSwap; - DoubleSplitCollapse doubleSplitCollapse; - SizeField* sf; - public: - int nes; - int ndsc; - int nf; -}; - -class LargeAngleTetFixer : public Operator -{ - public: - LargeAngleTetFixer(Adapt* a): - edgeEdgeFixer(a), - edgeVertFixer(a), - faceVertFixer(a) - { - adapter = a; - mesh = a->mesh; - tet = 0; - fixer = 0; - } - virtual ~LargeAngleTetFixer() - { - } - virtual int getTargetDimension() {return 3;} - enum { EDGE_EDGE, FACE_VERT, EDGE_VERT, VERT_VERT }; - virtual bool shouldApply(Entity* e) - { - if ( ! getFlag(adapter,e,BAD_QUALITY)) - return false; - tet = e; - CodeMatch match = matchSliver(adapter,e); - if (match.code_index==EDGE_EDGE) { - fixer = &edgeEdgeFixer; - } else if (match.code_index==FACE_VERT) { - fixer = &faceVertFixer; - } else if (match.code_index==EDGE_VERT) { - fixer = &edgeVertFixer; - } else if (match.code_index==VERT_VERT) { - fixer = &faceVertFixer; - } - Entity* v[4]; - mesh->getDownward(e,0,v); - Entity* rv[4]; - rotateTet(v,match.rotation,rv); - fixer->setTet(rv); - return true; - } - virtual bool requestLocality(apf::CavityOp* o) - { - return fixer->requestLocality(o); - } - virtual void apply() - { - if ( ! fixer->run()) - clearFlag(adapter,tet,BAD_QUALITY); - } - private: - Adapt* adapter; - Mesh* mesh; - Entity* tet; - TetFixerBase* fixer; - public: - EdgeEdgeFixer edgeEdgeFixer; - EdgeVertFixer edgeVertFixer; - FaceVertFixer faceVertFixer; -}; - -class LargeAngleTetAligner : public Operator -{ - public: - LargeAngleTetAligner(Adapt* a): - fixer(a) - { - adapter = a; - mesh = a->mesh; - tet = 0; - } - virtual ~LargeAngleTetAligner() - { - } - virtual int getTargetDimension() {return 3;} - virtual bool shouldApply(Entity* e) - { - if ( ! getFlag(adapter,e,BAD_QUALITY)) - return false; - tet = e; - /* PCU_ALWAYS_ASSERT(mesh->getType(e) == apf::Mesh::TET); */ - enum { EDGE_EDGE, FACE_VERT }; - CodeMatch match = matchSliver(adapter,e); - if (match.code_index==EDGE_EDGE) { - clearFlag(adapter,tet,BAD_QUALITY); - return false; - } - /* else */ - /* { PCU_ALWAYS_ASSERT(match.code_index==FACE_VERT); */ - /* fixer = &faceVertFixer; */ - /* } */ - Entity* v[4]; - mesh->getDownward(e,0,v); - fixer.setTet(v); - return true; - } - virtual bool requestLocality(apf::CavityOp* o) - { - return fixer.requestLocality(o); - } - virtual void apply() - { - if ( ! fixer.run()) - clearFlag(adapter,tet,BAD_QUALITY); - } - private: - Adapt* adapter; - Mesh* mesh; - Entity* tet; - FixBySwap fixer; -}; - class LargeAngleTriFixer : public Operator { public: @@ -737,19 +191,45 @@ class QualityImprover2D : public Operator int nf; }; -static double fixShortEdgeElements(Adapt* a) -{ - double t0 = pcu::Time(); - ShortEdgeFixer fixer(a); - applyOperator(a,&fixer); - double t1 = pcu::Time(); - return t1 - t0; -} - static void fixLargeAngleTets(Adapt* a) { - LargeAngleTetFixer fixer(a); - applyOperator(a,&fixer); + FaceSplitCollapse faceSplitCollapse(a); + SingleSplitCollapse splitCollapse(a); + DoubleSplitCollapse doubleSplitCollapse(a); + EdgeSwap* edgeSwap = makeEdgeSwap(a); + + Entity* tet; + Iterator* it = a->mesh->begin(3); + while ((tet = a->mesh->iterate(it))) { + if (!getFlag(a, tet, BAD_QUALITY)) continue; + clearFlag(a, tet, BAD_QUALITY); + Entity* verts[4]; + a->mesh->getDownward(tet, 0, verts); + Entity* vert = verts[0]; + Entity* face = getTetFaceOppositeVert(a->mesh, tet, vert); + Entity* ents[4]; + double area[4]; + int bit = getTetStats(a, vert, face, tet, ents, area); + + // two large dihedral angles -> key problem: two mesh edges + if (bit==3 || bit==5 || bit==6) { + if (edgeSwap->run(ents[0])) continue; + if (edgeSwap->run(ents[1])) continue; + if (splitCollapse.run(ents[0], vert)) continue; + if (splitCollapse.run(ents[1], vert)) continue; + if (doubleSplitCollapse.run(ents)) continue; + } + // three large dihedral angles -> key entity: a mesh face + else { + Entity* edges[3]; + a->mesh->getDownward(ents[0], 1, edges); + if (edgeSwap->run(edges[0])) continue; + if (edgeSwap->run(edges[1])) continue; + if (edgeSwap->run(edges[2])) continue; + //TODO: RUN FACE SWAP HERE + if (faceSplitCollapse.run(ents[0], tet)) continue; + } + } } static void fixLargeAngleTris(Adapt* a) @@ -758,18 +238,6 @@ static void fixLargeAngleTris(Adapt* a) applyOperator(a,&fixer); } -static void alignLargeAngleTets(Adapt* a) -{ - LargeAngleTetAligner aligner(a); - applyOperator(a,&aligner); -} - -static void alignLargeAngleTris(Adapt* a) -{ - LargeAngleTriFixer aligner(a); - applyOperator(a,&aligner); -} - static void improveQualities2D(Adapt* a) { QualityImprover2D improver(a); @@ -787,14 +255,6 @@ static double fixLargeAngles(Adapt* a) return t1 - t0; } -static void alignLargeAngles(Adapt* a) -{ - if (a->mesh->getDimension()==3) - alignLargeAngleTets(a); - else - alignLargeAngleTris(a); -} - double improveQualities(Adapt* a) { double t0 = pcu::Time(); @@ -812,6 +272,7 @@ void fixElementShapes(Adapt* a) return; double t0 = pcu::Time(); int count = markBadQuality(a); + print(a->mesh->getPCU(), "--iter %d of shape correction loop: #bad elements %d", 0, count); int originalCount = count; int prev_count; double time; @@ -820,7 +281,6 @@ void fixElementShapes(Adapt* a) if ( ! count) break; prev_count = count; - print(a->mesh->getPCU(), "--iter %d of shape correction loop: #bad elements %d", iter, count); time = fixLargeAngles(a); /* We need to snap the new verts as soon as they are * created (to avoid future problems). At the moment @@ -830,16 +290,10 @@ void fixElementShapes(Adapt* a) if (a->mesh->getDimension() == 3) snap(a); count = markBadQuality(a); - print(a->mesh->getPCU(), "--fixLargeAngles in %f seconds: #bad elements %d", time,count); - time = fixShortEdgeElements(a); - count = markBadQuality(a); - print(a->mesh->getPCU(), "--fixShortEdgeElements in %f seconds: #bad elements %d", time,count); if (count >= prev_count) unMarkBadQuality(a); // to make sure markEntities does not complain! // balance the mesh to avoid empty parts midBalance(a); - print(a->mesh->getPCU(), "--percent change in number of bad elements %f", - ((double) prev_count - (double) count) / (double) prev_count); iter++; } while(count < prev_count); double t1 = pcu::Time(); @@ -847,32 +301,6 @@ void fixElementShapes(Adapt* a) originalCount,count,t1-t0); } -void alignElements(Adapt* a) -{ - int max_iter = 5; - if ( ! a->input->shouldFixShape) - return; - double t0 = pcu::Time(); - int count = markBadQuality(a); - int originalCount = count; - int prev_count; - int i = 0; - do { - if ( ! count) - break; - prev_count = count; - alignLargeAngles(a); - count = markBadQuality(a); - ++i; - if (count >= prev_count || i >= max_iter) - unMarkBadQuality(a); - } while(count < prev_count && i < max_iter); - - double t1 = pcu::Time(); - print(a->mesh->getPCU(), "non-aligned elements down from %d to %d in %f seconds", - originalCount,count,t1-t0); -} - void printQuality(Adapt* a) { if ( ! a->input->shouldPrintQuality) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 90cd87c70..347c3c516 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -906,7 +906,7 @@ void snap(Adapt* a) snapLayer(a, snapTag); double t1 = pcu::Time(); - print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds\n", + print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds", toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); if (a->hasLayer) checkLayerShape(a->mesh, "after snapping"); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index a2511f845..1d2ae469c 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -184,7 +184,7 @@ static Vector projOnTriPlane(Adapt* a, Entity* face, Entity* vert) return 0 : if an edge is degenerated 1-7 : the index indicating the location of projection point */ -static int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* ents[4], double area[4]) +int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* ents[4], double area[4]) { Entity* faceEdges[3]; a->mesh->getDownward(face, 1, faceEdges); diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 3d6c0d6b3..395f5e5f2 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -89,6 +89,7 @@ class FirstProblemPlane void findCommonEdges(apf::Up& cpRegions); }; +int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* ents[4], double area[4]); Entity* getTetFaceOppositeVert(Mesh* m, Entity* e, Entity* v); void getFaceCoords(Mesh* m, Entity* face, std::vector& coords); Vector getCenter(Mesh* mesh, Entity* face); From af7f1a731023cf9b948371484ac73c82def55073 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 18 Jul 2025 22:18:17 -0400 Subject: [PATCH 126/181] better printFPP --- ma/maSnap.cc | 4 +--- ma/maSnapper.cc | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 347c3c516..723934f9e 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -897,9 +897,7 @@ void snap(Adapt* a) Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); preventMatchedCavityMods(a); int toSnap = tagVertsToSnap(a, snapTag); - - // ma_dbg::addTargetLocation(a, "snap_target"); - // ma_dbg::addClassification(a, "classification"); + if (toSnap == 0) return; Snapper snapper(a, snapTag, false); snapTaggedVerts(a, snapTag, snapper); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 1d2ae469c..a2229f3cd 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -126,6 +126,9 @@ static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) static void printFPP(Adapt* a, FirstProblemPlane* FPP) { + ma_dbg::addTargetLocation(a, "snap_target"); + ma_dbg::addClassification(a, "classification"); + apf::writeVtkFiles("FPP_Mesh", a->mesh); EntityArray invalid; for (int i=0; iproblemRegions.n; i++){ @@ -615,6 +618,8 @@ bool Snapper::trySimpleSnap() return tryReposition(adapt, vert, snapTag, invalid); } +static int DEBUGFAILED=0; + bool Snapper::run() { apf::Up invalid; @@ -639,7 +644,7 @@ bool Snapper::run() mesh->removeTag(vert,snapTag); clearFlag(adapt, vert, SNAP); } - // if (!success && numFailed == 1) printFPP(adapt, FPP); + // if (!success && ++DEBUGFAILED == 1) printFPP(adapt, FPP); if (FPP) delete FPP; return success; From 9c20565806201597aee338bbdb375615f7ddc594 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 23 Jul 2025 19:42:38 -0400 Subject: [PATCH 127/181] fixed bug with partial periodic --- gmi_cap/gmi_cap.cc | 5 +---- ma/ma.cc | 2 +- ma/maSnap.cc | 7 ++----- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index e21769311..64b23e26a 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -197,10 +197,7 @@ static int periodic(struct gmi_model* m, struct gmi_ent* e, int dim) /* PARAM_COMPOSITE=4, //!< parametrization of a composite edge or face */ /* PARAM_UNBOUNDED=8 //!< infinite parametrization */ /* }; */ - if (paramType & 1) return 0; - int isPeriodic = paramType & (1<<1); - PCU_ALWAYS_ASSERT_VERBOSE(isPeriodic == false, "for now cannot handle periodic geometric entity (with discontinuity in parametric coords)"); - return isPeriodic; + return paramType & (1<<1); } static void range(struct gmi_model* m, struct gmi_ent* e, int dim, diff --git a/ma/ma.cc b/ma/ma.cc index e27809368..c3d1033e0 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -37,9 +37,9 @@ void adapt(Input* in) snap(a); coarsen(a); coarsenLayer(a); - fixElementShapes(a); } allowSplitCollapseOutsideLayer(a); + // fixElementShapes(a); cleanupLayer(a); tetrahedronize(a); printQuality(a); diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 723934f9e..58a04dfb9 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -122,6 +122,8 @@ static double interpolateParametricCoordinate( } double period = range[1]-range[0]; double span = b-a; + if (period < 0.5) //partial range can't be periodic + return (1-t)*a + t*b; if (!mode) { if (span < (period/2)) return (1-t)*a + t*b; @@ -493,8 +495,6 @@ static void interpolateParametricCoordinatesOnRegularFace( * 1) we are assuming manifold surfaces * 2) we only check for faces that are periodic */ - -#ifndef HAVE_CAPSTONE // this need to be done for faces, only if (dim != 2) return; @@ -511,9 +511,6 @@ static void interpolateParametricCoordinatesOnRegularFace( bool isPeriodic = m->getPeriodicRange(g,d,range); p[d] = interpolateParametricCoordinate(t,a[d],b[d],range,isPeriodic, 1); } -#else - (void) gface_isPeriodic; -#endif } static void interpolateParametricCoordinatesOnFace( From c3a1db1ae305c5edcca12938fde351c52050623d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 23 Jul 2025 23:36:43 -0400 Subject: [PATCH 128/181] removed capdefined --- ma/CMakeLists.txt | 1 + ma/maSnap.cc | 166 ++++++++++++++++++++++++---------------------- 2 files changed, 86 insertions(+), 81 deletions(-) diff --git a/ma/CMakeLists.txt b/ma/CMakeLists.txt index c8af8e6fe..72584fe9d 100644 --- a/ma/CMakeLists.txt +++ b/ma/CMakeLists.txt @@ -80,6 +80,7 @@ target_link_libraries(ma apf mds parma + apf_cap apf_zoltan apf_metis pcu diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 58a04dfb9..8d40b45bd 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -16,6 +16,7 @@ #include "maLayer.h" #include "maMatch.h" #include "maDBG.h" +#include "apfCAP.h" #include #include #include @@ -71,10 +72,10 @@ static size_t isSurfUnderlyingFaceDegenerate( m->getFirstDerivative(g, p, uTan, vTan); double uTanSize = uTan.getLength(); double vTanSize = vTan.getLength(); -#ifdef HAVE_CAPSTONE - uTanSize = uTan * uTan; - vTanSize = vTan * vTan; -#endif + if (dynamic_cast(m)) { + uTanSize = uTan * uTan; + vTanSize = vTan * vTan; + } if (uTanSize < tol || vTanSize < tol) { axis = degenAxes; values.push_back(candidateDegenParam); @@ -155,46 +156,46 @@ static void interpolateParametricCoordinateOnEdge( p[1] = 0.0; p[2] = 0.0; -#ifdef HAVE_CAPSTONE - // account for non-uniform parameterization of model-edge - Vector X[3]; - Vector para[2] = {a, b}; - for (int i = 0; i < 2; i++) - m->snapToModel(g, para[i], X[i]); + if (dynamic_cast(m)) { + // account for non-uniform parameterization of model-edge + Vector X[3]; + Vector para[2] = {a, b}; + for (int i = 0; i < 2; i++) + m->snapToModel(g, para[i], X[i]); - double tMax = 1., tMin = 0.; - m->snapToModel(g, p, X[2]); + double tMax = 1., tMin = 0.; + m->snapToModel(g, p, X[2]); - // check if the snap point on the model edge is - // approximately at same length from either vertices + // check if the snap point on the model edge is + // approximately at same length from either vertices - double r = (X[0]-X[2]).getLength(); - double s = (X[1]-X[2]).getLength(); + double r = (X[0]-X[2]).getLength(); + double s = (X[1]-X[2]).getLength(); - double alpha = t/(1. - t); //parametric ratio + double alpha = t/(1. - t); //parametric ratio - int num_it = 0; - while (r/s < 0.95 * alpha || r/s > 1.05 * alpha) { - if ( r/s > alpha) { - tMax = t; - t = (tMin + t) / 2.; - } - else { - tMin = t; - t = (t + tMax) / 2.; - } + int num_it = 0; + while (r/s < 0.95 * alpha || r/s > 1.05 * alpha) { + if ( r/s > alpha) { + tMax = t; + t = (tMin + t) / 2.; + } + else { + tMin = t; + t = (t + tMax) / 2.; + } - p[0] = interpolateParametricCoordinate(t, a[0], b[0], range, isPeriodic, 0); + p[0] = interpolateParametricCoordinate(t, a[0], b[0], range, isPeriodic, 0); - m->snapToModel(g, p, X[2]); + m->snapToModel(g, p, X[2]); - r = (X[0]-X[2]).getLength(); - s = (X[1]-X[2]).getLength(); + r = (X[0]-X[2]).getLength(); + s = (X[1]-X[2]).getLength(); - if ( num_it > 20) break; - num_it++; + if ( num_it > 20) break; + num_it++; + } } -#endif } // convert (phi,theta) on unit sphere to (x,y,z) @@ -496,20 +497,22 @@ static void interpolateParametricCoordinatesOnRegularFace( * 2) we only check for faces that are periodic */ // this need to be done for faces, only - if (dim != 2) - return; - if (!gface_isPeriodic) - return; - - Vector x; - bool ok; - ok = m->isParamPointInsideModel(g, &p[0], x); - if (ok) - return; - - for (int d=0; d < dim; ++d) { - bool isPeriodic = m->getPeriodicRange(g,d,range); - p[d] = interpolateParametricCoordinate(t,a[d],b[d],range,isPeriodic, 1); + if (!dynamic_cast(m)) { + if (dim != 2) + return; + if (!gface_isPeriodic) + return; + + Vector x; + bool ok; + ok = m->isParamPointInsideModel(g, &p[0], x); + if (ok) + return; + + for (int d=0; d < dim; ++d) { + bool isPeriodic = m->getPeriodicRange(g,d,range); + p[d] = interpolateParametricCoordinate(t,a[d],b[d],range,isPeriodic, 1); + } } } @@ -526,50 +529,51 @@ static void interpolateParametricCoordinatesOnFace( size_t num = isSurfUnderlyingFaceDegenerate(m, g, axes, vals); if (num > 0) { // the underlying surface is degenerate -#ifndef HAVE_CAPSTONE - interpolateParametricCoordinatesOnDegenerateFace(m, g, t, a, b, axes, vals, p); -#else - // account for non-uniform parameterization of model-edge - Vector X[3]; - Vector para[2] = {a, b}; - for (int i = 0; i < 2; i++) - m->snapToModel(g, para[i], X[i]); + if (!dynamic_cast(m)) { + interpolateParametricCoordinatesOnDegenerateFace(m, g, t, a, b, axes, vals, p); + } + else { + // account for non-uniform parameterization of model-edge + Vector X[3]; + Vector para[2] = {a, b}; + for (int i = 0; i < 2; i++) + m->snapToModel(g, para[i], X[i]); - interpolateParametricCoordinatesOnDegenerateFace(m, g, t, para[0], para[1], axes, vals, p); + interpolateParametricCoordinatesOnDegenerateFace(m, g, t, para[0], para[1], axes, vals, p); - double tMax = 1., tMin = 0.; - m->snapToModel(g, p, X[2]); + double tMax = 1., tMin = 0.; + m->snapToModel(g, p, X[2]); - // check if the snap point on the model edge is - // approximately at same length from either vertices + // check if the snap point on the model edge is + // approximately at same length from either vertices - double r = (X[0]-X[2]).getLength(); - double s = (X[1]-X[2]).getLength(); + double r = (X[0]-X[2]).getLength(); + double s = (X[1]-X[2]).getLength(); - double alpha = t/(1. - t); //parametric ratio + double alpha = t/(1. - t); //parametric ratio - int num_it = 0; - while (r/s < 0.95 * alpha || r/s > 1.05 * alpha) { - if ( r/s > alpha) { - tMax = t; - t = (tMin + t) / 2.; - } - else { - tMin = t; - t = (t + tMax) / 2.; - } + int num_it = 0; + while (r/s < 0.95 * alpha || r/s > 1.05 * alpha) { + if ( r/s > alpha) { + tMax = t; + t = (tMin + t) / 2.; + } + else { + tMin = t; + t = (t + tMax) / 2.; + } - interpolateParametricCoordinatesOnDegenerateFace(m, g, t, para[0], para[1], axes, vals, p); + interpolateParametricCoordinatesOnDegenerateFace(m, g, t, para[0], para[1], axes, vals, p); - m->snapToModel(g, p, X[2]); + m->snapToModel(g, p, X[2]); - r = (X[0]-X[2]).getLength(); - s = (X[1]-X[2]).getLength(); + r = (X[0]-X[2]).getLength(); + s = (X[1]-X[2]).getLength(); - if ( num_it > 20) break; - num_it++; + if ( num_it > 20) break; + num_it++; + } } -#endif } else interpolateParametricCoordinatesOnRegularFace(m, g, t, a, b, p); From 82c5636e6f14420f7239e0dbcc72a6a8a6faf40b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 23 Jul 2025 23:36:58 -0400 Subject: [PATCH 129/181] fix shape once --- ma/ma.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index c3d1033e0..97c80456e 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -28,7 +28,6 @@ void adapt(Input* in) Adapt* a = new Adapt(in); preBalance(a); coarsen(a); - fixElementShapes(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); @@ -39,7 +38,7 @@ void adapt(Input* in) coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); - // fixElementShapes(a); + fixElementShapes(a); cleanupLayer(a); tetrahedronize(a); printQuality(a); From b1aa88ab366563448d264440fb621206ab5f52a3 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Jul 2025 15:38:31 -0400 Subject: [PATCH 130/181] optional capstone check --- ma/CMakeLists.txt | 5 ++++- ma/maSnap.cc | 53 +++++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/ma/CMakeLists.txt b/ma/CMakeLists.txt index 72584fe9d..45a217fd0 100644 --- a/ma/CMakeLists.txt +++ b/ma/CMakeLists.txt @@ -80,12 +80,15 @@ target_link_libraries(ma apf mds parma - apf_cap apf_zoltan apf_metis pcu ) +if (ENABLE_CAPSTONE) +target_link_libraries(ma PUBLIC apf_cap) +endif() + scorec_export_library(ma) bob_end_subdir() diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 8d40b45bd..eecee363f 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -16,7 +16,6 @@ #include "maLayer.h" #include "maMatch.h" #include "maDBG.h" -#include "apfCAP.h" #include #include #include @@ -25,8 +24,22 @@ #include #include +#ifdef HAVE_CAPSTONE +#include "apfCAP.h" +#endif + namespace ma { +static bool isCapstoneMesh(apf::Mesh* m) +{ + #ifdef HAVE_CAPSTONE + if (dynamic_cast(m)) return true; + else return false; + #else + return false; + #endif +} + static size_t isSurfUnderlyingFaceDegenerate( apf::Mesh* m, Model* g, // this the model entity in question @@ -72,7 +85,7 @@ static size_t isSurfUnderlyingFaceDegenerate( m->getFirstDerivative(g, p, uTan, vTan); double uTanSize = uTan.getLength(); double vTanSize = vTan.getLength(); - if (dynamic_cast(m)) { + if (isCapstoneMesh(m)) { uTanSize = uTan * uTan; vTanSize = vTan * vTan; } @@ -156,7 +169,7 @@ static void interpolateParametricCoordinateOnEdge( p[1] = 0.0; p[2] = 0.0; - if (dynamic_cast(m)) { + if (isCapstoneMesh(m)) { // account for non-uniform parameterization of model-edge Vector X[3]; Vector para[2] = {a, b}; @@ -497,22 +510,22 @@ static void interpolateParametricCoordinatesOnRegularFace( * 2) we only check for faces that are periodic */ // this need to be done for faces, only - if (!dynamic_cast(m)) { - if (dim != 2) - return; - if (!gface_isPeriodic) - return; - - Vector x; - bool ok; - ok = m->isParamPointInsideModel(g, &p[0], x); - if (ok) - return; - - for (int d=0; d < dim; ++d) { - bool isPeriodic = m->getPeriodicRange(g,d,range); - p[d] = interpolateParametricCoordinate(t,a[d],b[d],range,isPeriodic, 1); - } + if (isCapstoneMesh(m)) + return; + if (dim != 2) + return; + if (!gface_isPeriodic) + return; + + Vector x; + bool ok; + ok = m->isParamPointInsideModel(g, &p[0], x); + if (ok) + return; + + for (int d=0; d < dim; ++d) { + bool isPeriodic = m->getPeriodicRange(g,d,range); + p[d] = interpolateParametricCoordinate(t,a[d],b[d],range,isPeriodic, 1); } } @@ -529,7 +542,7 @@ static void interpolateParametricCoordinatesOnFace( size_t num = isSurfUnderlyingFaceDegenerate(m, g, axes, vals); if (num > 0) { // the underlying surface is degenerate - if (!dynamic_cast(m)) { + if (!isCapstoneMesh(m)) { interpolateParametricCoordinatesOnDegenerateFace(m, g, t, a, b, axes, vals, p); } else { From d7efb6370a8672d401ba50869da5660ffc5122ef Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 26 Jul 2025 16:05:30 -0400 Subject: [PATCH 131/181] remove aggressive coarsen --- ma/maCoarsen.cc | 8 ++------ ma/maCoarsen.h | 5 ++--- test/aniso_adapt.h | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 475d79c42..9d2310208 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -229,7 +229,7 @@ long markEdgesToCollapse(Adapt* a) DONT_COLLAPSE | NEED_NOT_COLLAPSE); } -bool coarsen(Adapt* a, bool aggressive) +bool coarsen(Adapt* a) { if (!a->input->shouldCoarsen) return false; @@ -411,16 +411,13 @@ std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) return shortEdgeVerts; } -bool coarsenMultiple(Adapt* a, bool aggressive) +bool coarsenMultiple(Adapt* a) { if (!a->input->shouldCoarsen) return false; double t0 = pcu::Time(); Tag* lengthTag = a->mesh->createDoubleTag("edge_length", 1); std::list shortEdgeVerts = getShortEdgeVerts(a, lengthTag); - bool oldShouldForce = a->input->shouldForceAdaptation; - if (aggressive) - a->input->shouldForceAdaptation = true; Collapse collapse; collapse.Init(a); @@ -438,7 +435,6 @@ bool coarsenMultiple(Adapt* a, bool aggressive) } } ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE | CHECKED, 0); - a->input->shouldForceAdaptation = oldShouldForce; a->mesh->destroyTag(lengthTag); double t1 = pcu::Time(); print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); diff --git a/ma/maCoarsen.h b/ma/maCoarsen.h index 8af51122c..2e4283c77 100644 --- a/ma/maCoarsen.h +++ b/ma/maCoarsen.h @@ -14,10 +14,9 @@ namespace ma { class Adapt; -bool coarsenMultiple(Adapt* a, bool aggressive=false); -bool coarsen(Adapt* a, bool aggressive=false); +bool coarsenMultiple(Adapt* a); +bool coarsen(Adapt* a); bool coarsenLayer(Adapt* a); -bool coarsenAndPrint(Adapt* a); void checkAllEdgeCollapses(Adapt* a, int modelDimension); void findIndependentSet(Adapt* a); diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 42cf39d8e..de2d68430 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -47,7 +47,7 @@ void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); - ma::coarsenMultiple(a, true); + ma::coarsenMultiple(a); for (int i = 0; i < in->maximumIterations; ++i) { ma::refine(a); From 51db69934318f6cd352642f2f7a95a98f20a29ad Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 13:54:20 -0400 Subject: [PATCH 132/181] revert maShape --- ma/maShape.cc | 652 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 612 insertions(+), 40 deletions(-) diff --git a/ma/maShape.cc b/ma/maShape.cc index 40a8d52fe..dcd0eec17 100644 --- a/ma/maShape.cc +++ b/ma/maShape.cc @@ -12,7 +12,6 @@ #include "maSize.h" #include "maAdapt.h" #include "maSnap.h" -#include "maSnapper.h" #include "maOperator.h" #include "maEdgeSwap.h" #include "maDoubleSplitCollapse.h" @@ -26,6 +25,100 @@ namespace ma { +/* projects vertex 3 onto the plane + of the bottom triangle and returns + the zone in which it lands as a bit code. + Each bit indicates whether the area coordinate + of that vertex is positive. +*/ + +int getSliverCode( + Adapt* a, + Entity* tet) +{ + SizeField* sf = a->sizeField; + Mesh* m = a->mesh; + Matrix J,Q; + apf::MeshElement* me = apf::createMeshElement(m,tet); + Vector center(.25,.25,.25); + apf::getJacobian(me,center,J); + sf->getTransform(me,center,Q); + J = J*Q; //Jacobian in metric space + apf::destroyMeshElement(me); + int code = 0; + // check first face + Entity* fs[4]; + m->getDownward(tet, 2, fs); + double f0Qual = a->shape->getQuality(fs[0]); + if ((f0Qual*f0Qual*f0Qual > a->input->goodQuality*a->input->goodQuality)) { + // if its okay, use it for projection + Vector v03 = J[2]; + J[2] = apf::cross(J[0],J[1]); //face normal towards v[3] + Vector projected = v03 - apf::project(v03,J[2]); //v[3] projected to face + Matrix inverseMap = apf::invert(apf::transpose(J)); + Vector basisPoint = inverseMap * projected; + Vector areaPoint(1-basisPoint[0]-basisPoint[1], + basisPoint[0], + basisPoint[1]); + for (int i=0; i < 3; ++i) + if (areaPoint[i] > 0) + code |= (1< -0.10 && areaPoint[i] < 0.10) + code |= ((1< 0) + code |= ((1< -0.20 && areaPoint[i] < 0.20) + code |= ((1<> 6) & 1) + return table2d[(code >> 7) & 3][(code >> 9) & 3]; + else + return table[code & 7][(code >> 3) & 7]; +} + struct IsBadQuality : public Predicate { IsBadQuality(Adapt* a_):a(a_) {} @@ -75,6 +168,459 @@ double getMinQuality(Adapt* a) return m->getPCU()->Min(minqual); } +class ShortEdgeFixer : public Operator +{ + public: + ShortEdgeFixer(Adapt* a): + remover(a) + { + adapter = a; + mesh = a->mesh; + sizeField = a->sizeField; + shortEdgeRatio = a->input->maximumEdgeRatio; + nr = nf = 0; + element = 0; + } + virtual ~ShortEdgeFixer() + { + } + virtual int getTargetDimension() {return mesh->getDimension();} + virtual bool shouldApply(Entity* e) + { + if ( ! getFlag(adapter,e,BAD_QUALITY)) + return false; + element = e; + Downward edges; + int n = mesh->getDownward(element,1,edges); + double l[6] = {}; + for (int i=0; i < n; ++i) + l[i] = sizeField->measure(edges[i]); + double maxLength; + double minLength; + Entity* shortEdge; + maxLength = minLength = l[0]; + shortEdge = edges[0]; + for (int i=1; i < n; ++i) + { + if (l[i] > maxLength) maxLength = l[i]; + if (l[i] < minLength) + { + minLength = l[i]; + shortEdge = edges[i]; + } + } + if ((maxLength/minLength) < shortEdgeRatio) + { + clearFlag(adapter,element,BAD_QUALITY); + return false; + } + remover.setEdge(shortEdge); + return true; + } + virtual bool requestLocality(apf::CavityOp* o) + { + return remover.requestLocality(o); + } + virtual void apply() + { + if (remover.run()) + ++nr; + else + { + ++nf; + clearFlag(adapter,element,BAD_QUALITY); + } + } + private: + Adapt* adapter; + Mesh* mesh; + Entity* element; + SizeField* sizeField; + ShortEdgeRemover remover; + double shortEdgeRatio; + public: + int nr; + int nf; +}; + +class TetFixerBase +{ + public: + virtual void setTet(Entity** v) = 0; + virtual bool requestLocality(apf::CavityOp* o) = 0; + virtual bool run() = 0; +}; + +class FixBySwap : public TetFixerBase +{ + public: + FixBySwap(Adapt* a): + adapter(a) + { + mesh = a->mesh; + edgeSwap = makeEdgeSwap(a); + nes = nf = numToTry = 0; + edges[0] = 0; + edges[1] = 0; + edges[2] = 0; + } + ~FixBySwap() + { + delete edgeSwap; + } + virtual void setTet(Entity** v) + { + Entity* tet = apf::findElement(mesh, apf::Mesh::TET, v); + PCU_ALWAYS_ASSERT(tet); + match = matchSliver(adapter, tet); + Entity* dv[4]; + mesh->getDownward(tet, 0, dv); + Entity* rv[4]; + rotateTet(dv,match.rotation,rv); + + enum { EDGE_EDGE, FACE_VERT }; + if (match.code_index==EDGE_EDGE) { + Entity* ev[2]; + ev[0] = rv[0]; ev[1] = rv[2]; + edges[0] = findUpward(mesh, apf::Mesh::EDGE, ev); + ev[0] = rv[1]; ev[1] = rv[3]; + edges[1] = findUpward(mesh, apf::Mesh::EDGE, ev); + numToTry = 2; + } + else + { + PCU_ALWAYS_ASSERT(match.code_index==FACE_VERT); + apf::findTriDown(mesh,rv,edges); + numToTry = 3; + } + } + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(edges, numToTry); + } + virtual bool run() + { + for (int i=0; i < numToTry; ++i) + if (edgeSwap->run(edges[i])) + { + ++nes; + return true; + } + ++nf; + return false; + } + private: + Adapt* adapter; + Mesh* mesh; + Entity* edges[3]; + EdgeSwap* edgeSwap; + CodeMatch match; + int numToTry; + int nes; + int nf; +}; + +class EdgeVertFixer : public TetFixerBase +{ +public: + EdgeVertFixer(Adapt* a): + singleSplitCollapse(a) + { + mesh = a->mesh; + edgeSwap = makeEdgeSwap(a); + nes = nssc = nf = 0; + edge = 0; + oppVert = 0; + } + ~EdgeVertFixer() + { + delete edgeSwap; + } + virtual void setTet(Entity** v) + { + /* In this template, the edge v[0]--v[1] and vert v[3] + are too close*/ + edge = apf::findElement(mesh, apf::Mesh::EDGE, v); + oppVert = v[3]; + verts[0] = v[0]; + verts[1] = v[1]; + verts[2] = v[3]; + } + virtual bool requestLocality(apf::CavityOp* o) + { + /* by requesting locality for all the verts we can be sure + * that all the desired entities for this operator are local */ + return o->requestLocality(verts,3); + } + virtual bool run() { + if (edgeSwap->run(edge)) { + ++nes; + return true; + } + if (singleSplitCollapse.run(edge, oppVert)) + { + ++nssc; + return true; + } + ++nf; + return false; + } +private: + Mesh* mesh; + Entity* verts[3]; + Entity *edge, *oppVert; + SingleSplitCollapse singleSplitCollapse; + EdgeSwap* edgeSwap; +public: + int nes; /* number of edge swaps done */ + int nssc; /* number of SSCs done */ + int nf; /* number of failures */ +}; + +class FaceVertFixer : public TetFixerBase +{ + public: + FaceVertFixer(Adapt* a): + faceSplitCollapse(a) + { + mesh = a->mesh; + edgeSwap = makeEdgeSwap(a); + nes = nf = nfsc = 0; + edges[0] = 0; + edges[1] = 0; + edges[2] = 0; + verts[0] = 0; + verts[1] = 0; + verts[2] = 0; + verts[3] = 0; + face = 0; + oppVert = 0; + tet = 0; + } + ~FaceVertFixer() + { + delete edgeSwap; + } + virtual void setTet(Entity** v) + { +/* in this template, the bottom face and v[3] + are too close, the key edges are those that bound + face v(0,1,2) */ + apf::findTriDown(mesh,v,edges); + tet = apf::findElement(mesh, apf::Mesh::TET, v); + oppVert = v[3]; + verts[0] = v[0]; + verts[1] = v[1]; + verts[2] = v[2]; + verts[3] = v[3]; + } + virtual bool requestLocality(apf::CavityOp* o) + { + /* by requesting locality for all the verts we can be sure + * that all the desired entities for this operator are local */ + return o->requestLocality(verts,4); + } + virtual bool run() + { + for (int i=0; i < 3; ++i) + if (edgeSwap->run(edges[i])) + { + ++nes; + return true; + } + face = apf::findUpward(mesh, apf::Mesh::TRIANGLE, edges); + if (faceSplitCollapse.run(face, tet)) + { + ++nfsc; + return true; + } + ++nf; + return false; + } + private: + Mesh* mesh; + Entity* edges[3]; + Entity* verts[4]; + Entity *face, *oppVert; + Entity* tet; + FaceSplitCollapse faceSplitCollapse; + EdgeSwap* edgeSwap; + public: + int nes; /* number of edge swaps done */ + int nfsc; /* number of FSCs done */ + int nf; /* number of failures */ +}; + +class EdgeEdgeFixer : public TetFixerBase +{ + public: + EdgeEdgeFixer(Adapt* a): + doubleSplitCollapse(a) + { + mesh = a->mesh; + edgeSwap = makeEdgeSwap(a); + nes = ndsc = nf = 0; + sf = a->sizeField; + edges[0] = 0; + edges[1] = 0; + } + ~EdgeEdgeFixer() + { + delete edgeSwap; + } + virtual void setTet(Entity** v) + { +/* in this template, the v[0]-v[2] amd v[1]-v[3] + edges are too close. */ + Entity* ev[2]; + ev[0] = v[0]; ev[1] = v[2]; + edges[0] = findUpward(mesh, apf::Mesh::EDGE, ev); + ev[0] = v[1]; ev[1] = v[3]; + edges[1] = findUpward(mesh, apf::Mesh::EDGE, ev); + } + virtual bool requestLocality(apf::CavityOp* o) + { + return o->requestLocality(edges,2); + } + virtual bool run() + { + for (int i=0; i < 2; ++i) + if (edgeSwap->run(edges[i])) + { + ++nes; + return true; + } + if (doubleSplitCollapse.run(edges)) + { + ++ndsc; + return true; + } + ++nf; + return false; + } + private: + Mesh* mesh; + Entity* edges[2]; + EdgeSwap* edgeSwap; + DoubleSplitCollapse doubleSplitCollapse; + SizeField* sf; + public: + int nes; + int ndsc; + int nf; +}; + +class LargeAngleTetFixer : public Operator +{ + public: + LargeAngleTetFixer(Adapt* a): + edgeEdgeFixer(a), + edgeVertFixer(a), + faceVertFixer(a) + { + adapter = a; + mesh = a->mesh; + tet = 0; + fixer = 0; + } + virtual ~LargeAngleTetFixer() + { + } + virtual int getTargetDimension() {return 3;} + enum { EDGE_EDGE, FACE_VERT, EDGE_VERT, VERT_VERT }; + virtual bool shouldApply(Entity* e) + { + if ( ! getFlag(adapter,e,BAD_QUALITY)) + return false; + tet = e; + CodeMatch match = matchSliver(adapter,e); + if (match.code_index==EDGE_EDGE) { + fixer = &edgeEdgeFixer; + } else if (match.code_index==FACE_VERT) { + fixer = &faceVertFixer; + } else if (match.code_index==EDGE_VERT) { + fixer = &edgeVertFixer; + } else if (match.code_index==VERT_VERT) { + fixer = &faceVertFixer; + } + Entity* v[4]; + mesh->getDownward(e,0,v); + Entity* rv[4]; + rotateTet(v,match.rotation,rv); + fixer->setTet(rv); + return true; + } + virtual bool requestLocality(apf::CavityOp* o) + { + return fixer->requestLocality(o); + } + virtual void apply() + { + if ( ! fixer->run()) + clearFlag(adapter,tet,BAD_QUALITY); + } + private: + Adapt* adapter; + Mesh* mesh; + Entity* tet; + TetFixerBase* fixer; + public: + EdgeEdgeFixer edgeEdgeFixer; + EdgeVertFixer edgeVertFixer; + FaceVertFixer faceVertFixer; +}; + +class LargeAngleTetAligner : public Operator +{ + public: + LargeAngleTetAligner(Adapt* a): + fixer(a) + { + adapter = a; + mesh = a->mesh; + tet = 0; + } + virtual ~LargeAngleTetAligner() + { + } + virtual int getTargetDimension() {return 3;} + virtual bool shouldApply(Entity* e) + { + if ( ! getFlag(adapter,e,BAD_QUALITY)) + return false; + tet = e; + /* PCU_ALWAYS_ASSERT(mesh->getType(e) == apf::Mesh::TET); */ + enum { EDGE_EDGE, FACE_VERT }; + CodeMatch match = matchSliver(adapter,e); + if (match.code_index==EDGE_EDGE) { + clearFlag(adapter,tet,BAD_QUALITY); + return false; + } + /* else */ + /* { PCU_ALWAYS_ASSERT(match.code_index==FACE_VERT); */ + /* fixer = &faceVertFixer; */ + /* } */ + Entity* v[4]; + mesh->getDownward(e,0,v); + fixer.setTet(v); + return true; + } + virtual bool requestLocality(apf::CavityOp* o) + { + return fixer.requestLocality(o); + } + virtual void apply() + { + if ( ! fixer.run()) + clearFlag(adapter,tet,BAD_QUALITY); + } + private: + Adapt* adapter; + Mesh* mesh; + Entity* tet; + FixBySwap fixer; +}; + class LargeAngleTriFixer : public Operator { public: @@ -191,45 +737,19 @@ class QualityImprover2D : public Operator int nf; }; +static double fixShortEdgeElements(Adapt* a) +{ + double t0 = pcu::Time(); + ShortEdgeFixer fixer(a); + applyOperator(a,&fixer); + double t1 = pcu::Time(); + return t1 - t0; +} + static void fixLargeAngleTets(Adapt* a) { - FaceSplitCollapse faceSplitCollapse(a); - SingleSplitCollapse splitCollapse(a); - DoubleSplitCollapse doubleSplitCollapse(a); - EdgeSwap* edgeSwap = makeEdgeSwap(a); - - Entity* tet; - Iterator* it = a->mesh->begin(3); - while ((tet = a->mesh->iterate(it))) { - if (!getFlag(a, tet, BAD_QUALITY)) continue; - clearFlag(a, tet, BAD_QUALITY); - Entity* verts[4]; - a->mesh->getDownward(tet, 0, verts); - Entity* vert = verts[0]; - Entity* face = getTetFaceOppositeVert(a->mesh, tet, vert); - Entity* ents[4]; - double area[4]; - int bit = getTetStats(a, vert, face, tet, ents, area); - - // two large dihedral angles -> key problem: two mesh edges - if (bit==3 || bit==5 || bit==6) { - if (edgeSwap->run(ents[0])) continue; - if (edgeSwap->run(ents[1])) continue; - if (splitCollapse.run(ents[0], vert)) continue; - if (splitCollapse.run(ents[1], vert)) continue; - if (doubleSplitCollapse.run(ents)) continue; - } - // three large dihedral angles -> key entity: a mesh face - else { - Entity* edges[3]; - a->mesh->getDownward(ents[0], 1, edges); - if (edgeSwap->run(edges[0])) continue; - if (edgeSwap->run(edges[1])) continue; - if (edgeSwap->run(edges[2])) continue; - //TODO: RUN FACE SWAP HERE - if (faceSplitCollapse.run(ents[0], tet)) continue; - } - } + LargeAngleTetFixer fixer(a); + applyOperator(a,&fixer); } static void fixLargeAngleTris(Adapt* a) @@ -238,6 +758,18 @@ static void fixLargeAngleTris(Adapt* a) applyOperator(a,&fixer); } +static void alignLargeAngleTets(Adapt* a) +{ + LargeAngleTetAligner aligner(a); + applyOperator(a,&aligner); +} + +static void alignLargeAngleTris(Adapt* a) +{ + LargeAngleTriFixer aligner(a); + applyOperator(a,&aligner); +} + static void improveQualities2D(Adapt* a) { QualityImprover2D improver(a); @@ -255,6 +787,14 @@ static double fixLargeAngles(Adapt* a) return t1 - t0; } +static void alignLargeAngles(Adapt* a) +{ + if (a->mesh->getDimension()==3) + alignLargeAngleTets(a); + else + alignLargeAngleTris(a); +} + double improveQualities(Adapt* a) { double t0 = pcu::Time(); @@ -272,7 +812,6 @@ void fixElementShapes(Adapt* a) return; double t0 = pcu::Time(); int count = markBadQuality(a); - print(a->mesh->getPCU(), "--iter %d of shape correction loop: #bad elements %d", 0, count); int originalCount = count; int prev_count; double time; @@ -281,6 +820,7 @@ void fixElementShapes(Adapt* a) if ( ! count) break; prev_count = count; + print(a->mesh->getPCU(), "--iter %d of shape correction loop: #bad elements %d", iter, count); time = fixLargeAngles(a); /* We need to snap the new verts as soon as they are * created (to avoid future problems). At the moment @@ -290,10 +830,16 @@ void fixElementShapes(Adapt* a) if (a->mesh->getDimension() == 3) snap(a); count = markBadQuality(a); + print(a->mesh->getPCU(), "--fixLargeAngles in %f seconds: #bad elements %d", time,count); + time = fixShortEdgeElements(a); + count = markBadQuality(a); + print(a->mesh->getPCU(), "--fixShortEdgeElements in %f seconds: #bad elements %d", time,count); if (count >= prev_count) unMarkBadQuality(a); // to make sure markEntities does not complain! // balance the mesh to avoid empty parts midBalance(a); + print(a->mesh->getPCU(), "--percent change in number of bad elements %f", + ((double) prev_count - (double) count) / (double) prev_count); iter++; } while(count < prev_count); double t1 = pcu::Time(); @@ -301,6 +847,32 @@ void fixElementShapes(Adapt* a) originalCount,count,t1-t0); } +void alignElements(Adapt* a) +{ + int max_iter = 5; + if ( ! a->input->shouldFixShape) + return; + double t0 = pcu::Time(); + int count = markBadQuality(a); + int originalCount = count; + int prev_count; + int i = 0; + do { + if ( ! count) + break; + prev_count = count; + alignLargeAngles(a); + count = markBadQuality(a); + ++i; + if (count >= prev_count || i >= max_iter) + unMarkBadQuality(a); + } while(count < prev_count && i < max_iter); + + double t1 = pcu::Time(); + print(a->mesh->getPCU(), "non-aligned elements down from %d to %d in %f seconds", + originalCount,count,t1-t0); +} + void printQuality(Adapt* a) { if ( ! a->input->shouldPrintQuality) @@ -309,4 +881,4 @@ void printQuality(Adapt* a) print(a->mesh->getPCU(), "worst element quality is %e", minqual); } -} +} \ No newline at end of file From cc0d27475c230551f73b92bf30c095758646e1d4 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 14:06:57 -0400 Subject: [PATCH 133/181] remove unused --- ma/maAdapt.h | 1 - ma/maCollapse.cc | 19 ------------------- ma/maCollapse.h | 1 - ma/maRefine.cc | 1 - ma/maRefine.h | 1 - 5 files changed, 23 deletions(-) diff --git a/ma/maAdapt.h b/ma/maAdapt.h index e4daa9246..0b7a0324d 100644 --- a/ma/maAdapt.h +++ b/ma/maAdapt.h @@ -11,7 +11,6 @@ #define MA_ADAPT_H #include "maInput.h" -#include namespace ma { diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index cf492249b..fb32eb6ce 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -80,25 +80,6 @@ bool Collapse::edgesGoodSize() { return true; } -bool Collapse::edgeGrewPastMaxLength() { - PCU_ALWAYS_ASSERT(elementsToKeep.size()); - PCU_ALWAYS_ASSERT(elementsToKeep.size() == newElements.size()); - size_t i=0; - APF_ITERATE(EntitySet,elementsToKeep,it) { - Entity* edgesBefore[6]; - adapt->mesh->getDownward(*it,1,edgesBefore); - Entity* edgesAfter[6]; - adapt->mesh->getDownward(newElements[i++],1,edgesAfter); - for (int j=0; j<6; j++) { - double sizeBefore = adapt->sizeField->measure(edgesBefore[j]); - double sizeAfter = adapt->sizeField->measure(edgesAfter[j]); - if (sizeAfter > sizeBefore && sizeAfter > MAXLENGTH) - return true; - } - } - return false; -} - bool Collapse::tryThisDirection(double qualityToBeat) { if (!tryThisDirectionNoCancel(qualityToBeat)) { diff --git a/ma/maCollapse.h b/ma/maCollapse.h index 096bdea8d..d9a449adf 100644 --- a/ma/maCollapse.h +++ b/ma/maCollapse.h @@ -42,7 +42,6 @@ class Collapse bool tryBothDirections(double qualityToBeat); void getOldElements(EntityArray& oldElements); bool edgesGoodSize(); - bool edgeGrewPastMaxLength(); double getOldQuality(); Adapt* adapt; Entity* edge; diff --git a/ma/maRefine.cc b/ma/maRefine.cc index 10dea7d95..915d8481a 100644 --- a/ma/maRefine.cc +++ b/ma/maRefine.cc @@ -19,7 +19,6 @@ #include "maLayer.h" #include #include -#include namespace ma { diff --git a/ma/maRefine.h b/ma/maRefine.h index 7553b9551..88efd8275 100644 --- a/ma/maRefine.h +++ b/ma/maRefine.h @@ -12,7 +12,6 @@ #include "maMesh.h" #include "maTables.h" -#include namespace ma { From a9c52a875db6a56321f61ef89edc502ec91405f3 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 15:03:39 -0400 Subject: [PATCH 134/181] fixed snap bug --- ma/maSnap.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index eecee363f..93f73e6e2 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -911,17 +911,18 @@ void snap(Adapt* a) Tag* snapTag = a->mesh->createDoubleTag("ma_snap", 3); preventMatchedCavityMods(a); int toSnap = tagVertsToSnap(a, snapTag); - if (toSnap == 0) return; - - Snapper snapper(a, snapTag, false); - snapTaggedVerts(a, snapTag, snapper); - snapLayer(a, snapTag); - - double t1 = pcu::Time(); - print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds", - toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); - if (a->hasLayer) - checkLayerShape(a->mesh, "after snapping"); + if (toSnap) + { + Snapper snapper(a, snapTag, false); + snapTaggedVerts(a, snapTag, snapper); + snapLayer(a, snapTag); + + double t1 = pcu::Time(); + print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds", + toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); + if (a->hasLayer) + checkLayerShape(a->mesh, "after snapping"); + } a->mesh->destroyTag(snapTag); } } From fcb8e0d2a3cfc51ca3f9e0a31b9d700d236b7466 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 15:06:30 -0400 Subject: [PATCH 135/181] removed unused test --- test/testing.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/testing.cmake b/test/testing.cmake index e3aca08b3..9f93a1d66 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -374,11 +374,6 @@ if(ENABLE_ZOLTAN) "${MESHES}/cube/cube.dmg" "${MESHES}/cube/pumi670/cube.smb" "0") - mpi_test(aniso_ma2 1 - ./aniso_ma_test - "${MESHES}/cube/cube.dmg" - "${MESHES}/cube/pumi670/cube.smb" - "1" "8") mpi_test(aniso_ma_serial_log_interpolation 1 ./aniso_ma_test "${MESHES}/cube/cube.dmg" @@ -716,7 +711,6 @@ mpi_test(construct_bottom_up 1 ./construct_bottom_up "${MDIR}/bottom_up_constructed_cube.smb" "${MDIR}/cube.dmg") -mpi_test(coarsen 1 ./coarsen) set(MDIR ${MESHES}/embeddedEdges) mpi_test(embedded_edges 1 ./embedded_edges From 1c1a0f96f321a30b4ffe54f9756bd02102cba049 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 16:05:08 -0400 Subject: [PATCH 136/181] end iterator --- ma/maCoarsen.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 9d2310208..05d0d45cd 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -408,6 +408,7 @@ std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) } } clearListFlag(a, shortEdgeVerts, CHECKED); + a->mesh->end(it); return shortEdgeVerts; } From 17628e83be449a577c97af4dbf26b9920385c062 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 17:30:12 -0400 Subject: [PATCH 137/181] split clps valid quality --- ma/maSnapper.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index a2229f3cd..892242f99 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -362,7 +362,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) numSwap++; return true; } - if (splitCollapse.run(longest, FPP->vert, 0)) { + if (splitCollapse.run(longest, FPP->vert, adapt->input->validQuality)) { numSplitCollapse++; return true; } @@ -379,11 +379,11 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) return true; } for (int i=0; i<2; i++) - if (splitCollapse.run(ents[i], FPP->vert, 0)) { + if (splitCollapse.run(ents[i], FPP->vert, adapt->input->validQuality)) { numSplitCollapse++; return true; } - if (doubleSplitCollapse.run(ents, 0)) { + if (doubleSplitCollapse.run(ents, adapt->input->validQuality)) { numSplitCollapse++; return true; } @@ -400,7 +400,7 @@ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) } } //TODO: RUN FACE SWAP HERE - if (splitCollapse.run(ents[1], FPP->vert, 0)) { + if (splitCollapse.run(ents[1], FPP->vert, adapt->input->validQuality)) { numSplitCollapse++; return true; } From e257e356854bb83058b7b851a4dba7045d2ba795 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 18:26:37 -0400 Subject: [PATCH 138/181] removed meshes --- pumi-meshes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumi-meshes b/pumi-meshes index 8d7deb32d..70977efb9 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit 8d7deb32d6543804738c9bbc19faefc24346a6b3 +Subproject commit 70977efb9c2375bef93d1d6dc7edcfe1759e0174 From a7f40eb0ee0e1440d0710605d8be4b91028ecf5b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 18:27:44 -0400 Subject: [PATCH 139/181] remove double cone --- pumi-meshes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumi-meshes b/pumi-meshes index 70977efb9..27415dd6d 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit 70977efb9c2375bef93d1d6dc7edcfe1759e0174 +Subproject commit 27415dd6d53fe644c1190b79ed95f46812768a60 From 44a7fe7b1b87ab7722c1972dcbf95d1d86155987 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 30 Jul 2025 19:02:10 -0400 Subject: [PATCH 140/181] revert aniso_ma_test --- test/CMakeLists.txt | 1 + test/aniso_adapt.cc | 28 +++++++++++++++++++++++ test/aniso_ma_test.cc | 52 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 test/aniso_adapt.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d2630398c..6812153b8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -174,6 +174,7 @@ test_exe_func(pumiLoadMesh pumiLoadMesh.cc) test_exe_func(xgc_split xgc_split.cc) test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) +test_exe_func(aniso_adapt aniso_adapt.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) test_exe_func(aniso_adapt_sim aniso_adapt_sim.cc) test_exe_func(torus_ma_test torus_ma_test.cc) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc new file mode 100644 index 000000000..fab5aca87 --- /dev/null +++ b/test/aniso_adapt.cc @@ -0,0 +1,28 @@ +#include "ma.h" +#include +#include +#include +#include +#include +#include +#include +#include "aniso_adapt.h" + +int main(int argc, char** argv) +{ + PCU_ALWAYS_ASSERT(argc==3); + const char* modelFile = argv[1]; + const char* meshFile = argv[2]; + pcu::Init(&argc,&argv); + { + pcu::PCU PCUObj; + lion_set_verbosity(1); + gmi_register_mesh(); + ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); + refineSnapTest(m, 0.5, 1); + m->destroyNative(); + apf::destroyMesh(m); + } + pcu::Finalize(); +} + diff --git a/test/aniso_ma_test.cc b/test/aniso_ma_test.cc index fab5aca87..e115d1c58 100644 --- a/test/aniso_ma_test.cc +++ b/test/aniso_ma_test.cc @@ -5,24 +5,68 @@ #include #include #include + #include -#include "aniso_adapt.h" + +class AnIso : public ma::AnisotropicFunction +{ + public: + AnIso(ma::Mesh* m) + { + mesh = m; + average = ma::getAverageEdgeLength(m); + ma::getBoundingBox(m,lower,upper); + } + virtual void getValue(ma::Entity* v, ma::Matrix& R, ma::Vector& H) + { + ma::Vector p = ma::getPosition(mesh,v); + double x = (p[0] - lower[0])/(upper[0] - lower[0]); + double sizeFactor = 2.; + if (x < 0.5) + sizeFactor = 3.; + ma::Vector h(average, average/sizeFactor, average/sizeFactor); + ma::Matrix r(1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0); + H = h; + R = r; + } + private: + ma::Mesh* mesh; + double average; + ma::Vector lower; + ma::Vector upper; +}; int main(int argc, char** argv) { - PCU_ALWAYS_ASSERT(argc==3); + PCU_ALWAYS_ASSERT(argc==4); const char* modelFile = argv[1]; const char* meshFile = argv[2]; + bool logInterpolation = atoi(argv[3]) > 0 ? true : false; pcu::Init(&argc,&argv); { pcu::PCU PCUObj; lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - refineSnapTest(m, 0.5, 1); + m->verify(); + apf::writeVtkFiles("aniso_before",m); + AnIso sf(m); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf, 0, logInterpolation)); + in->shouldRunPreZoltan = true; + in->shouldRunMidParma = true; + in->shouldRunPostParma = true; + in->shouldRefineLayer = true; + in->goodQuality = 0.2; + ma::adapt(in); + m->verify(); + if (logInterpolation) + apf::writeVtkFiles("aniso_log_interpolation_after",m); + else + apf::writeVtkFiles("aniso_after",m); m->destroyNative(); apf::destroyMesh(m); } pcu::Finalize(); } - From b0d8a7fbb56c620d26dabee1f7750cb496744a2a Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 31 Jul 2025 19:50:07 -0400 Subject: [PATCH 141/181] cube test --- test/aniso_adapt.cc | 3 +- test/aniso_adapt.h | 71 ++++++++++++++++++++++++++++++++++++++--- test/aniso_adapt_sim.cc | 2 +- test/testing.cmake | 4 +++ 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index fab5aca87..ae7d4daa7 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -19,7 +19,8 @@ int main(int argc, char** argv) lion_set_verbosity(1); gmi_register_mesh(); ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - refineSnapTest(m, 0.5, 1); + coarsenTest(m); + // refineSnapTest(m); m->destroyNative(); apf::destroyMesh(m); } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index de2d68430..8954c522d 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -39,22 +39,83 @@ class AnIso : public ma::AnisotropicFunction ma::Vector lower, upper; }; -void refineSnapTest(ma::Mesh* m, double sizeFactor1, double sizeFactor2) +void measureQuality(ma::Mesh* m, double& avgQuality, double& minQuality) +{ + int d = m->getDimension(); + apf::MeshEntity* elem; + apf::MeshIterator* elems = m->begin(d); + ma::IdentitySizeField I(m); + while ((elem = m->iterate(elems))) { + double q = ma::measureElementQuality(m, &I, elem); + avgQuality += q; + minQuality = fmin(minQuality, q); + } + m->end(elems); + avgQuality = avgQuality / m->count(d); +} + +int countEdges(ma::Mesh* m) +{ + return m->count(1); +} + +void coarsenTest(ma::Mesh* m) { m->verify(); - apf::writeVtkFiles("before_adapt",m); - AnIso sf(m, sizeFactor1, sizeFactor2); + apf::writeVtkFiles("before_coarsen_test",m); + AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); + double avgQualBefore, avgQualAfter, minQualBefore, minQualAfter; + measureQuality(m, avgQualBefore, minQualBefore); + double averageBefore = ma::getAverageEdgeLength(m); + int edgesBefore = countEdges(m); ma::coarsenMultiple(a); + measureQuality(m, avgQualAfter, minQualAfter); + double averageAfter = ma::getAverageEdgeLength(m); + int edgesAfter = countEdges(m); + + PCU_ALWAYS_ASSERT(edgesBefore > edgesAfter); + PCU_ALWAYS_ASSERT(averageBefore < averageAfter); + PCU_ALWAYS_ASSERT(minQualBefore <= minQualAfter); + // PCU_ALWAYS_ASSERT(avgQualBefore <= avgQualAfter); + + + //TODO: Check that force coarsen again doesn't result in any changes + m->verify(); + apf::printStats(m); + apf::writeVtkFiles("after_coarsen_test",m); + delete a; + // cleanup input object and associated sizefield and solutiontransfer objects + if (in->ownsSizeField) + delete in->sizeField; + if (in->ownsSolutionTransfer) + delete in->solutionTransfer; + delete in; +} + +void refineSnapTest(ma::Mesh* m) +{ + m->verify(); + apf::writeVtkFiles("before_adapt",m); + AnIso sf(m, 2, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + ma::Adapt* a = new ma::Adapt(in); + int edgesBefore = countEdges(m); + double averageBefore = ma::getAverageEdgeLength(m); + for (int i = 0; i < in->maximumIterations; ++i) { ma::refine(a); ma::snap(a); - ma::coarsenMultiple(a); } - ma::fixElementShapes(a); + int edgesAfter = countEdges(m); + double averageAfter = ma::getAverageEdgeLength(m); + PCU_ALWAYS_ASSERT(edgesBefore < edgesAfter); + PCU_ALWAYS_ASSERT(averageBefore > averageAfter); + + m->verify(); apf::writeVtkFiles("after_adapt",m); } \ No newline at end of file diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index cfe91a37b..0c6e40b1b 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -56,7 +56,7 @@ int main(int argc, char* argv[]) { apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); //Adapt - refineSnapTest(m, 3, 1); + refineSnapTest(m); //Clean up m->destroyNative(); diff --git a/test/testing.cmake b/test/testing.cmake index 9f93a1d66..08f6ab20d 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -369,6 +369,10 @@ if(ENABLE_ZOLTAN) ./ma_test "${MDIR}/pipe.${GXT}" "pipe.smb") + mpi_test(adapt_cube 1 + ./aniso_adapt + "${MESHES}/cube/cube.dmg" + "${MESHES}/cube/pumi7k/cube.smb") mpi_test(aniso_ma_serial 1 ./aniso_ma_test "${MESHES}/cube/cube.dmg" From 2440d949b552b81fc370e65c68bdb86523ddaad8 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 31 Jul 2025 20:27:13 -0400 Subject: [PATCH 142/181] force coarsen test --- test/aniso_adapt.cc | 5 +--- test/aniso_adapt.h | 65 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index ae7d4daa7..141ce3791 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -18,11 +18,8 @@ int main(int argc, char** argv) pcu::PCU PCUObj; lion_set_verbosity(1); gmi_register_mesh(); - ma::Mesh* m = apf::loadMdsMesh(modelFile,meshFile,&PCUObj); - coarsenTest(m); + coarsenTest(modelFile,meshFile,&PCUObj); // refineSnapTest(m); - m->destroyNative(); - apf::destroyMesh(m); } pcu::Finalize(); } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 8954c522d..46a60574c 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -59,33 +59,61 @@ int countEdges(ma::Mesh* m) return m->count(1); } -void coarsenTest(ma::Mesh* m) +ma::Mesh* coarsenForced(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) { + ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); m->verify(); - apf::writeVtkFiles("before_coarsen_test",m); AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + in->shouldForceAdaptation = true; ma::Adapt* a = new ma::Adapt(in); double avgQualBefore, avgQualAfter, minQualBefore, minQualAfter; measureQuality(m, avgQualBefore, minQualBefore); double averageBefore = ma::getAverageEdgeLength(m); int edgesBefore = countEdges(m); + ma::coarsenMultiple(a); + measureQuality(m, avgQualAfter, minQualAfter); - double averageAfter = ma::getAverageEdgeLength(m); - int edgesAfter = countEdges(m); - PCU_ALWAYS_ASSERT(edgesBefore > edgesAfter); - PCU_ALWAYS_ASSERT(averageBefore < averageAfter); - PCU_ALWAYS_ASSERT(minQualBefore <= minQualAfter); - // PCU_ALWAYS_ASSERT(avgQualBefore <= avgQualAfter); + PCU_ALWAYS_ASSERT(edgesBefore > countEdges(m)); + PCU_ALWAYS_ASSERT(averageBefore < ma::getAverageEdgeLength(m)); + PCU_ALWAYS_ASSERT(minQualAfter >= 0); + + m->verify(); + delete a; + // cleanup input object and associated sizefield and solutiontransfer objects + if (in->ownsSizeField) + delete in->sizeField; + if (in->ownsSolutionTransfer) + delete in->solutionTransfer; + delete in; + return m; +} + +ma::Mesh* coarsenRegular(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +{ + ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); + m->verify(); + AnIso sf(m, .5, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + ma::Adapt* a = new ma::Adapt(in); + double avgQualBefore, avgQualAfter, minQualBefore, minQualAfter; + + measureQuality(m, avgQualBefore, minQualBefore); + double averageBefore = ma::getAverageEdgeLength(m); + int edgesBefore = countEdges(m); + ma::coarsenMultiple(a); + + measureQuality(m, avgQualAfter, minQualAfter); + + PCU_ALWAYS_ASSERT(edgesBefore > countEdges(m)); + PCU_ALWAYS_ASSERT(averageBefore < ma::getAverageEdgeLength(m)); + PCU_ALWAYS_ASSERT(fabs(minQualBefore - minQualAfter) < 0.001f || minQualBefore < minQualAfter); - //TODO: Check that force coarsen again doesn't result in any changes m->verify(); - apf::printStats(m); - apf::writeVtkFiles("after_coarsen_test",m); delete a; // cleanup input object and associated sizefield and solutiontransfer objects if (in->ownsSizeField) @@ -93,6 +121,21 @@ void coarsenTest(ma::Mesh* m) if (in->ownsSolutionTransfer) delete in->solutionTransfer; delete in; + return m; +} + +void coarsenTest(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +{ + ma::Mesh* mReg = coarsenRegular(modelfile, meshfile, PCUObj); + ma::Mesh* mForce = coarsenForced(modelfile, meshfile, PCUObj); + + PCU_ALWAYS_ASSERT(countEdges(mReg) > countEdges(mForce)); + PCU_ALWAYS_ASSERT(ma::getAverageEdgeLength(mReg) < ma::getAverageEdgeLength(mForce)); + + mReg->destroyNative(); + apf::destroyMesh(mReg); + mForce->destroyNative(); + apf::destroyMesh(mForce); } void refineSnapTest(ma::Mesh* m) From ae33ba52321bb6f760f5cf096933aabdb22c634b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 31 Jul 2025 23:05:30 -0400 Subject: [PATCH 143/181] snap test --- test/aniso_adapt.cc | 2 +- test/aniso_adapt.h | 45 ++++++++++++++++++++++++++++++++++------- test/aniso_adapt_sim.cc | 5 ++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index 141ce3791..0b3b00094 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -19,7 +19,7 @@ int main(int argc, char** argv) lion_set_verbosity(1); gmi_register_mesh(); coarsenTest(modelFile,meshFile,&PCUObj); - // refineSnapTest(m); + refineSnapTest(modelFile,meshFile,&PCUObj); } pcu::Finalize(); } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 46a60574c..09cb9cee7 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -13,6 +13,7 @@ #include "maRefine.h" #include "maShape.h" #include "maSnap.h" +#include "apfGeometry.h" class AnIso : public ma::AnisotropicFunction { @@ -138,10 +139,35 @@ void coarsenTest(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) apf::destroyMesh(mForce); } -void refineSnapTest(ma::Mesh* m) +bool allVertsOnModel(ma::Adapt* a) { + if (!a->input->shouldSnap) + return true; + ma::Mesh* m = a->mesh; + int dim = m->getDimension(); + ma::Iterator* it = m->begin(0); + ma::Entity* vert; + while ((vert = m->iterate(it))) { + int md = m->getModelType(m->toModel(vert)); + if (dim == 3 && md == 3) + continue; + ma::Vector position = ma::getPosition(m, vert); + ma::Model* g = m->toModel(vert); + ma::Vector target; + ma::Vector closest; + m->getClosestPoint(g, position, target, closest); + (void) target; + if (!apf::areClose(position, closest, 1e-12)) + return false; + } + m->end(it); + return true; +} + +void refineSnapTest(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +{ + ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); m->verify(); - apf::writeVtkFiles("before_adapt",m); AnIso sf(m, 2, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); @@ -153,12 +179,17 @@ void refineSnapTest(ma::Mesh* m) ma::refine(a); ma::snap(a); } - int edgesAfter = countEdges(m); - double averageAfter = ma::getAverageEdgeLength(m); - PCU_ALWAYS_ASSERT(edgesBefore < edgesAfter); - PCU_ALWAYS_ASSERT(averageBefore > averageAfter); + PCU_ALWAYS_ASSERT(edgesBefore < countEdges(m)); + PCU_ALWAYS_ASSERT(averageBefore > ma::getAverageEdgeLength(m)); + PCU_ALWAYS_ASSERT(allVertsOnModel(a)); m->verify(); - apf::writeVtkFiles("after_adapt",m); + delete a; + // cleanup input object and associated sizefield and solutiontransfer objects + if (in->ownsSizeField) + delete in->sizeField; + if (in->ownsSolutionTransfer) + delete in->solutionTransfer; + delete in; } \ No newline at end of file diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 0c6e40b1b..2921e9c95 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -56,7 +56,10 @@ int main(int argc, char* argv[]) { apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); //Adapt - refineSnapTest(m); + m->verify(); + AnIso sf(m, 3, 1); + ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); + adapt(in); //Clean up m->destroyNative(); From daae4be32efc3d22880fc87bacf76ff95893a0ed Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 1 Aug 2025 17:19:30 -0400 Subject: [PATCH 144/181] fixed layer snapping error --- ma/maSnap.cc | 2 ++ ma/maSnapper.cc | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 93f73e6e2..ede269847 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -772,6 +772,8 @@ class SnapAll : public Operator { if ( ! getFlag(adapter, e, SNAP)) return false; + if (getFlag(adapter, e, LAYER)) + return false; vert = e; snapper->setVert(e); return true; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 892242f99..072c81d01 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -585,12 +585,18 @@ static FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up return FPP; } -static void getInvalidTets(Mesh* mesh, Upward& adjacentElements, apf::Up& invalid) +static void getInvalidTets(Adapt* a, Upward& adjacentElements, apf::Up& invalid) { invalid.n = 0; Vector v[4]; for (size_t i = 0; i < adjacentElements.getSize(); ++i) { - ma::getVertPoints(mesh,adjacentElements[i],v); + /* for now, when snapping a vertex on the boundary + layer, ignore the quality of layer elements. + not only do we not have metrics for this, but the + algorithm that moves curves would need to change */ + if (getFlag(a, adjacentElements[i], LAYER)) + continue; + ma::getVertPoints(a->mesh,adjacentElements[i],v); if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) invalid.e[invalid.n++] = adjacentElements[i]; } @@ -606,7 +612,7 @@ static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& i Upward adjacentElements; mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); mesh->setPoint(vertex, 0, target); - getInvalidTets(mesh, adjacentElements, invalid); + getInvalidTets(adapt, adjacentElements, invalid); if (invalid.n == 0) return true; mesh->setPoint(vertex, 0, prev); return false; @@ -624,7 +630,6 @@ bool Snapper::run() { apf::Up invalid; bool success = tryReposition(adapt, vert, snapTag, invalid); - if (success) { numSnapped++; mesh->removeTag(vert,snapTag); @@ -633,7 +638,6 @@ bool Snapper::run() } FirstProblemPlane* FPP = getFPP(adapt, vert, snapTag, invalid); - if (!success) success = tryCollapseToVertex(FPP); if (!success) success = tryReduceCommonEdges(FPP); if (!success) success = tryCollapseTetEdges(FPP); From f127dadbd4b1f669d7833f7800beb98fa7b3dc3f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 1 Aug 2025 18:42:10 -0400 Subject: [PATCH 145/181] adapt_cap --- test/CMakeLists.txt | 3 +- test/aniso_adapt_cap.cc | 146 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 test/aniso_adapt_cap.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6812153b8..59ed44c4a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -176,7 +176,6 @@ test_exe_func(ma_insphere ma_insphere.cc) test_exe_func(ma_test ma_test.cc) test_exe_func(aniso_adapt aniso_adapt.cc) test_exe_func(aniso_ma_test aniso_ma_test.cc) -test_exe_func(aniso_adapt_sim aniso_adapt_sim.cc) test_exe_func(torus_ma_test torus_ma_test.cc) test_exe_func(dg_ma_test dg_ma_test.cc) test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc) @@ -207,6 +206,7 @@ if(ENABLE_DSP) endif() if(ENABLE_SIMMETRIX) test_exe_func(curvetest curvetest.cc) + test_exe_func(aniso_adapt_sim aniso_adapt_sim.cc) test_exe_func(curve_to_bezier curve_to_bezier.cc) test_exe_func(make_all_cavities makeAllCavities.cc) test_exe_func(inClosureOf_test inClosureOf_test.cc) @@ -230,6 +230,7 @@ if(ENABLE_CAPSTONE) util_exe_func(capGeomTest capGeomTest.cc) util_exe_func(capCheckParam capCheckParam.cc) util_exe_func(capAdapt capAdapt.cc) + test_exe_func(aniso_adapt_cap aniso_adapt_cap.cc) target_link_libraries(capAdapt framework_meshing) endif() diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc new file mode 100644 index 000000000..4a3f10961 --- /dev/null +++ b/test/aniso_adapt_cap.cc @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "maAdapt.h" +#include "maCoarsen.h" +#include "maRefine.h" +#include "maSnap.h" +#include "lionPrint.h" +#include "aniso_adapt.h" + +#include "CapstoneModule.h" +#include "CreateMG_Framework_Core.h" +#include "CreateMG_Framework_Analysis.h" +#include "CreateMG_Framework_Application.h" +#include "CreateMG_Framework_Attributes.h" +#include "CreateMG_Framework_Core.h" +#include "CreateMG_Framework_Geometry.h" +#include "CreateMG_Framework_Mesh.h" + +using namespace CreateMG; +using namespace CreateMG::Attribution; +using namespace CreateMG::Mesh; +using namespace CreateMG::Geometry; + +int main(int argc, char** argv) +{ + MPI_Init(&argc, &argv); + { + pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); + + if (argc < 2) { + if(PCUObj.Self()==0) + std::cerr << "usage: " << argv[0] + << " <.cre file> or\n" + << " <.smb file> \n"; + return EXIT_FAILURE; + } + + + gmi_register_mesh(); + gmi_register_null(); + + const char* meshFile = argv[1]; + // load capstone mesh + // create an instance of the Capstone Module activating CREATE/CREATE/CREATE + // for the Geometry/Mesh/Attribution databases + /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ + const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD + const std::string mdbName("Mesh Database : Create"); + const std::string adbName("Attribution Database : Create"); + + CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); + + GeometryDatabaseInterface *g = cs.get_geometry(); + MeshDatabaseInterface *m = cs.get_mesh(); + AppContext *c = cs.get_context(); + + PCU_ALWAYS_ASSERT(g); + PCU_ALWAYS_ASSERT(m); + PCU_ALWAYS_ASSERT(c); + + v_string filenames; + filenames.push_back(meshFile); + + M_GModel gmodel = cs.load_files(filenames); + + int numbreps = 0; + MG_CALL(g->get_num_breps(numbreps)); + std::cout << "number of b reps is " << numbreps << std::endl; + if(numbreps == 0) + error(HERE, ERR_INVALID_INPUT, "Model is empty"); + + M_MModel mmodel; + // Pick the volume mesh model from associated mesh models to this geom model + std::vector mmodels; + MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); + for(std::size_t i = 0; i < mmodels.size(); ++i) + { + M_MModel ammodel = mmodels[i]; + std::size_t numregs = 0; + std::size_t numfaces = 0; + std::size_t numedges = 0; + std::size_t numverts = 0; + MG_API_CALL(m, set_current_model(ammodel)); + MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); + MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); + MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); + MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); + std::cout << "num regions is " << numregs << std::endl; + std::cout << "num faces is " << numfaces << std::endl; + std::cout << "num edges is " << numedges << std::endl; + std::cout << "num verts is " << numverts << std::endl; + std::cout << "-----------" << std::endl; + if(numregs > 0) + { + mmodel = ammodel; + break; + } + } + + /* SET THE ADJACENCIES */ + MG_API_CALL(m, set_adjacency_state(REGION2FACE| + REGION2EDGE| + REGION2VERTEX| + FACE2EDGE| + FACE2VERTEX)); + MG_API_CALL(m, set_reverse_states()); + MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); + MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); + MG_API_CALL(m, compute_adjacency()); + + gmi_cap_start(); + gmi_register_cap(); + + // convert the mesh to apf/mds mesh + + apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); + lion_set_verbosity(1); + + //Adapt + // refineSnapTest(mesh, 2, 1); + + gmi_cap_stop(); + } + MPI_Finalize(); +} \ No newline at end of file From e04178f8b4169e3288e0b25dc0aecde4142bb2a9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 1 Aug 2025 20:53:14 -0400 Subject: [PATCH 146/181] sim_test --- pumi-meshes | 2 +- test/aniso_adapt.cc | 13 +++++++++++-- test/aniso_adapt.h | 35 ++++++++++++++++++----------------- test/aniso_adapt_sim.cc | 38 ++++++++++++++++++++------------------ test/testing.cmake | 5 +++++ 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/pumi-meshes b/pumi-meshes index 27415dd6d..aa88a43c3 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit 27415dd6d53fe644c1190b79ed95f46812768a60 +Subproject commit aa88a43c3a51f06b1b1060a3d4196a7509d236b2 diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index 0b3b00094..cc1ef8365 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -8,6 +8,11 @@ #include #include "aniso_adapt.h" +ma::Mesh* createMesh(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +{ + return apf::loadMdsMesh(modelfile,meshfile,PCUObj); +} + int main(int argc, char** argv) { PCU_ALWAYS_ASSERT(argc==3); @@ -18,8 +23,12 @@ int main(int argc, char** argv) pcu::PCU PCUObj; lion_set_verbosity(1); gmi_register_mesh(); - coarsenTest(modelFile,meshFile,&PCUObj); - refineSnapTest(modelFile,meshFile,&PCUObj); + + auto createMeshValues = [modelFile,meshFile,&PCUObj]() + { return createMesh(modelFile,meshFile,&PCUObj); }; + + coarsenTest(createMeshValues); + refineSnapTest(createMeshValues); } pcu::Finalize(); } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 09cb9cee7..4a02a7e44 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -14,6 +14,7 @@ #include "maShape.h" #include "maSnap.h" #include "apfGeometry.h" +#include class AnIso : public ma::AnisotropicFunction { @@ -60,9 +61,9 @@ int countEdges(ma::Mesh* m) return m->count(1); } -ma::Mesh* coarsenForced(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +ma::Mesh* coarsenForced(const std::function& createMesh) { - ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); + ma::Mesh* m = createMesh(); m->verify(); AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); @@ -93,9 +94,9 @@ ma::Mesh* coarsenForced(const char* modelfile, const char* meshfile, pcu::PCU *P return m; } -ma::Mesh* coarsenRegular(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +ma::Mesh* coarsenRegular(const std::function& createMesh) { - ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); + ma::Mesh* m = createMesh(); m->verify(); AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); @@ -125,10 +126,10 @@ ma::Mesh* coarsenRegular(const char* modelfile, const char* meshfile, pcu::PCU * return m; } -void coarsenTest(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +void coarsenTest(const std::function& createMesh) { - ma::Mesh* mReg = coarsenRegular(modelfile, meshfile, PCUObj); - ma::Mesh* mForce = coarsenForced(modelfile, meshfile, PCUObj); + ma::Mesh* mReg = coarsenRegular(createMesh); + ma::Mesh* mForce = coarsenForced(createMesh); PCU_ALWAYS_ASSERT(countEdges(mReg) > countEdges(mForce)); PCU_ALWAYS_ASSERT(ma::getAverageEdgeLength(mReg) < ma::getAverageEdgeLength(mForce)); @@ -151,24 +152,24 @@ bool allVertsOnModel(ma::Adapt* a) int md = m->getModelType(m->toModel(vert)); if (dim == 3 && md == 3) continue; + ma::Vector modelPoint, param; + m->getPoint(vert,0,modelPoint); + m->getParam(vert,param); + ma::Model* model = m->toModel(vert); + m->snapToModel(model,param,modelPoint); ma::Vector position = ma::getPosition(m, vert); - ma::Model* g = m->toModel(vert); - ma::Vector target; - ma::Vector closest; - m->getClosestPoint(g, position, target, closest); - (void) target; - if (!apf::areClose(position, closest, 1e-12)) - return false; + if (apf::areClose(modelPoint, position, 1e-12)) + continue; } m->end(it); return true; } -void refineSnapTest(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) +void refineSnapTest(const std::function& createMesh) { - ma::Mesh* m = apf::loadMdsMesh(modelfile,meshfile,PCUObj); + ma::Mesh* m = createMesh(); m->verify(); - AnIso sf(m, 2, 1); + AnIso sf(m, 3, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); ma::Adapt* a = new ma::Adapt(in); int edgesBefore = countEdges(m); diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 2921e9c95..4c50e4dca 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -23,15 +23,29 @@ #include "SimAdvMeshing.h" #include "SimMeshTools.h" -int main(int argc, char* argv[]) { +ma::Mesh* createMesh(const char* nativefile, const char* smdfile, const char* smsfile, pcu::PCU* PCUObj) +{ + pProgress progress = Progress_new(); + Progress_setDefaultCallback(progress); + gmi_model* mdl_ref = gmi_sim_load(nativefile, smdfile); + pGModel model = gmi_export_sim(mdl_ref); + pParMesh mesh = PM_load(smsfile, model, progress); + ma::Mesh* mesh_ref = apf::createMesh(mesh, PCUObj); + apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); + return m; +} + +int main(int argc, char* argv[]) +{ if (argc != 4) { std::cerr << "Usage: " << argv[0] << " " << std::endl; return 1; } //Load Mesh - const char* modelFile = argv[1]; - const char* meshFile = argv[2]; + const char* nativefile = argv[1]; + const char* smdfile = argv[2]; + const char* smsfile = argv[3]; MPI_Init(&argc, &argv); pcu::PCU *PCUObj = new pcu::PCU(MPI_COMM_WORLD); lion_set_verbosity(1); @@ -46,24 +60,12 @@ int main(int argc, char* argv[]) { gmi_sim_start(); gmi_register_sim(); - pProgress progress = Progress_new(); - Progress_setDefaultCallback(progress); - gmi_model* mdl_ref = gmi_sim_load(argv[1], argv[2]); - pGModel model = gmi_export_sim(mdl_ref); - pParMesh mesh = PM_load(argv[3], model, progress); - ma::Mesh* mesh_ref = apf::createMesh(mesh, PCUObj); - apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); + auto createMeshValues = [nativefile, smdfile, smsfile, PCUObj]() + { return createMesh(nativefile, smdfile, smsfile, PCUObj); }; - //Adapt - m->verify(); - AnIso sf(m, 3, 1); - ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); - adapt(in); + refineSnapTest(createMeshValues); - //Clean up - m->destroyNative(); - apf::destroyMesh(m); delete PCUObj; MPI_Finalize(); } diff --git a/test/testing.cmake b/test/testing.cmake index 08f6ab20d..f1f7985b3 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -363,6 +363,11 @@ if(ENABLE_SIMMETRIX) "pipe_unif.smb" "pipe.smb") set_test_depends(TESTS snap_serial DEPENDS uniform_serial) + mpi_test(adapt_deformed_slab 1 + ./aniso_adapt_sim + "${MESHES}/deformedSlab/sim_model.x_t" + "${MESHES}/deformedSlab/sim_model.smd" + "${MESHES}/deformedSlab/sim_mesh.sms") endif() if(ENABLE_ZOLTAN) mpi_test(ma_serial 1 From 7b6a33fa162b989b07e0ef936ed679170443f867 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 2 Aug 2025 17:01:24 -0400 Subject: [PATCH 147/181] refine into coarsen --- test/aniso_adapt.cc | 3 +-- test/aniso_adapt.h | 46 +++++++++++++++++++++++------------------ test/aniso_adapt_sim.cc | 2 +- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index cc1ef8365..6e1eb334d 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -27,8 +27,7 @@ int main(int argc, char** argv) auto createMeshValues = [modelFile,meshFile,&PCUObj]() { return createMesh(modelFile,meshFile,&PCUObj); }; - coarsenTest(createMeshValues); - refineSnapTest(createMeshValues); + adaptTests(createMeshValues); } pcu::Finalize(); } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 4a02a7e44..706df1b19 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -61,9 +61,8 @@ int countEdges(ma::Mesh* m) return m->count(1); } -ma::Mesh* coarsenForced(const std::function& createMesh) +ma::Mesh* coarsenForced(ma::Mesh* m) { - ma::Mesh* m = createMesh(); m->verify(); AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); @@ -94,9 +93,8 @@ ma::Mesh* coarsenForced(const std::function& createMesh) return m; } -ma::Mesh* coarsenRegular(const std::function& createMesh) +ma::Mesh* coarsenRegular(ma::Mesh* m) { - ma::Mesh* m = createMesh(); m->verify(); AnIso sf(m, .5, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); @@ -126,20 +124,6 @@ ma::Mesh* coarsenRegular(const std::function& createMesh) return m; } -void coarsenTest(const std::function& createMesh) -{ - ma::Mesh* mReg = coarsenRegular(createMesh); - ma::Mesh* mForce = coarsenForced(createMesh); - - PCU_ALWAYS_ASSERT(countEdges(mReg) > countEdges(mForce)); - PCU_ALWAYS_ASSERT(ma::getAverageEdgeLength(mReg) < ma::getAverageEdgeLength(mForce)); - - mReg->destroyNative(); - apf::destroyMesh(mReg); - mForce->destroyNative(); - apf::destroyMesh(mForce); -} - bool allVertsOnModel(ma::Adapt* a) { if (!a->input->shouldSnap) @@ -165,9 +149,8 @@ bool allVertsOnModel(ma::Adapt* a) return true; } -void refineSnapTest(const std::function& createMesh) +ma::Mesh* refineSnapTest(ma::Mesh* m) { - ma::Mesh* m = createMesh(); m->verify(); AnIso sf(m, 3, 1); ma::Input* in = ma::makeAdvanced(ma::configure(m, &sf)); @@ -193,4 +176,27 @@ void refineSnapTest(const std::function& createMesh) if (in->ownsSolutionTransfer) delete in->solutionTransfer; delete in; + return m; +} + +void adaptTests(const std::function& createMesh) +{ + ma::Mesh* meshReg = createMesh(); + apf::writeVtkFiles("startMesh", meshReg); + refineSnapTest(meshReg); + apf::writeVtkFiles("afterRefine", meshReg); + + + coarsenRegular(meshReg); + apf::writeVtkFiles("afterCoarsen", meshReg); + ma::Mesh* meshForce = coarsenForced(refineSnapTest(createMesh())); + apf::writeVtkFiles("afterForcedCoarsen", meshForce); + + PCU_ALWAYS_ASSERT(countEdges(meshReg) > countEdges(meshForce)); + PCU_ALWAYS_ASSERT(ma::getAverageEdgeLength(meshReg) < ma::getAverageEdgeLength(meshForce)); + + meshReg->destroyNative(); + apf::destroyMesh(meshReg); + meshForce->destroyNative(); + apf::destroyMesh(meshForce); } \ No newline at end of file diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 4c50e4dca..32881f641 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) auto createMeshValues = [nativefile, smdfile, smsfile, PCUObj]() { return createMesh(nativefile, smdfile, smsfile, PCUObj); }; - refineSnapTest(createMeshValues); + adaptTests(createMeshValues); delete PCUObj; MPI_Finalize(); From 02edf078b2addd99010ec63b86e7ecf0b5b0a57f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 2 Aug 2025 17:13:37 -0400 Subject: [PATCH 148/181] aniso adapt cap tests --- test/aniso_adapt.h | 3 +- test/aniso_adapt_cap.cc | 91 +++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 706df1b19..d20272aff 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -183,12 +183,13 @@ void adaptTests(const std::function& createMesh) { ma::Mesh* meshReg = createMesh(); apf::writeVtkFiles("startMesh", meshReg); + refineSnapTest(meshReg); apf::writeVtkFiles("afterRefine", meshReg); - coarsenRegular(meshReg); apf::writeVtkFiles("afterCoarsen", meshReg); + ma::Mesh* meshForce = coarsenForced(refineSnapTest(createMesh())); apf::writeVtkFiles("afterForcedCoarsen", meshForce); diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 4a3f10961..7f73dfc7f 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -42,25 +42,8 @@ using namespace CreateMG::Attribution; using namespace CreateMG::Mesh; using namespace CreateMG::Geometry; -int main(int argc, char** argv) +ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) { - MPI_Init(&argc, &argv); - { - pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); - - if (argc < 2) { - if(PCUObj.Self()==0) - std::cerr << "usage: " << argv[0] - << " <.cre file> or\n" - << " <.smb file> \n"; - return EXIT_FAILURE; - } - - - gmi_register_mesh(); - gmi_register_null(); - - const char* meshFile = argv[1]; // load capstone mesh // create an instance of the Capstone Module activating CREATE/CREATE/CREATE // for the Geometry/Mesh/Attribution databases @@ -88,7 +71,7 @@ int main(int argc, char** argv) MG_CALL(g->get_num_breps(numbreps)); std::cout << "number of b reps is " << numbreps << std::endl; if(numbreps == 0) - error(HERE, ERR_INVALID_INPUT, "Model is empty"); + error(HERE, ERR_INVALID_INPUT, "Model is empty"); M_MModel mmodel; // Pick the volume mesh model from associated mesh models to this geom model @@ -96,26 +79,25 @@ int main(int argc, char** argv) MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); for(std::size_t i = 0; i < mmodels.size(); ++i) { - M_MModel ammodel = mmodels[i]; - std::size_t numregs = 0; - std::size_t numfaces = 0; - std::size_t numedges = 0; - std::size_t numverts = 0; - MG_API_CALL(m, set_current_model(ammodel)); - MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); - MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); - MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); - MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); - std::cout << "num regions is " << numregs << std::endl; - std::cout << "num faces is " << numfaces << std::endl; - std::cout << "num edges is " << numedges << std::endl; - std::cout << "num verts is " << numverts << std::endl; - std::cout << "-----------" << std::endl; - if(numregs > 0) - { - mmodel = ammodel; - break; - } + M_MModel ammodel = mmodels[i]; + std::size_t numregs = 0; + std::size_t numfaces = 0; + std::size_t numedges = 0; + std::size_t numverts = 0; + MG_API_CALL(m, set_current_model(ammodel)); + MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); + MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); + MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); + MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); + std::cout << "num regions is " << numregs << std::endl; + std::cout << "num faces is " << numfaces << std::endl; + std::cout << "num edges is " << numedges << std::endl; + std::cout << "num verts is " << numverts << std::endl; + std::cout << "-----------" << std::endl; + if(numregs > 0) { + mmodel = ammodel; + break; + } } /* SET THE ADJACENCIES */ @@ -129,16 +111,35 @@ int main(int argc, char** argv) MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); MG_API_CALL(m, compute_adjacency()); + apf::Mesh2* mesh = apf::createMesh(m,g,PCUObj); + return mesh; +} + +int main(int argc, char** argv) +{ + MPI_Init(&argc, &argv); + { + pcu::PCU PCUObj = pcu::PCU(MPI_COMM_WORLD); + + if (argc < 2) { + if(PCUObj.Self()==0) + std::cerr << "usage: " << argv[0] + << " <.cre file> or\n" + << " <.smb file> \n"; + return EXIT_FAILURE; + } + + gmi_register_mesh(); + gmi_register_null(); gmi_cap_start(); gmi_register_cap(); + lion_set_verbosity(1); - // convert the mesh to apf/mds mesh + const char* meshFile = argv[1]; + auto createMeshValues = [meshFile, &PCUObj]() + { return createMesh(meshFile, &PCUObj); }; - apf::Mesh2* mesh = apf::createMesh(m,g,&PCUObj); - lion_set_verbosity(1); - - //Adapt - // refineSnapTest(mesh, 2, 1); + adaptTests(createMeshValues); gmi_cap_stop(); } From a672a3ce41d3ba5aee1ebd19a0ec9b24ade5502d Mon Sep 17 00:00:00 2001 From: Angelyr Date: Sat, 2 Aug 2025 17:16:43 -0400 Subject: [PATCH 149/181] smaller cube test --- test/testing.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testing.cmake b/test/testing.cmake index f1f7985b3..69f915aef 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -377,7 +377,7 @@ if(ENABLE_ZOLTAN) mpi_test(adapt_cube 1 ./aniso_adapt "${MESHES}/cube/cube.dmg" - "${MESHES}/cube/pumi7k/cube.smb") + "${MESHES}/cube/pumi670/cube.smb") mpi_test(aniso_ma_serial 1 ./aniso_ma_test "${MESHES}/cube/cube.dmg" From c3c41aff3eda730affeecac3098fe987909f99b0 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 6 Aug 2025 17:54:06 -0400 Subject: [PATCH 150/181] capstone mesh --- test/aniso_adapt_cap.cc | 10 +++++----- test/testing.cmake | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 7f73dfc7f..090c203c9 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -52,11 +52,11 @@ ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) const std::string mdbName("Mesh Database : Create"); const std::string adbName("Attribution Database : Create"); - CapstoneModule cs("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); + CapstoneModule* cs = new CapstoneModule("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); - GeometryDatabaseInterface *g = cs.get_geometry(); - MeshDatabaseInterface *m = cs.get_mesh(); - AppContext *c = cs.get_context(); + GeometryDatabaseInterface *g = cs->get_geometry(); + MeshDatabaseInterface *m = cs->get_mesh(); + AppContext *c = cs->get_context(); PCU_ALWAYS_ASSERT(g); PCU_ALWAYS_ASSERT(m); @@ -65,7 +65,7 @@ ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) v_string filenames; filenames.push_back(meshFile); - M_GModel gmodel = cs.load_files(filenames); + M_GModel gmodel = cs->load_files(filenames); int numbreps = 0; MG_CALL(g->get_num_breps(numbreps)); diff --git a/test/testing.cmake b/test/testing.cmake index 69f915aef..faa5c768f 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -998,6 +998,7 @@ if(ENABLE_CAPSTONE) mpi_test(capVolCyl2 1 ./capVol -vg 4 ${MESHES}/cap/cyl_surf_only.cre) mpi_test(cap_inClosureOf 1 ./cap_inClosureOf ${MESHES}/cap/cube_surf_only.cre) mpi_test(cap_closestPoint 1 ./cap_closestPoint ${MESHES}/cap/cube_surf_only.cre) + mpi_test(adapt_curved_cube 1 ./aniso_adapt_cap "${MESHES}/curvedCube/cap_mesh.cre") if(HAVE_CAPSTONE_SIZINGMETRICTOOL) mpi_test(cap_smooth 1 ./cap_smooth) endif() From 762e86de093d14e4adc47eca97ea2772eef96cfe Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 6 Aug 2025 17:54:38 -0400 Subject: [PATCH 151/181] curved cube mesh --- pumi-meshes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumi-meshes b/pumi-meshes index aa88a43c3..e61d3c4ca 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit aa88a43c3a51f06b1b1060a3d4196a7509d236b2 +Subproject commit e61d3c4ca2246479e0f198fb4cce8e02ba98e695 From 1d006c0e4c577b52007f3b133f40c4f1218d1dbc Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 6 Aug 2025 23:18:11 -0400 Subject: [PATCH 152/181] update mesh dir --- pumi-meshes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumi-meshes b/pumi-meshes index e61d3c4ca..27dca7523 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit e61d3c4ca2246479e0f198fb4cce8e02ba98e695 +Subproject commit 27dca75239ed386594b7eb35d69c2d58fb28cfe3 From 3ffc85f2d521fa4329eadcaa49d50ae18f08718f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 6 Aug 2025 23:22:46 -0400 Subject: [PATCH 153/181] added meshes back in --- pumi-meshes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pumi-meshes b/pumi-meshes index 27dca7523..93d3dadf4 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit 27dca75239ed386594b7eb35d69c2d58fb28cfe3 +Subproject commit 93d3dadf4ecf73f6ec50bdf6f91a4d3ffd0f6f10 From b27f8b52dc10e391b004b1824c54b98684c7df87 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 14:34:50 -0400 Subject: [PATCH 154/181] updated capstone test --- test/aniso_adapt_cap.cc | 90 ++++------------------------------------- test/capVol.cc | 2 +- 2 files changed, 8 insertions(+), 84 deletions(-) diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 090c203c9..82f4628e7 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -28,91 +28,15 @@ #include "lionPrint.h" #include "aniso_adapt.h" -#include "CapstoneModule.h" -#include "CreateMG_Framework_Core.h" -#include "CreateMG_Framework_Analysis.h" -#include "CreateMG_Framework_Application.h" -#include "CreateMG_Framework_Attributes.h" -#include "CreateMG_Framework_Core.h" -#include "CreateMG_Framework_Geometry.h" -#include "CreateMG_Framework_Mesh.h" - -using namespace CreateMG; -using namespace CreateMG::Attribution; -using namespace CreateMG::Mesh; -using namespace CreateMG::Geometry; - ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) { - // load capstone mesh - // create an instance of the Capstone Module activating CREATE/CREATE/CREATE - // for the Geometry/Mesh/Attribution databases - /* const std::string gdbName("Geometry Database : Create");// Switch Create with SMLIB for CAD */ - const std::string gdbName("Geometry Database : SMLIB");// Switch Create with SMLIB for CAD - const std::string mdbName("Mesh Database : Create"); - const std::string adbName("Attribution Database : Create"); - - CapstoneModule* cs = new CapstoneModule("the_module", gdbName.c_str(), mdbName.c_str(), adbName.c_str()); - - GeometryDatabaseInterface *g = cs->get_geometry(); - MeshDatabaseInterface *m = cs->get_mesh(); - AppContext *c = cs->get_context(); - - PCU_ALWAYS_ASSERT(g); - PCU_ALWAYS_ASSERT(m); - PCU_ALWAYS_ASSERT(c); - - v_string filenames; - filenames.push_back(meshFile); - - M_GModel gmodel = cs->load_files(filenames); - - int numbreps = 0; - MG_CALL(g->get_num_breps(numbreps)); - std::cout << "number of b reps is " << numbreps << std::endl; - if(numbreps == 0) - error(HERE, ERR_INVALID_INPUT, "Model is empty"); - - M_MModel mmodel; - // Pick the volume mesh model from associated mesh models to this geom model - std::vector mmodels; - MG_API_CALL(m, get_associated_mesh_models(gmodel, mmodels)); - for(std::size_t i = 0; i < mmodels.size(); ++i) - { - M_MModel ammodel = mmodels[i]; - std::size_t numregs = 0; - std::size_t numfaces = 0; - std::size_t numedges = 0; - std::size_t numverts = 0; - MG_API_CALL(m, set_current_model(ammodel)); - MG_API_CALL(m, get_num_topos(TOPO_REGION, numregs)); - MG_API_CALL(m, get_num_topos(TOPO_FACE, numfaces)); - MG_API_CALL(m, get_num_topos(TOPO_EDGE, numedges)); - MG_API_CALL(m, get_num_topos(TOPO_VERTEX, numverts)); - std::cout << "num regions is " << numregs << std::endl; - std::cout << "num faces is " << numfaces << std::endl; - std::cout << "num edges is " << numedges << std::endl; - std::cout << "num verts is " << numverts << std::endl; - std::cout << "-----------" << std::endl; - if(numregs > 0) { - mmodel = ammodel; - break; - } - } - - /* SET THE ADJACENCIES */ - MG_API_CALL(m, set_adjacency_state(REGION2FACE| - REGION2EDGE| - REGION2VERTEX| - FACE2EDGE| - FACE2VERTEX)); - MG_API_CALL(m, set_reverse_states()); - MG_API_CALL(m, set_adjacency_scope(TOPO_EDGE, SCOPE_FULL)); - MG_API_CALL(m, set_adjacency_scope(TOPO_FACE, SCOPE_FULL)); - MG_API_CALL(m, compute_adjacency()); - - apf::Mesh2* mesh = apf::createMesh(m,g,PCUObj); - return mesh; + gmi_model* model = gmi_load(meshFile); + ma::Mesh* apfCapMesh = apf::createCapMesh(model, PCUObj); + apf::disownCapModel(apfCapMesh); + ma::Mesh* apfMesh = apf::createMdsMesh(model, apfCapMesh, true); + apf::disownMdsModel(apfMesh); + apf::destroyMesh(apfCapMesh); + return apfMesh; } int main(int argc, char** argv) diff --git a/test/capVol.cc b/test/capVol.cc index a6d0fc897..a7ccc0beb 100644 --- a/test/capVol.cc +++ b/test/capVol.cc @@ -241,7 +241,7 @@ apf::Splitter* makeSplitter(Args::Partitioner ptnr, apf::Mesh2* mesh) { default: #if defined(PUMI_HAS_ZOLTAN) return apf::makeZoltanSplitter( - adaptMesh, apf::GRAPH, apf::PARTITION + mesh, apf::GRAPH, apf::PARTITION ); #elif defined(PUMI_HAS_METIS) return apf::makeMETISsplitter(mesh); From 18017d8c3cff012029d8774d2a781c67b51aaec6 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 14:51:03 -0400 Subject: [PATCH 155/181] fixed warnings --- ma/maCoarsen.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 05d0d45cd..1c9f4de8a 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -346,7 +346,7 @@ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdg itr = shortEdgeVerts.erase(itr); return false; } - for (int i=0; i < sorted.size(); i++) { + for (size_t i=0; i < sorted.size(); i++) { Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, sorted[i].edge, vertex); if (!tryCollapseEdge(a, sorted[i].edge, keepVertex, collapse, adjacent)) continue; flagIndependentSet(a, adjacent, checked); @@ -367,9 +367,9 @@ void clearListFlag(Adapt* a, std::list list, int flag) } //Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an independent set -bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& itr, bool& independentSetStarted, const int checked, apf::Up& adjacent) +bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& itr, bool& independentSetStarted, apf::Up& adjacent) { - int numItr=0; + size_t numItr=0; do { numItr++; if (itr == shortEdgeVerts.end()) itr = shortEdgeVerts.begin(); @@ -429,7 +429,7 @@ bool coarsenMultiple(Adapt* a) while (checked < shortEdgeVerts.size()) { apf::Up adjacent; - if (!getAdjIndependentSet(a, shortEdgeVerts, itr, independentSetStarted, checked, adjacent)) continue; + if (!getAdjIndependentSet(a, shortEdgeVerts, itr, independentSetStarted, adjacent)) continue; if (collapseShortest(a, collapse, shortEdgeVerts, itr, checked, adjacent, lengthTag)) { independentSetStarted=true; success++; @@ -438,7 +438,7 @@ bool coarsenMultiple(Adapt* a) ma::clearFlagFromDimension(a, NEED_NOT_COLLAPSE | CHECKED, 0); a->mesh->destroyTag(lengthTag); double t1 = pcu::Time(); - print(a->mesh->getPCU(), "coarsened %li edges in %f seconds", success, t1-t0); + print(a->mesh->getPCU(), "coarsened %d edges in %f seconds", success, t1-t0); return true; } From 48eb9e6cb27790724edc1d1f87483aaab9e99563 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 14:55:25 -0400 Subject: [PATCH 156/181] checked size_t --- ma/maCoarsen.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 1c9f4de8a..79913e56f 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -307,7 +307,7 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll } //Prevent adjacent vertices from collapsing to create indepedent set -void flagIndependentSet(Adapt* a, apf::Up& adjacent, int& checked) +void flagIndependentSet(Adapt* a, apf::Up& adjacent, size_t& checked) { for (int adj=0; adj < adjacent.n; adj++) { Entity* vertices[2]; @@ -331,7 +331,7 @@ struct EdgeLength } }; -bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, int& checked, apf::Up& adjacent, Tag* lengthTag) +bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, size_t& checked, apf::Up& adjacent, Tag* lengthTag) { Entity* vertex = *itr; std::vector sorted; @@ -423,7 +423,7 @@ bool coarsenMultiple(Adapt* a) Collapse collapse; collapse.Init(a); int success = 0; - int checked = 0; + size_t checked = 0; bool independentSetStarted = false; std::list::iterator itr = shortEdgeVerts.begin(); while (checked < shortEdgeVerts.size()) From 04f5fbc0d078e1664246f327237cfdf5ce10b3a9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 15:14:13 -0400 Subject: [PATCH 157/181] void m --- ma/maSnap.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index ede269847..352a57b83 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -36,6 +36,7 @@ static bool isCapstoneMesh(apf::Mesh* m) if (dynamic_cast(m)) return true; else return false; #else + (void)m; return false; #endif } From 9f2005dc17b4518edd338cdc45032f6ca8fd0ff9 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 15:29:50 -0400 Subject: [PATCH 158/181] fixed snapper warnings --- ma/maMatchedSnapper.cc | 7 ++--- ma/maMatchedSnapper.h | 3 +- ma/maSnap.cc | 12 ++++---- ma/maSnapper.cc | 62 ++---------------------------------------- ma/maSnapper.h | 2 +- 5 files changed, 14 insertions(+), 72 deletions(-) diff --git a/ma/maMatchedSnapper.cc b/ma/maMatchedSnapper.cc index c5e87feb1..311c571eb 100644 --- a/ma/maMatchedSnapper.cc +++ b/ma/maMatchedSnapper.cc @@ -16,11 +16,10 @@ namespace ma { -MatchedSnapper::MatchedSnapper(Adapt* a, Tag* st, bool is) +MatchedSnapper::MatchedSnapper(Adapt* a, Tag* st) { adapter = a; snapTag = st; - isSimple = is; sharing = apf::getSharing(a->mesh); vert = 0; } @@ -38,7 +37,7 @@ void MatchedSnapper::setVert(Entity* v) { snappers.setSize(0); snappers.setSize(1); - snappers[0] = new Snapper(adapter, snapTag, isSimple); + snappers[0] = new Snapper(adapter, snapTag); snappers[0]->setVert(v); vert = v; } @@ -63,7 +62,7 @@ void MatchedSnapper::setVerts() snappers.setSize(copies.getSize() + 1); for (unsigned i = 0; i < snappers.getSize(); i++) - snappers[i] = new Snapper(adapter, snapTag, isSimple); + snappers[i] = new Snapper(adapter, snapTag); snappers[0]->setVert(v); for (unsigned i = 0; i < copies.getSize(); i++) snappers[i+1]->setVert(copies[i].entity); diff --git a/ma/maMatchedSnapper.h b/ma/maMatchedSnapper.h index c8fdbd487..42a7c12ce 100644 --- a/ma/maMatchedSnapper.h +++ b/ma/maMatchedSnapper.h @@ -21,7 +21,7 @@ namespace ma { class MatchedSnapper { public: - MatchedSnapper(Adapt* a, Tag* st, bool is); + MatchedSnapper(Adapt* a, Tag* st); ~MatchedSnapper(); void setVert(Entity* v); bool requestLocality(apf::CavityOp* o); @@ -34,7 +34,6 @@ class MatchedSnapper Entity* vert; apf::DynamicArray snappers; apf::DynamicArray locations; - bool isSimple; apf::Sharing* sharing; }; diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 352a57b83..c848f605b 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -807,8 +807,8 @@ bool snapAllVerts(Adapt* a, Tag* t, Snapper& snapper) class SnapMatched : public Operator { public: - SnapMatched(Adapt* a, Tag* t, bool simple): - snapper(a, t, simple) + SnapMatched(Adapt* a, Tag* t): + snapper(a, t) { adapter = a; tag = t; @@ -847,9 +847,9 @@ class SnapMatched : public Operator MatchedSnapper snapper; }; -bool snapMatchedVerts(Adapt* a, Tag* t, bool isSimple, long& successCount) +bool snapMatchedVerts(Adapt* a, Tag* t, long& successCount) { - SnapMatched op(a, t, isSimple); + SnapMatched op(a, t); applyOperator(a, &op); successCount += a->mesh->getPCU()->Add(op.successCount); return a->mesh->getPCU()->Or(op.didAnything); @@ -893,7 +893,7 @@ long snapTaggedVerts(Adapt* a, Tag* tag, Snapper& snapper) if (tagged == prevTagged) break; prevTagged = tagged; if (a->mesh->hasMatching()) - snapped = snapMatchedVerts(a, tag, false, successCount); + snapped = snapMatchedVerts(a, tag, successCount); else snapped = snapAllVerts(a, tag, snapper); } @@ -916,7 +916,7 @@ void snap(Adapt* a) int toSnap = tagVertsToSnap(a, snapTag); if (toSnap) { - Snapper snapper(a, snapTag, false); + Snapper snapper(a, snapTag); snapTaggedVerts(a, snapTag, snapper); snapLayer(a, snapTag); diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 072c81d01..f783ee7a6 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -19,7 +19,7 @@ namespace ma { -Snapper::Snapper(Adapt* a, Tag* st, bool is) : splitCollapse(a), doubleSplitCollapse(a) +Snapper::Snapper(Adapt* a, Tag* st) : splitCollapse(a), doubleSplitCollapse(a) { adapt = a; mesh = a->mesh; @@ -61,62 +61,6 @@ bool Snapper::requestLocality(apf::CavityOp* o) return o->requestLocality(&ovs.e[0], ovs.n); } -static void computeNormals(Mesh* m, Upward& es, apf::NewArray& normals) -{ - if (m->getDimension() != 2) - return; - normals.allocate(es.getSize()); - for (size_t i = 0; i < es.getSize(); ++i) - normals[i] = getTriNormal(m, es[i]); -} - -static bool didInvert(Mesh* m, Vector& oldNormal, Entity* tri) -{ - return (oldNormal * getTriNormal(m, tri)) < 0; -} - -static void updateVertexParametricCoords( - Mesh* m, - Entity* vert, - Vector& newTarget) -{ - PCU_ALWAYS_ASSERT_VERBOSE(m->getType(vert) == apf::Mesh::VERTEX, - "expecting a vertex!"); - - // if vert is classified on a model vert or edge return - Model* g = m->toModel(vert); - if (m->getModelType(g) != 2) - return; - - // get the list of upward adj edges that are - // classified on the same model face as vert - apf::Up edges; - m->getUp(vert,edges); - apf::Up oes; - oes.n = edges.n; - int counter = 0; - for (int i = 0; i < edges.n; ++i) { - Model* h = m->toModel(edges.e[i]); - if (m->getModelType(h) == 3) - continue; - PCU_ALWAYS_ASSERT_VERBOSE(g == h, - "expecting the model to be the same for current edge and vert"); - oes.e[counter] = edges.e[i]; - counter++; - } - - Vector pBar(0., 0., 0.); - for (int i = 0; i < counter; i++) { - Vector pTmp; - transferParametricOnEdgeSplit(m, oes.e[i], 0.5, pTmp); - pBar += pTmp; - } - pBar = pBar / oes.n; - - m->snapToModel(m->toModel(vert), pBar, newTarget); - m->setParam(vert, pBar); -} - static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) { setFlag(a, ent, CHECKED); @@ -558,7 +502,7 @@ bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) BestCollapse best; - for (size_t i = 0; i < FPP->commEdges.n; ++i) { + for (int i = 0; i < FPP->commEdges.n; ++i) { Entity* edge = FPP->commEdges.e[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(mesh, edge, vert); Vector vFPPCoord = getPosition(mesh, vertexOnFPP); @@ -648,7 +592,7 @@ bool Snapper::run() mesh->removeTag(vert,snapTag); clearFlag(adapt, vert, SNAP); } - // if (!success && ++DEBUGFAILED == 1) printFPP(adapt, FPP); + if (!success && ++DEBUGFAILED == 1) printFPP(adapt, FPP); if (FPP) delete FPP; return success; diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 395f5e5f2..88034346b 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -37,7 +37,7 @@ class Snapper int numSwap = 0; int numSplitCollapse = 0; - Snapper(Adapt* a, Tag* st, bool is); + Snapper(Adapt* a, Tag* st); ~Snapper(); void setVert(Entity* v); Entity* getVert(); From 24561ab5001fcaaca528973399b4504f638e0382 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Thu, 7 Aug 2025 15:34:10 -0400 Subject: [PATCH 159/181] remove unsused from adapt test --- test/aniso_adapt.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index d20272aff..aaec1e29a 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -20,7 +20,7 @@ class AnIso : public ma::AnisotropicFunction { public: AnIso(ma::Mesh* m, double sf1, double sf2) : - mesh(m), sizeFactor1(sf1), sizeFactor2(sf2) + sizeFactor1(sf1), sizeFactor2(sf2) { average = ma::getAverageEdgeLength(m); ma::getBoundingBox(m, lower, upper); @@ -36,7 +36,6 @@ class AnIso : public ma::AnisotropicFunction ); } private: - ma::Mesh* mesh; double sizeFactor1, sizeFactor2, average; ma::Vector lower, upper; }; From 6fd71edabfe7c6ac42f27946c1fd5b37532fc240 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 8 Aug 2025 15:39:40 -0400 Subject: [PATCH 160/181] added comments --- CMakeLists.txt | 2 +- ma/maCoarsen.cc | 25 +++++++++++++++++++++++-- ma/maSnapper.cc | 43 ++++++++++++++++++++++++++++++++++++++++--- test/aniso_adapt.h | 32 ++++++++++++++++++++++++++++---- 4 files changed, 92 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 621afc77b..7a2ad4c00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ endif() # This is the top level CMake file for the SCOREC build cmake_minimum_required(VERSION 3.12) -project(SCOREC VERSION 4.0.0 LANGUAGES CXX C) +project(SCOREC VERSION 4.1.0 LANGUAGES CXX C) include(cmake/bob.cmake) include(cmake/xsdk.cmake) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 79913e56f..333499927 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -257,6 +257,7 @@ bool coarsen(Adapt* a) return true; } +//Measure and edge lenght and stores the result so it doesn't have to be calculated again static double getLength(Adapt* a, Tag* lengthTag, Entity* edge) { double length = 0; @@ -271,6 +272,7 @@ static double getLength(Adapt* a, Tag* lengthTag, Entity* edge) } +//Make sure that a collapse will not create an edge longer than the max bool collapseSizeCheck(Adapt* a, Entity* vertex, Entity* edge, apf::Up& adjacent) { Entity* vCollapse = getEdgeVertOppositeVert(a->mesh, edge, vertex); @@ -306,7 +308,11 @@ static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& coll return result; } -//Prevent adjacent vertices from collapsing to create indepedent set +/* + Used after collpasing a vertex to flag adjacent vertices NEED_NOT_COLLAPSE, will create a + set of collapses were no two adjacent vertices collapsed called an independent set. Will + also clear adjacent vertices for collapse in next independent set since they might succeed now. +*/ void flagIndependentSet(Adapt* a, apf::Up& adjacent, size_t& checked) { for (int adj=0; adj < adjacent.n; adj++) { @@ -331,6 +337,11 @@ struct EdgeLength } }; +/* + Given an iterator pointing to a vertex we will collapse the shortest adjacent edge and try the next + shorted until one succeeds and then it will expand independent set. In Li's thesis it only attempts + to collapse the shortest edge, but this gave us better results. +*/ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdgeVerts, std::list::iterator& itr, size_t& checked, apf::Up& adjacent, Tag* lengthTag) { Entity* vertex = *itr; @@ -366,7 +377,12 @@ void clearListFlag(Adapt* a, std::list list, int flag) clearFlag(a, *i++, flag); } -//Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an independent set +/* + Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an + independent set. We want our collapses to touch the independent set in order to + reduce adjacent collapses, since collapsing adjacent vertices will result in a + lower quality mesh. +*/ bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::list::iterator& itr, bool& independentSetStarted, apf::Up& adjacent) { size_t numItr=0; @@ -390,6 +406,7 @@ bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::lis return false; } +//returns a list of vertices that bound a short edge and flags them std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) { std::list shortEdgeVerts; @@ -412,6 +429,10 @@ std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) return shortEdgeVerts; } +/* + Follows the alogritm in Li's thesis in order to coarsen all short edges + in a mesh while maintaining a decent quality mesh. +*/ bool coarsenMultiple(Adapt* a) { if (!a->input->shouldCoarsen) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index f783ee7a6..d5981c4ac 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -61,6 +61,8 @@ bool Snapper::requestLocality(apf::CavityOp* o) return o->requestLocality(&ovs.e[0], ovs.n); } +//Write snapping data to files for debugging purposes +//In order to view relevant information it is neccessary to hide entities with relevent flag in vtk viewer static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) { setFlag(a, ent, CHECKED); @@ -68,6 +70,7 @@ static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) clearFlag(a, ent, CHECKED); } +//Write snapping data to files for debugging purposes static void printFPP(Adapt* a, FirstProblemPlane* FPP) { ma_dbg::addTargetLocation(a, "snap_target"); @@ -284,6 +287,11 @@ int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* en return bit; } +/* + We perform this last to make sure that we have a simple region where we can determine the + best operation to perform and because we want to avoid creating more vertices to snap since + we could get stuck in an infinite loop of creating and snapping those vertices. +*/ bool Snapper::trySwapOrSplit(FirstProblemPlane* FPP) { Entity* ents[4] = {0}; @@ -379,6 +387,11 @@ struct BestCollapse Entity* keep; }; +/* + Perfomes a collapse operation and stores the operation in best if the quality is better, + then cancels the collapse. We want to pick the highest quality after collapsing to the + first problem plane so future operations are more likely to succeed. +*/ static void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, BestCollapse& best) { PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); @@ -400,6 +413,7 @@ static void getBestQualityCollapse(Adapt* a, Entity* edge, Entity* keep, Collaps if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); } +//returns if testVert and refVert are on the same side of the face static bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) { Entity* faceVert[3]; @@ -420,6 +434,11 @@ static bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) return true; //same side of face } +/* + If collapsing the common edges failed we want to try collapsing any edge that will + move us towards the first problem plane. We try collapses first in order to simplify + the region until we can perform smarter operations. +*/ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; @@ -454,6 +473,11 @@ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) else return false; } +/* + If collapsing to the first problem plane has failed then we want + to collapse edges on the first problem plane in order to simplify + the region future operations are more likely to succeed. +*/ bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) { apf::Up& commEdges = FPP->commEdges; @@ -493,6 +517,11 @@ bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) else return false; } +/* + First we try collapsing to a vertex on the first problem plane because this is the most likely + operation to succeed. We first try collapsing to the common edges among the invalid regions + since those are more likely to succeed. +*/ bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) { Vector position = getPosition(mesh, vert); @@ -506,7 +535,6 @@ bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) Entity* edge = FPP->commEdges.e[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(mesh, edge, vert); Vector vFPPCoord = getPosition(mesh, vertexOnFPP); - //TODO: add logic for boundary layers double distToFPPVert = (vFPPCoord - target).getLength(); if (distToFPPVert > distTarget) continue; getBestQualityCollapse(adapt, edge, vert, collapse, best); @@ -546,6 +574,7 @@ static void getInvalidTets(Adapt* a, Upward& adjacentElements, apf::Up& invalid) } } +//Moved vertex to model surface or returns invalid elements if not possible static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& invalid) { Mesh* mesh = adapt->mesh; @@ -567,9 +596,16 @@ bool Snapper::trySimpleSnap() apf::Up invalid; return tryReposition(adapt, vert, snapTag, invalid); } - +#if defined(DEBUG_FPP) static int DEBUGFAILED=0; +#endif +/* +This function will attempt to move vert to the model surface, if it can not do so then it +will atleast move to the first problem plane as described in Li's thesis. It might take multiple +iterations for vert to reach the model surface. Li's thesis was missing some details on how +to apply certain opperators so other algoritms were adapted from old scorec libraries. +*/ bool Snapper::run() { apf::Up invalid; @@ -592,8 +628,9 @@ bool Snapper::run() mesh->removeTag(vert,snapTag); clearFlag(adapt, vert, SNAP); } + #if defined(DEBUG_FPP) if (!success && ++DEBUGFAILED == 1) printFPP(adapt, FPP); - + #endif if (FPP) delete FPP; return success; } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index aaec1e29a..2a93098dd 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -44,17 +44,29 @@ void measureQuality(ma::Mesh* m, double& avgQuality, double& minQuality) { int d = m->getDimension(); apf::MeshEntity* elem; - apf::MeshIterator* elems = m->begin(d); + apf::MeshIterator* it = m->begin(d); ma::IdentitySizeField I(m); - while ((elem = m->iterate(elems))) { + while ((elem = m->iterate(it))) { double q = ma::measureElementQuality(m, &I, elem); avgQuality += q; minQuality = fmin(minQuality, q); } - m->end(elems); + m->end(it); avgQuality = avgQuality / m->count(d); } +//make sure refinement is done +bool noLongEdges(ma::Adapt* a) +{ + apf::MeshEntity* edge; + apf::MeshIterator* it = a->mesh->begin(1); + while ((edge = a->mesh->iterate(it))) + if (a->sizeField->measure(edge) > ma::MAXLENGTH) + return false; + a->mesh->end(it); + return true; +} + int countEdges(ma::Mesh* m) { return m->count(1); @@ -77,9 +89,10 @@ ma::Mesh* coarsenForced(ma::Mesh* m) measureQuality(m, avgQualAfter, minQualAfter); + //make sure that coarsening is happening and it doesn't make the mesh invalid PCU_ALWAYS_ASSERT(edgesBefore > countEdges(m)); PCU_ALWAYS_ASSERT(averageBefore < ma::getAverageEdgeLength(m)); - PCU_ALWAYS_ASSERT(minQualAfter >= 0); + PCU_ALWAYS_ASSERT(minQualAfter >= in->validQuality); m->verify(); delete a; @@ -108,6 +121,7 @@ ma::Mesh* coarsenRegular(ma::Mesh* m) measureQuality(m, avgQualAfter, minQualAfter); + //Makes sure that coarsening is happening and it isn't decreasing the quality of the mesh PCU_ALWAYS_ASSERT(edgesBefore > countEdges(m)); PCU_ALWAYS_ASSERT(averageBefore < ma::getAverageEdgeLength(m)); PCU_ALWAYS_ASSERT(fabs(minQualBefore - minQualAfter) < 0.001f || minQualBefore < minQualAfter); @@ -123,6 +137,7 @@ ma::Mesh* coarsenRegular(ma::Mesh* m) return m; } +//Makes sure that all of the vertices snapped to the model bool allVertsOnModel(ma::Adapt* a) { if (!a->input->shouldSnap) @@ -163,9 +178,16 @@ ma::Mesh* refineSnapTest(ma::Mesh* m) ma::snap(a); } + double avgQualAfter, minQualAfter; + measureQuality(m, avgQualAfter, minQualAfter); + + //Makes sure that refinement is happening PCU_ALWAYS_ASSERT(edgesBefore < countEdges(m)); PCU_ALWAYS_ASSERT(averageBefore > ma::getAverageEdgeLength(m)); + + PCU_ALWAYS_ASSERT(noLongEdges(a)); PCU_ALWAYS_ASSERT(allVertsOnModel(a)); + PCU_ALWAYS_ASSERT(minQualAfter >= 0); m->verify(); delete a; @@ -180,6 +202,7 @@ ma::Mesh* refineSnapTest(ma::Mesh* m) void adaptTests(const std::function& createMesh) { + //Mesh created multiple times to compare adaptation ma::Mesh* meshReg = createMesh(); apf::writeVtkFiles("startMesh", meshReg); @@ -192,6 +215,7 @@ void adaptTests(const std::function& createMesh) ma::Mesh* meshForce = coarsenForced(refineSnapTest(createMesh())); apf::writeVtkFiles("afterForcedCoarsen", meshForce); + //Make sure setting to force coarsen is functioning PCU_ALWAYS_ASSERT(countEdges(meshReg) > countEdges(meshForce)); PCU_ALWAYS_ASSERT(ma::getAverageEdgeLength(meshReg) < ma::getAverageEdgeLength(meshForce)); From 9395079149d3994cb30cc727b11609ad38f7be32 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 8 Aug 2025 15:54:45 -0400 Subject: [PATCH 161/181] fixed unused warning --- ma/maSnapper.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index d5981c4ac..f616090af 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -63,14 +63,17 @@ bool Snapper::requestLocality(apf::CavityOp* o) //Write snapping data to files for debugging purposes //In order to view relevant information it is neccessary to hide entities with relevent flag in vtk viewer +#if defined(DEBUG_FPP) static void flagAndPrint(Adapt* a, Entity* ent, int dim, const char* name) { setFlag(a, ent, CHECKED); ma_dbg::dumpMeshWithFlag(a, 0, dim, CHECKED, name, name); clearFlag(a, ent, CHECKED); } +#endif //Write snapping data to files for debugging purposes +#if defined(DEBUG_FPP) static void printFPP(Adapt* a, FirstProblemPlane* FPP) { ma_dbg::addTargetLocation(a, "snap_target"); @@ -91,6 +94,7 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) flagAndPrint(a, FPP->problemFace, 2, "FPP_Face"); flagAndPrint(a, FPP->problemRegion, 3, "FPP_Region"); } +#endif static int indexOfMin(double a0, double a1, double a2) { From f6832babd5c56372589bd9d6e8e7a5ac795f893c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 8 Aug 2025 16:11:44 -0400 Subject: [PATCH 162/181] collapse comments --- ma/maCollapse.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index fb32eb6ce..6b4a2ddc9 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -55,6 +55,7 @@ bool Collapse::tryThisDirectionNoCancel(double qualityToBeat) return true; } +//Prevents snapping from undoing refinement bool Collapse::edgesGoodSize() { PCU_ALWAYS_ASSERT(elementsToKeep.size()); PCU_ALWAYS_ASSERT(elementsToKeep.size() == newElements.size()); @@ -155,8 +156,10 @@ bool checkEdgeCollapseEdgeRings(Adapt* a, Entity* edge) Mesh* m = a->mesh; Entity* v[2]; m->getDownward(edge,0,v); - if (!getFlag(a, v[0], DONT_COLLAPSE)) PCU_ALWAYS_ASSERT( ! m->isShared(v[0])); - if (!getFlag(a, v[1], DONT_COLLAPSE)) PCU_ALWAYS_ASSERT( ! m->isShared(v[1])); + if (!getFlag(a, v[0], DONT_COLLAPSE)) //Allow collapse in one direction + PCU_ALWAYS_ASSERT( ! m->isShared(v[0])); + if (!getFlag(a, v[1], DONT_COLLAPSE)) //Allow collapse in one direction + PCU_ALWAYS_ASSERT( ! m->isShared(v[1])); apf::Up ve[2]; m->getUp(v[0],ve[0]); m->getUp(v[1],ve[1]); From 1c829f67ebc2b46ea820d0a863e947933d925302 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 8 Aug 2025 16:52:54 -0400 Subject: [PATCH 163/181] update simmetrix version --- .../simmetrix_enabled_pr_comment_trigger_self_hosted.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/simmetrix_enabled_pr_comment_trigger_self_hosted.yml b/.github/workflows/simmetrix_enabled_pr_comment_trigger_self_hosted.yml index 02999fdbf..1af4cd3b2 100644 --- a/.github/workflows/simmetrix_enabled_pr_comment_trigger_self_hosted.yml +++ b/.github/workflows/simmetrix_enabled_pr_comment_trigger_self_hosted.yml @@ -37,7 +37,7 @@ jobs: module use /opt/scorec/spack/rhel9/v0201_4/lmod/linux-rhel9-x86_64/Core/ module load gcc/12.3.0-iil3lno module load mpich/4.1.1-xpoyz4t - module load simmetrix-simmodsuite/2024.0-240119dev-7abimo4 + module load simmetrix-simmodsuite/2025.0-250108dev-llxq6sk module load zoltan/3.83-hap4ggo module load cmake/3.26.3-2duxfcd set -e @@ -70,7 +70,7 @@ jobs: module use /opt/scorec/spack/rhel9/v0201_4/lmod/linux-rhel9-x86_64/Core/ module load gcc/12.3.0-iil3lno module load mpich/4.1.1-xpoyz4t - module load simmetrix-simmodsuite/2024.0-240119dev-7abimo4 + module load simmetrix-simmodsuite/2025.0-250108dev-llxq6sk module load zoltan/3.83-hap4ggo module load cmake/3.26.3-2duxfcd module load cgns/develop-cc4dfwp From 4163701616189dc8e909a6a9bb3d405cd505206b Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 13 Aug 2025 15:59:13 -0400 Subject: [PATCH 164/181] 2d get invalid --- ma/maSnapper.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index f616090af..95a378ebe 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -561,7 +561,21 @@ static FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up return FPP; } -static void getInvalidTets(Adapt* a, Upward& adjacentElements, apf::Up& invalid) +static void computeNormals(Mesh* m, Upward& es, apf::NewArray& normals) +{ + if (m->getDimension() != 2) + return; + normals.allocate(es.getSize()); + for (size_t i = 0; i < es.getSize(); ++i) + normals[i] = getTriNormal(m, es[i]); +} + +static bool didInvert(Mesh* m, Vector& oldNormal, Entity* tri) +{ + return (oldNormal * getTriNormal(m, tri)) < 0; +} + +static void getInvalid(Adapt* a, Upward& adjacentElements, apf::NewArray& normals, apf::Up& invalid) { invalid.n = 0; Vector v[4]; @@ -572,9 +586,16 @@ static void getInvalidTets(Adapt* a, Upward& adjacentElements, apf::Up& invalid) algorithm that moves curves would need to change */ if (getFlag(a, adjacentElements[i], LAYER)) continue; - ma::getVertPoints(a->mesh,adjacentElements[i],v); - if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) - invalid.e[invalid.n++] = adjacentElements[i]; + + if ((a->mesh->getDimension() == 2)) { + if (didInvert(a->mesh, normals[i], adjacentElements[i])) + invalid.e[invalid.n++] = adjacentElements[i]; + } + else{ + ma::getVertPoints(a->mesh,adjacentElements[i],v); + if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) + invalid.e[invalid.n++] = adjacentElements[i]; + } } } @@ -588,8 +609,12 @@ static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& i mesh->getDoubleTag(vertex, snapTag, &target[0]); Upward adjacentElements; mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); + + apf::NewArray normals; + computeNormals(mesh, adjacentElements, normals); + mesh->setPoint(vertex, 0, target); - getInvalidTets(adapt, adjacentElements, invalid); + getInvalid(adapt, adjacentElements, normals, invalid); if (invalid.n == 0) return true; mesh->setPoint(vertex, 0, prev); return false; From 41e827e445f2974e0838af6f628cd1849d926e7c Mon Sep 17 00:00:00 2001 From: Aditya Joshi Date: Thu, 28 Aug 2025 10:50:37 -0400 Subject: [PATCH 165/181] apply coarsening first, revert changes --- ma/ma.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ma/ma.cc b/ma/ma.cc index 97c80456e..b1aa8c3f9 100644 --- a/ma/ma.cc +++ b/ma/ma.cc @@ -27,15 +27,14 @@ void adapt(Input* in) validateInput(in); Adapt* a = new Adapt(in); preBalance(a); - coarsen(a); for (int i = 0; i < in->maximumIterations; ++i) { print(a->mesh->getPCU(), "iteration %d", i); + coarsen(a); + coarsenLayer(a); midBalance(a); refine(a); snap(a); - coarsen(a); - coarsenLayer(a); } allowSplitCollapseOutsideLayer(a); fixElementShapes(a); From d4654792acdeb772f9f843fa9b6454460a74dc35 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 29 Aug 2025 17:46:37 -0400 Subject: [PATCH 166/181] moved comments from github --- ma/maCoarsen.cc | 9 +++++++++ ma/maCollapse.cc | 4 +++- ma/maDBG.cc | 3 ++- ma/maDBG.h | 2 ++ ma/maDoubleSplitCollapse.h | 3 +++ ma/maSingleSplitCollapse.h | 3 +++ ma/maSize.h | 4 ++++ ma/maSnapper.cc | 6 ++++++ test/aniso_adapt.h | 7 ++++++- 9 files changed, 38 insertions(+), 3 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 333499927..cde1151ee 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -7,6 +7,15 @@ of the SCOREC Non-Commercial License this program is distributed under. *******************************************************************************/ +/* +This file contains two coarsening alogrithms. + 1. coarsenMultiple: will repeatedly create independent sets and collapse the mesh + until there are no more short edges left. This code is currently only used for testing + since more work needs to be done to achieve better performance and have the code work in + parallel, at which point the other coarsen algorithm can be deleted. + 2. coarsen: The first will create one independent set and then collapse all of the edges + in that independent set. +*/ #include "maCoarsen.h" #include "maAdapt.h" #include "maCollapse.h" diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index 6b4a2ddc9..f966fa37d 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -55,7 +55,9 @@ bool Collapse::tryThisDirectionNoCancel(double qualityToBeat) return true; } -//Prevents snapping from undoing refinement +/*Sometimes the snapping procedure will attempt to collapse a edge that was just +refined. This function will prevent that when the growth of the edge is above a +thresh hold where it might not reach the target edge length*/ bool Collapse::edgesGoodSize() { PCU_ALWAYS_ASSERT(elementsToKeep.size()); PCU_ALWAYS_ASSERT(elementsToKeep.size() == newElements.size()); diff --git a/ma/maDBG.cc b/ma/maDBG.cc index f766a296c..ed78f92df 100644 --- a/ma/maDBG.cc +++ b/ma/maDBG.cc @@ -30,7 +30,7 @@ static double PI = 3.14159265359; namespace ma_dbg { - +// If no dimension specified then it will write the greatest dimension to the file. void writeMesh(ma::Mesh* m, const char* prefix, const char* suffix, @@ -262,6 +262,7 @@ void createCavityMesh(ma::Adapt* a, cavityMesh->acceptChanges(); std::stringstream ss; + //Allows the user to print to current directory or to folder if (a->input->debugFolder) { ss << a->input->debugFolder << "/"; } diff --git a/ma/maDBG.h b/ma/maDBG.h index 2d7ed62f9..16a65d882 100644 --- a/ma/maDBG.h +++ b/ma/maDBG.h @@ -25,6 +25,8 @@ void writeMesh(ma::Mesh* m, const char* prefix, const char* suffix); +/* Creates a field to contain the model classification for each vertex. Which can be + printed to a file using writeMesh() with dim=0. */ void addClassification(ma::Adapt* a, const char* fieldName); diff --git a/ma/maDoubleSplitCollapse.h b/ma/maDoubleSplitCollapse.h index 42c8a9f06..048faa0aa 100644 --- a/ma/maDoubleSplitCollapse.h +++ b/ma/maDoubleSplitCollapse.h @@ -24,6 +24,9 @@ class DoubleSplitCollapse bool tryThisCollapse(); bool tryBothCollapses(Entity* e); void accept(); + /* Quality is optional since during fix shape we don't need a target quality as + the quality improves. However we need a target quality during snapping since + we don't care if the quality gets worse. */ bool run(Entity** edges, double quality = -1); Adapt* getAdapt(); private: diff --git a/ma/maSingleSplitCollapse.h b/ma/maSingleSplitCollapse.h index 712e412ed..19cefb6f2 100644 --- a/ma/maSingleSplitCollapse.h +++ b/ma/maSingleSplitCollapse.h @@ -32,6 +32,9 @@ class SingleSplitCollapse bool tryThisCollapse(); bool tryBothCollapses(Entity* e); void accept(); + /* Quality is optional since during fix shape we don't need a target quality as + the quality improves. However we need a target quality during snapping since + we don't care if the quality gets worse. */ bool run(Entity* edge, Entity* vert, double quality=-1); Adapt* getAdapt(); private: diff --git a/ma/maSize.h b/ma/maSize.h index f83021a30..83cd2b7e8 100644 --- a/ma/maSize.h +++ b/ma/maSize.h @@ -19,6 +19,10 @@ namespace ma { typedef apf::Matrix3x3 Matrix; +/* Desired length bounds in metric space to replace hard coded values. Right now +these values are const, since we are not sure it is worth while to have the user, +modify these in addition to desired length. Future testing in need because Li's +thesis describes there might be utility to having the user modify them */ const double MAXLENGTH = 1.5; const double MINLENGTH = .5; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 95a378ebe..0eb2a9d31 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -7,6 +7,12 @@ of the SCOREC Non-Commercial License this program is distributed under. *******************************************************************************/ +/* + This file contains functions to move a point to the model surface. As described + in Li's thesis it will first try to collapse in the target direction. Otherwise + it will collapse to simplify the region and attempt other operators such as + swap, split collapse, double split collapse. +*/ #include "maSnapper.h" #include "maAdapt.h" #include "maShapeHandler.h" diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 2a93098dd..51f21e575 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -15,7 +15,12 @@ #include "maSnap.h" #include "apfGeometry.h" #include - +/* + Test some of the individual components in mesh adaptation to make sure that they are + functioning as intended. Right now it only tests coarsen refinement and snapping but + can be expanded to test more in the future. This has been tested with mds, simmetrix, + and capstone meshes. +*/ class AnIso : public ma::AnisotropicFunction { public: From 38dcf6ec704769d720c00c33d134d2085d6d121c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 3 Sep 2025 14:17:53 -0400 Subject: [PATCH 167/181] fix tolerance bug --- gmi_cap/gmi_cap.cc | 4 ++++ gmi_cap/gmi_cap.h | 6 ++++++ ma/maSnap.cc | 19 +++++++++---------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index 9996caed6..17eb50491 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -41,6 +41,10 @@ void gmi_cap_start(void) { } } +bool is_gmi_cap_started() { + return cs_module->get_context() && cs_module->get_geometry() && cs_module->get_mesh(); +} + void gmi_cap_stop(void) { if (!cs_module) gmi_fail("gmi_cap_stop called before gmi_cap_start"); diff --git a/gmi_cap/gmi_cap.h b/gmi_cap/gmi_cap.h index 6ee457198..beadebac4 100644 --- a/gmi_cap/gmi_cap.h +++ b/gmi_cap/gmi_cap.h @@ -57,6 +57,12 @@ struct gmi_ent; * \note This call is required before calling any other gmi_cap functions. */ void gmi_cap_start(void); + +/** + * \brief Returns true if gmi_cap library has been initialized with gmi_cap_start + */ +bool is_gmi_cap_started(); + /** * \brief Finalize gmi_cap library. * diff --git a/ma/maSnap.cc b/ma/maSnap.cc index c848f605b..7ab1ea531 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -24,17 +24,16 @@ #include #include -#ifdef HAVE_CAPSTONE -#include "apfCAP.h" +#ifdef PUMI_HAS_CAPSTONE +#include "gmi_cap.h" #endif namespace ma { -static bool isCapstoneMesh(apf::Mesh* m) +static bool isCapstone() { - #ifdef HAVE_CAPSTONE - if (dynamic_cast(m)) return true; - else return false; + #ifdef PUMI_HAS_CAPSTONE + return is_gmi_cap_started(); #else (void)m; return false; @@ -86,7 +85,7 @@ static size_t isSurfUnderlyingFaceDegenerate( m->getFirstDerivative(g, p, uTan, vTan); double uTanSize = uTan.getLength(); double vTanSize = vTan.getLength(); - if (isCapstoneMesh(m)) { + if (isCapstone()) { uTanSize = uTan * uTan; vTanSize = vTan * vTan; } @@ -170,7 +169,7 @@ static void interpolateParametricCoordinateOnEdge( p[1] = 0.0; p[2] = 0.0; - if (isCapstoneMesh(m)) { + if (isCapstone()) { // account for non-uniform parameterization of model-edge Vector X[3]; Vector para[2] = {a, b}; @@ -511,7 +510,7 @@ static void interpolateParametricCoordinatesOnRegularFace( * 2) we only check for faces that are periodic */ // this need to be done for faces, only - if (isCapstoneMesh(m)) + if (isCapstone()) return; if (dim != 2) return; @@ -543,7 +542,7 @@ static void interpolateParametricCoordinatesOnFace( size_t num = isSurfUnderlyingFaceDegenerate(m, g, axes, vals); if (num > 0) { // the underlying surface is degenerate - if (!isCapstoneMesh(m)) { + if (!isCapstone()) { interpolateParametricCoordinatesOnDegenerateFace(m, g, t, a, b, axes, vals, p); } else { From 7988f5f5b8f7233c78049e784afb75356ac23f4a Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 3 Sep 2025 14:39:49 -0400 Subject: [PATCH 168/181] remove unused --- ma/maSnap.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 7ab1ea531..bc0c5ae0b 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -35,7 +35,6 @@ static bool isCapstone() #ifdef PUMI_HAS_CAPSTONE return is_gmi_cap_started(); #else - (void)m; return false; #endif } From 9f9d333181ba6f39ee58fb323a7cfa00e1f0586c Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 14:44:31 -0400 Subject: [PATCH 169/181] fixed snapper issue --- ma/maSnapper.cc | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 0eb2a9d31..47861770d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -581,10 +581,9 @@ static bool didInvert(Mesh* m, Vector& oldNormal, Entity* tri) return (oldNormal * getTriNormal(m, tri)) < 0; } -static void getInvalid(Adapt* a, Upward& adjacentElements, apf::NewArray& normals, apf::Up& invalid) +static void getInvalid(Adapt* a, Upward& adjacentElements, apf::Up& invalid) { invalid.n = 0; - Vector v[4]; for (size_t i = 0; i < adjacentElements.getSize(); ++i) { /* for now, when snapping a vertex on the boundary layer, ignore the quality of layer elements. @@ -592,16 +591,8 @@ static void getInvalid(Adapt* a, Upward& adjacentElements, apf::NewArray algorithm that moves curves would need to change */ if (getFlag(a, adjacentElements[i], LAYER)) continue; - - if ((a->mesh->getDimension() == 2)) { - if (didInvert(a->mesh, normals[i], adjacentElements[i])) - invalid.e[invalid.n++] = adjacentElements[i]; - } - else{ - ma::getVertPoints(a->mesh,adjacentElements[i],v); - if ((cross((v[1] - v[0]), (v[2] - v[0])) * (v[3] - v[0])) < 0) - invalid.e[invalid.n++] = adjacentElements[i]; - } + if (a->shape->getQuality(adjacentElements[i]) < a->input->validQuality) + invalid.e[invalid.n++] = adjacentElements[i]; } } @@ -616,11 +607,8 @@ static bool tryReposition(Adapt* adapt, Entity* vertex, Tag* snapTag, apf::Up& i Upward adjacentElements; mesh->getAdjacent(vertex, mesh->getDimension(), adjacentElements); - apf::NewArray normals; - computeNormals(mesh, adjacentElements, normals); - mesh->setPoint(vertex, 0, target); - getInvalid(adapt, adjacentElements, normals, invalid); + getInvalid(adapt, adjacentElements, invalid); if (invalid.n == 0) return true; mesh->setPoint(vertex, 0, prev); return false; From 63c223deb7f0ec8a9d3576395472e7df47d0ccce Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 16:14:07 -0400 Subject: [PATCH 170/181] fixed cap test --- ma/maSnapper.cc | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 47861770d..7828a3129 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -567,20 +567,6 @@ static FirstProblemPlane* getFPP(Adapt* a, Entity* vertex, Tag* snapTag, apf::Up return FPP; } -static void computeNormals(Mesh* m, Upward& es, apf::NewArray& normals) -{ - if (m->getDimension() != 2) - return; - normals.allocate(es.getSize()); - for (size_t i = 0; i < es.getSize(); ++i) - normals[i] = getTriNormal(m, es[i]); -} - -static bool didInvert(Mesh* m, Vector& oldNormal, Entity* tri) -{ - return (oldNormal * getTriNormal(m, tri)) < 0; -} - static void getInvalid(Adapt* a, Upward& adjacentElements, apf::Up& invalid) { invalid.n = 0; @@ -640,11 +626,14 @@ bool Snapper::run() return true; } - FirstProblemPlane* FPP = getFPP(adapt, vert, snapTag, invalid); - if (!success) success = tryCollapseToVertex(FPP); - if (!success) success = tryReduceCommonEdges(FPP); - if (!success) success = tryCollapseTetEdges(FPP); - if (!success) success = trySwapOrSplit(FPP); + FirstProblemPlane* FPP=0; + if (mesh->getDimension() == 3) { + if (!success) FPP = getFPP(adapt, vert, snapTag, invalid); + if (!success) success = tryCollapseToVertex(FPP); + if (!success) success = tryReduceCommonEdges(FPP); + if (!success) success = tryCollapseTetEdges(FPP); + if (!success) success = trySwapOrSplit(FPP); + } if (!success) { numFailed++; From eddc01342558491c642f668a41e082b76a98dd78 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 16:53:49 -0400 Subject: [PATCH 171/181] removed unused adapt tests --- ma/maSnap.cc | 2 +- test/aniso_adapt.cc | 5 ----- test/aniso_adapt.h | 24 +++++++++++++----------- test/aniso_adapt_cap.cc | 24 ------------------------ test/aniso_adapt_sim.cc | 18 ------------------ 5 files changed, 14 insertions(+), 59 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index bc0c5ae0b..733cce5d7 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -135,7 +135,7 @@ static double interpolateParametricCoordinate( } double period = range[1]-range[0]; double span = b-a; - if (period < 0.5) //partial range can't be periodic + if (period < 0.5) //meshes in capstone can have partial ranges that aren't periodic return (1-t)*a + t*b; if (!mode) { if (span < (period/2)) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index 6e1eb334d..7bbd9c6cb 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -1,11 +1,6 @@ -#include "ma.h" #include #include #include -#include -#include -#include -#include #include "aniso_adapt.h" ma::Mesh* createMesh(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 51f21e575..9d549f670 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -1,19 +1,19 @@ -#include -#include -#include +#ifndef TEST_ANISO_ADAPT_H +#define TEST_ANISO_ADAPT_H +#include #include #include #include #include #include #include -#include "maCoarsen.h" -#include "maAdapt.h" -#include "maRefine.h" -#include "maShape.h" -#include "maSnap.h" -#include "apfGeometry.h" +#include +#include +#include +#include +#include +#include #include /* Test some of the individual components in mesh adaptation to make sure that they are @@ -54,7 +54,7 @@ void measureQuality(ma::Mesh* m, double& avgQuality, double& minQuality) while ((elem = m->iterate(it))) { double q = ma::measureElementQuality(m, &I, elem); avgQuality += q; - minQuality = fmin(minQuality, q); + minQuality = std::min(minQuality, q); } m->end(it); avgQuality = avgQuality / m->count(d); @@ -228,4 +228,6 @@ void adaptTests(const std::function& createMesh) apf::destroyMesh(meshReg); meshForce->destroyNative(); apf::destroyMesh(meshForce); -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 82f4628e7..73e7e1a0d 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -1,31 +1,7 @@ #include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "maAdapt.h" -#include "maCoarsen.h" -#include "maRefine.h" -#include "maSnap.h" -#include "lionPrint.h" #include "aniso_adapt.h" ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 32881f641..89de5dce9 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -1,27 +1,9 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include #include "aniso_adapt.h" - #include #include -#include #include #include -#include - -#include "SimParasolidKrnl.h" -#include "MeshSimAdapt.h" -#include "SimDiscrete.h" #include "SimAdvMeshing.h" -#include "SimMeshTools.h" ma::Mesh* createMesh(const char* nativefile, const char* smdfile, const char* smsfile, pcu::PCU* PCUObj) { From 1a72cf846cae73c35d1de231e8628d9ad6cfa2e5 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 17:06:31 -0400 Subject: [PATCH 172/181] moved code maCoarsen --- ma/CMakeLists.txt | 2 +- ma/maCoarsen.cc | 120 ++++++++++++++++++++++------------------------ 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/ma/CMakeLists.txt b/ma/CMakeLists.txt index 45a217fd0..e54b59b38 100644 --- a/ma/CMakeLists.txt +++ b/ma/CMakeLists.txt @@ -86,7 +86,7 @@ target_link_libraries(ma ) if (ENABLE_CAPSTONE) -target_link_libraries(ma PUBLIC apf_cap) +target_link_libraries(ma PRIVATE apf_cap) endif() scorec_export_library(ma) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index cde1151ee..719ee502b 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -29,6 +29,58 @@ This file contains two coarsening alogrithms. namespace ma { +namespace { + +//Measures edge length and stores the result so it doesn't have to be calculated again +double getLength(Adapt* a, Tag* lengthTag, Entity* edge) +{ + double length = 0; + if (a->mesh->hasTag(edge, lengthTag)) + a->mesh->getDoubleTag(edge, lengthTag, &length); + else { + length = a->sizeField->measure(edge); + a->mesh->setDoubleTag(edge, lengthTag, &length); + } + return length; +} + +//Make sure that a collapse will not create an edge longer than the max +bool collapseSizeCheck(Adapt* a, Entity* vertex, Entity* edge, apf::Up& adjacent) +{ + Entity* vCollapse = getEdgeVertOppositeVert(a->mesh, edge, vertex); + for (int i=0; imesh, adjacent.e[i], vCollapse)}; + Entity* newEdge = a->mesh->createEntity(apf::Mesh::EDGE, 0, newEdgeVerts); + double length = a->sizeField->measure(newEdge); + destroyElement(a, newEdge); + if (length > MAXLENGTH) return false; + } + return true; +} + +bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, apf::Up& adjacent) +{ + PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); + bool alreadyFlagged = true; + if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); + if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); + + double quality = a->input->shouldForceAdaptation ? a->input->validQuality + : a->input->goodQuality; + + bool result = false; + if (collapse.setEdge(edge) && + collapse.checkClass() && + collapse.checkTopo() && + collapseSizeCheck(a, keep, edge, adjacent) && + collapse.tryBothDirections(quality)) { + result = true; + } + if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); + return result; +} +} + class CollapseChecker : public apf::CavityOp { public: @@ -266,61 +318,10 @@ bool coarsen(Adapt* a) return true; } -//Measure and edge lenght and stores the result so it doesn't have to be calculated again -static double getLength(Adapt* a, Tag* lengthTag, Entity* edge) -{ - double length = 0; - length = a->sizeField->measure(edge); - if (a->mesh->hasTag(edge, lengthTag)) - a->mesh->getDoubleTag(edge, lengthTag, &length); - else { - length = a->sizeField->measure(edge); - a->mesh->setDoubleTag(edge, lengthTag, &length); - } - return length; - -} - -//Make sure that a collapse will not create an edge longer than the max -bool collapseSizeCheck(Adapt* a, Entity* vertex, Entity* edge, apf::Up& adjacent) -{ - Entity* vCollapse = getEdgeVertOppositeVert(a->mesh, edge, vertex); - for (int i=0; imesh, adjacent.e[i], vCollapse)}; - Entity* newEdge = a->mesh->createEntity(apf::Mesh::EDGE, 0, newEdgeVerts); - double length = a->sizeField->measure(newEdge); - destroyElement(a, newEdge); - if (length > MAXLENGTH) return false; - } - return true; -} - -static bool tryCollapseEdge(Adapt* a, Entity* edge, Entity* keep, Collapse& collapse, apf::Up& adjacent) -{ - PCU_ALWAYS_ASSERT(a->mesh->getType(edge) == apf::Mesh::EDGE); - bool alreadyFlagged = true; - if (keep) alreadyFlagged = getFlag(a, keep, DONT_COLLAPSE); - if (!alreadyFlagged) setFlag(a, keep, DONT_COLLAPSE); - - double quality = a->input->shouldForceAdaptation ? a->input->validQuality - : a->input->goodQuality; - - bool result = false; - if (collapse.setEdge(edge) && - collapse.checkClass() && - collapse.checkTopo() && - collapseSizeCheck(a, keep, edge, adjacent) && - collapse.tryBothDirections(quality)) { - result = true; - } - if (!alreadyFlagged) clearFlag(a, keep, DONT_COLLAPSE); - return result; -} - /* - Used after collpasing a vertex to flag adjacent vertices NEED_NOT_COLLAPSE, will create a - set of collapses were no two adjacent vertices collapsed called an independent set. Will - also clear adjacent vertices for collapse in next independent set since they might succeed now. + To be used after collapsing a vertex to flag adjacent vertices as NEED_NOT_COLLAPSE. This will create a + set of collapses where no two adjacent are vertices collapsed. Will also clear adjacent vertices for + collapse in next independent set since they might succeed after a collapse. */ void flagIndependentSet(Adapt* a, apf::Up& adjacent, size_t& checked) { @@ -379,13 +380,6 @@ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdg return false; } -void clearListFlag(Adapt* a, std::list list, int flag) -{ - auto i = list.begin(); - while (i != list.end()) - clearFlag(a, *i++, flag); -} - /* Iterates through shortEdgeVerts until it finds a vertex that is adjacent to an independent set. We want our collapses to touch the independent set in order to @@ -410,7 +404,7 @@ bool getAdjIndependentSet(Adapt* a, std::list& shortEdgeVerts, std::lis } itr++; } while (numItr < shortEdgeVerts.size()); - clearListFlag(a, shortEdgeVerts, NEED_NOT_COLLAPSE); + for (auto v : shortEdgeVerts) clearFlag(a, v, NEED_NOT_COLLAPSE); independentSetStarted = false; return false; } @@ -433,7 +427,7 @@ std::list getShortEdgeVerts(Adapt* a, Tag* lengthTag) shortEdgeVerts.push_back(vertices[i]); } } - clearListFlag(a, shortEdgeVerts, CHECKED); + for (auto v : shortEdgeVerts) clearFlag(a, v, CHECKED); a->mesh->end(it); return shortEdgeVerts; } From 03119fe6d70ff4d89591e3dd2876f13dfe6f8aac Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 17:38:45 -0400 Subject: [PATCH 173/181] reformating --- ma/maCollapse.cc | 2 +- ma/maSize.h | 1 + ma/maSnap.cc | 8 ++++++-- ma/maSnapper.cc | 16 ++++++++-------- test/aniso_adapt_cap.cc | 2 -- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ma/maCollapse.cc b/ma/maCollapse.cc index f966fa37d..af13ba324 100644 --- a/ma/maCollapse.cc +++ b/ma/maCollapse.cc @@ -79,7 +79,7 @@ bool Collapse::edgesGoodSize() { } } } - if (maxSize > MAXLENGTH && ratioAtMaxSize > 1.2 ) return false; + if (maxSize > MAXLENGTH && ratioAtMaxSize > MAXLENGTHRATIO) return false; return true; } diff --git a/ma/maSize.h b/ma/maSize.h index 83cd2b7e8..e8f9b6058 100644 --- a/ma/maSize.h +++ b/ma/maSize.h @@ -25,6 +25,7 @@ modify these in addition to desired length. Future testing in need because Li's thesis describes there might be utility to having the user modify them */ const double MAXLENGTH = 1.5; const double MINLENGTH = .5; +const double MAXLENGTHRATIO = 1.2; class SizeField { diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 733cce5d7..025dceb1b 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -919,8 +919,12 @@ void snap(Adapt* a) snapLayer(a, snapTag); double t1 = pcu::Time(); - print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d - Collapse %d - Swap %d - SplitCollapse %d - completed in %f seconds", - toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); + print(a->mesh->getPCU(), "ToSnap %d - Moved %d - Failed %d - CollapseToVtx %d" + " - Collapse %d - Swap %d - SplitCollapse %d" + " - completed in %f seconds", + toSnap, collect(a,snapper.numSnapped), collect(a,snapper.numFailed), + collect(a,snapper.numCollapseToVtx), collect(a,snapper.numCollapse), + collect(a,snapper.numSwap), collect(a,snapper.numSplitCollapse), t1 - t0); if (a->hasLayer) checkLayerShape(a->mesh, "after snapping"); } diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 7828a3129..b592dddcb 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -713,16 +713,16 @@ bool FirstProblemPlane::find() lion_oprint(1, "Info: Found Infinitely Many Intersection Points!\n"); Vector newDirection = intersect - ray.start; if (newDirection.getLength() < minDist) { - dists.push_back(newDirection.getLength()); - minDist = dists.back(); - problemFace = face; - problemRegion = elem; - intersection = intersect; - // do not need to check whether the move is valid since the valid - // ones should have been taken care of by this point + dists.push_back(newDirection.getLength()); + minDist = dists.back(); + problemFace = face; + problemRegion = elem; + intersection = intersect; + // do not need to check whether the move is valid since the valid + // ones should have been taken care of by this point } else - dists.push_back(newDirection.getLength()); + dists.push_back(newDirection.getLength()); } } diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 73e7e1a0d..246fd403e 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -1,7 +1,6 @@ #include #include #include -#include #include "aniso_adapt.h" ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) @@ -30,7 +29,6 @@ int main(int argc, char** argv) } gmi_register_mesh(); - gmi_register_null(); gmi_cap_start(); gmi_register_cap(); lion_set_verbosity(1); From 1d928d983b26a0945cc36e58df94f62e7e640027 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 17:51:19 -0400 Subject: [PATCH 174/181] removed unecessary apf::up --- ma/maSnapper.cc | 55 +++++++++++++++++++++---------------------------- ma/maSnapper.h | 4 ++-- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index b592dddcb..7a62596bc 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -451,18 +451,18 @@ static bool sameSide(Adapt* a, Entity* testVert, Entity* refVert, Entity* face) */ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) { - apf::Up& commEdges = FPP->commEdges; + std::vector& commEdges = FPP->commEdges; BestCollapse best; - for (int i=0; igetDownward(commEdges.e[i], 0, vertex); + mesh->getDownward(commEdges[i], 0, vertex); for (int j=0; j<2; j++) - getBestQualityCollapse(adapt, commEdges.e[i], vertex[j], collapse, best); + getBestQualityCollapse(adapt, commEdges[i], vertex[j], collapse, best); } - for (int i=0; igetUp(vertexFPP, adjEdges); @@ -490,15 +490,15 @@ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) */ bool Snapper::tryReduceCommonEdges(FirstProblemPlane* FPP) { - apf::Up& commEdges = FPP->commEdges; + std::vector& commEdges = FPP->commEdges; BestCollapse best; Entity* pbEdges[3]; mesh->getDownward(FPP->problemFace, 1, pbEdges); - switch(commEdges.n) { + switch(commEdges.size()) { case 2: { - Entity* v1 = getEdgeVertOppositeVert(mesh, commEdges.e[0], vert); - Entity* v2 = getEdgeVertOppositeVert(mesh, commEdges.e[1], vert); + Entity* v1 = getEdgeVertOppositeVert(mesh, commEdges[0], vert); + Entity* v2 = getEdgeVertOppositeVert(mesh, commEdges[1], vert); for (int i=0; i<3; i++) { Entity* pbVert[2]; @@ -541,8 +541,8 @@ bool Snapper::tryCollapseToVertex(FirstProblemPlane* FPP) BestCollapse best; - for (int i = 0; i < FPP->commEdges.n; ++i) { - Entity* edge = FPP->commEdges.e[i]; + for (int i = 0; i < FPP->commEdges.size(); ++i) { + Entity* edge = FPP->commEdges[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(mesh, edge, vert); Vector vFPPCoord = getPosition(mesh, vertexOnFPP); double distToFPPVert = (vFPPCoord - target).getLength(); @@ -653,7 +653,7 @@ FirstProblemPlane::FirstProblemPlane(Adapt* a, Tag* st) snapTag = st; problemFace = 0; problemRegion = 0; - commEdges.n = 0; + commEdges.clear(); tol = 1.0e-14; } @@ -664,9 +664,8 @@ void FirstProblemPlane::setVertex(Entity* v) void FirstProblemPlane::setBadElements(apf::Up& badElements) { - problemRegions.n = badElements.n; for (int i = 0; i < badElements.n; i++) { - problemRegions.e[i] = badElements.e[i]; + problemRegions.push_back(badElements.e[i]); } } @@ -686,8 +685,7 @@ bool FirstProblemPlane::find() // determine distances to all possible problem faces, the shortest // distance and its intersection on first problem plane (FPP) - int n; - n = problemRegions.n; + int n = problemRegions.size(); Entity* elem; Entity* face; Ray ray; @@ -699,7 +697,7 @@ bool FirstProblemPlane::find() dists.clear(); for (int i = 0; i < n; i++) { - elem = problemRegions.e[i]; + elem = problemRegions[i]; face = getTetFaceOppositeVert(mesh, elem, vert); std::vector coords; getFaceCoords(mesh, face, coords); @@ -731,18 +729,18 @@ bool FirstProblemPlane::find() coplanarProblemRegions.n = 0; if (!problemRegion) { - problemRegion = problemRegions.e[0]; + problemRegion = problemRegions[0]; problemFace = getTetFaceOppositeVert(mesh, problemRegion, vert); coplanarProblemRegions.n = n; for (int i = 0; i < n; i++) { - coplanarProblemRegions.e[i] = problemRegions.e[i]; + coplanarProblemRegions.e[i] = problemRegions[i]; } } else { minDist += tol; for (int i = 0; i < n; i++) { if (dists[i] < minDist) { - coplanarProblemRegions.e[coplanarProblemRegions.n] = problemRegions.e[i]; + coplanarProblemRegions.e[coplanarProblemRegions.n] = problemRegions[i]; coplanarProblemRegions.n++; } } @@ -769,8 +767,8 @@ void FirstProblemPlane::findCandidateEdges(std::vector &edges) Entity* edge; Entity* v; - for (int i = 0; i < commEdges.n; i++) { - edge = commEdges.e[i]; + for (int i = 0; i < commEdges.size(); i++) { + edge = commEdges[i]; Downward dv; mesh->getDownward(edge, 0, dv); (dv[0] == vert) ? v = dv[1] : v = dv[0]; @@ -844,10 +842,8 @@ void FirstProblemPlane::findCommonEdges(apf::Up& cpRegions) Downward edges; int nDownEdges = mesh->getDownward(cpRegions.e[0], 1, edges); for (int i = 0; i < nDownEdges; i++) { - if (isLowInHigh(mesh, edges[i], vert)) { - commEdges.e[commEdges.n] = edges[i]; - commEdges.n++; - } + if (isLowInHigh(mesh, edges[i], vert)) + commEdges.push_back(edges[i]); } return; } @@ -887,10 +883,7 @@ void FirstProblemPlane::findCommonEdges(apf::Up& cpRegions) break; } } - if (flag) { - commEdges.e[commEdges.n] = edges[i]; - commEdges.n++; - } + if (flag) commEdges.push_back(edges[i]); } } } diff --git a/ma/maSnapper.h b/ma/maSnapper.h index 88034346b..8aa17f5da 100644 --- a/ma/maSnapper.h +++ b/ma/maSnapper.h @@ -74,8 +74,8 @@ class FirstProblemPlane void getCandidateEdges(std::vector &edges); Entity* vert; Entity* problemFace; - apf::Up commEdges; - apf::Up problemRegions; + std::vector commEdges; + std::vector problemRegions; Entity* problemRegion; Tag* snapTag; private: From 905f74be41c3a974b0bced9e9fd0ee368bfe4bd8 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 17:55:37 -0400 Subject: [PATCH 175/181] using size_t --- ma/maSnapper.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 7a62596bc..46ceebecc 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -454,14 +454,14 @@ bool Snapper::tryCollapseTetEdges(FirstProblemPlane* FPP) std::vector& commEdges = FPP->commEdges; BestCollapse best; - for (int i=0; igetDownward(commEdges[i], 0, vertex); for (int j=0; j<2; j++) getBestQualityCollapse(adapt, commEdges[i], vertex[j], collapse, best); } - for (int i=0; icommEdges.size(); ++i) { + for (size_t i = 0; i < FPP->commEdges.size(); ++i) { Entity* edge = FPP->commEdges[i]; Entity* vertexOnFPP = getEdgeVertOppositeVert(mesh, edge, vert); Vector vFPPCoord = getPosition(mesh, vertexOnFPP); @@ -685,7 +685,7 @@ bool FirstProblemPlane::find() // determine distances to all possible problem faces, the shortest // distance and its intersection on first problem plane (FPP) - int n = problemRegions.size(); + size_t n = problemRegions.size(); Entity* elem; Entity* face; Ray ray; @@ -696,7 +696,7 @@ bool FirstProblemPlane::find() ray.dir = target - ray.start; dists.clear(); - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { elem = problemRegions[i]; face = getTetFaceOppositeVert(mesh, elem, vert); std::vector coords; @@ -767,7 +767,7 @@ void FirstProblemPlane::findCandidateEdges(std::vector &edges) Entity* edge; Entity* v; - for (int i = 0; i < commEdges.size(); i++) { + for (size_t i = 0; i < commEdges.size(); i++) { edge = commEdges[i]; Downward dv; mesh->getDownward(edge, 0, dv); From 9c0fba7e34af8cd8a2187aa7ab2cd810522e671f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 18:10:38 -0400 Subject: [PATCH 176/181] int to size_t --- ma/maSnapper.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 46ceebecc..1b3233544 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -732,13 +732,13 @@ bool FirstProblemPlane::find() problemRegion = problemRegions[0]; problemFace = getTetFaceOppositeVert(mesh, problemRegion, vert); coplanarProblemRegions.n = n; - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { coplanarProblemRegions.e[i] = problemRegions[i]; } } else { minDist += tol; - for (int i = 0; i < n; i++) { + for (size_t i = 0; i < n; i++) { if (dists[i] < minDist) { coplanarProblemRegions.e[coplanarProblemRegions.n] = problemRegions[i]; coplanarProblemRegions.n++; From 41ec12215615e0a5c82446bfd863ec14f2fe0bbd Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 19:15:39 -0400 Subject: [PATCH 177/181] simplify code --- ma/maCoarsen.cc | 5 +++-- ma/maSnapper.cc | 42 ++++++++++++++++++------------------------ 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/ma/maCoarsen.cc b/ma/maCoarsen.cc index 719ee502b..9baa67130 100644 --- a/ma/maCoarsen.cc +++ b/ma/maCoarsen.cc @@ -26,6 +26,7 @@ This file contains two coarsening alogrithms. #include "apfShape.h" #include #include +#include namespace ma { @@ -360,13 +361,13 @@ bool collapseShortest(Adapt* a, Collapse& collapse, std::list& shortEdg double length = getLength(a, lengthTag, adjacent.e[i]); EdgeLength measured{adjacent.e[i], length}; if (measured.length > MINLENGTH) continue; - auto pos = std::lower_bound(sorted.begin(), sorted.end(), measured); - sorted.insert(pos, measured); + sorted.push_back(measured); } if (sorted.size() == 0) { //performance optimization, will rarely result in a missed edge itr = shortEdgeVerts.erase(itr); return false; } + std::sort(sorted.begin(), sorted.end()); for (size_t i=0; i < sorted.size(); i++) { Entity* keepVertex = getEdgeVertOppositeVert(a->mesh, sorted[i].edge, vertex); if (!tryCollapseEdge(a, sorted[i].edge, keepVertex, collapse, adjacent)) continue; diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 1b3233544..4fe1ea34d 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -7,11 +7,13 @@ of the SCOREC Non-Commercial License this program is distributed under. *******************************************************************************/ -/* - This file contains functions to move a point to the model surface. As described - in Li's thesis it will first try to collapse in the target direction. Otherwise - it will collapse to simplify the region and attempt other operators such as - swap, split collapse, double split collapse. +/** + * \file maSnapper.cc + * \brief Definition of maSnapper.h file. + * This file contains functions to move a point to the model surface. As described + * in Li's thesis it will first try to collapse in the target direction. Otherwise + * it will collapse to simplify the region and attempt other operators such as + * swap, split collapse, double split collapse. */ #include "maSnapper.h" #include "maAdapt.h" @@ -102,29 +104,23 @@ static void printFPP(Adapt* a, FirstProblemPlane* FPP) } #endif +//returns the greater index in the case of equality static int indexOfMin(double a0, double a1, double a2) { - int k; - double buf; - if( a0mesh->getDownward(face, 0, faceVert); - Vector facePos[3]; - for (int i=0; i < 3; ++i) - facePos[i] = getPosition(a->mesh,faceVert[i]); - - Vector normal = apf::cross((facePos[1]-facePos[0]),(facePos[2]-facePos[0])); double magN = normal*normal; Vector vertPos = getPosition(a->mesh, vert); - double magCP = (vertPos-facePos[0]) * normal; + double magCP = (vertPos-v0) * normal; double ratio=magCP/magN; Vector result; @@ -182,14 +178,12 @@ int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* en } } - Vector projection = projOnTriPlane(a, face, vert); - //TODO: ERROR if projection = any point on problem face - /* find normal to the plane */ Vector v01 = facePos[1] - facePos[0]; Vector v02 = facePos[2] - facePos[0]; Vector norm = apf::cross(v01, v02); + Vector projection = projOnTriPlane(a, face, vert, norm, facePos[0]); Vector ri = projection - facePos[0]; Vector rj = projection - facePos[1]; Vector rk = projection - facePos[2]; From 6894ffc5c4b2cf1314dd17f60accf2114eadc67f Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 22:18:07 -0400 Subject: [PATCH 178/181] fixed error with isCapstone --- gmi_cap/gmi_cap.cc | 8 ++++---- gmi_cap/gmi_cap.h | 14 +++++++++----- ma/maSnap.cc | 13 ++++++------- ma/maSnapper.cc | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/gmi_cap/gmi_cap.cc b/gmi_cap/gmi_cap.cc index 17eb50491..ab1b697e0 100644 --- a/gmi_cap/gmi_cap.cc +++ b/gmi_cap/gmi_cap.cc @@ -41,10 +41,6 @@ void gmi_cap_start(void) { } } -bool is_gmi_cap_started() { - return cs_module->get_context() && cs_module->get_geometry() && cs_module->get_mesh(); -} - void gmi_cap_stop(void) { if (!cs_module) gmi_fail("gmi_cap_stop called before gmi_cap_start"); @@ -545,3 +541,7 @@ GDBI* gmi_export_cap(gmi_model* m) cap_model* cm = (cap_model*)m; return cm->geomInterface; } + +int gmi_cap_test(struct gmi_model* model) { + return model->ops == &ops ? 1 : 0; +} diff --git a/gmi_cap/gmi_cap.h b/gmi_cap/gmi_cap.h index beadebac4..fcf9e31e2 100644 --- a/gmi_cap/gmi_cap.h +++ b/gmi_cap/gmi_cap.h @@ -58,11 +58,6 @@ struct gmi_ent; */ void gmi_cap_start(void); -/** - * \brief Returns true if gmi_cap library has been initialized with gmi_cap_start - */ -bool is_gmi_cap_started(); - /** * \brief Finalize gmi_cap library. * @@ -100,6 +95,15 @@ struct gmi_model* gmi_cap_load(const char* creFileName); */ void gmi_cap_write(struct gmi_model* model, const char* creFileName); +/** + * \brief Test if model is a Capstone gmi_model. + * + * \param model An abstract gmi_model which may have an underlying Capstone + * database. + * \return 1 if model is a Capstone gmi_model and 0 otherwise. + */ +int gmi_cap_test(struct gmi_model* model); + #ifdef __cplusplus /** diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 025dceb1b..9271d4448 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -30,10 +30,9 @@ namespace ma { -static bool isCapstone() -{ +static bool isCapstone(apf::Mesh* m) { #ifdef PUMI_HAS_CAPSTONE - return is_gmi_cap_started(); + return gmi_cap_test(m->getModel()); #else return false; #endif @@ -84,7 +83,7 @@ static size_t isSurfUnderlyingFaceDegenerate( m->getFirstDerivative(g, p, uTan, vTan); double uTanSize = uTan.getLength(); double vTanSize = vTan.getLength(); - if (isCapstone()) { + if (isCapstone(m)) { uTanSize = uTan * uTan; vTanSize = vTan * vTan; } @@ -168,7 +167,7 @@ static void interpolateParametricCoordinateOnEdge( p[1] = 0.0; p[2] = 0.0; - if (isCapstone()) { + if (isCapstone(m)) { // account for non-uniform parameterization of model-edge Vector X[3]; Vector para[2] = {a, b}; @@ -509,7 +508,7 @@ static void interpolateParametricCoordinatesOnRegularFace( * 2) we only check for faces that are periodic */ // this need to be done for faces, only - if (isCapstone()) + if (isCapstone(m)) return; if (dim != 2) return; @@ -541,7 +540,7 @@ static void interpolateParametricCoordinatesOnFace( size_t num = isSurfUnderlyingFaceDegenerate(m, g, axes, vals); if (num > 0) { // the underlying surface is degenerate - if (!isCapstone()) { + if (!isCapstone(m)) { interpolateParametricCoordinatesOnDegenerateFace(m, g, t, a, b, axes, vals, p); } else { diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 4fe1ea34d..6a4558ba8 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -116,7 +116,7 @@ static int indexOfMin(double a0, double a1, double a2) } } -static Vector projOnTriPlane(Adapt* a, Entity* face, Entity* vert, Vector normal, Vector v0) +static Vector projOnTriPlane(Adapt* a, Entity* vert, Vector normal, Vector v0) { double magN = normal*normal; Vector vertPos = getPosition(a->mesh, vert); @@ -183,7 +183,7 @@ int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* en Vector v02 = facePos[2] - facePos[0]; Vector norm = apf::cross(v01, v02); - Vector projection = projOnTriPlane(a, face, vert, norm, facePos[0]); + Vector projection = projOnTriPlane(a, vert, norm, facePos[0]); Vector ri = projection - facePos[0]; Vector rj = projection - facePos[1]; Vector rk = projection - facePos[2]; From 47ed51a10a2a2a57b3d7f6c2627ef314cfa652cd Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 22:31:20 -0400 Subject: [PATCH 179/181] reuse and recycle adapt_sim --- ma/maSnap.cc | 1 + test/aniso_adapt.h | 2 -- test/aniso_adapt_sim.cc | 31 +++++++++++++++++-------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ma/maSnap.cc b/ma/maSnap.cc index 9271d4448..fef9a28de 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -34,6 +34,7 @@ static bool isCapstone(apf::Mesh* m) { #ifdef PUMI_HAS_CAPSTONE return gmi_cap_test(m->getModel()); #else + (void) m; return false; #endif } diff --git a/test/aniso_adapt.h b/test/aniso_adapt.h index 9d549f670..9beaab9d5 100644 --- a/test/aniso_adapt.h +++ b/test/aniso_adapt.h @@ -226,8 +226,6 @@ void adaptTests(const std::function& createMesh) meshReg->destroyNative(); apf::destroyMesh(meshReg); - meshForce->destroyNative(); - apf::destroyMesh(meshForce); } #endif \ No newline at end of file diff --git a/test/aniso_adapt_sim.cc b/test/aniso_adapt_sim.cc index 89de5dce9..39da0b102 100644 --- a/test/aniso_adapt_sim.cc +++ b/test/aniso_adapt_sim.cc @@ -5,18 +5,6 @@ #include #include "SimAdvMeshing.h" -ma::Mesh* createMesh(const char* nativefile, const char* smdfile, const char* smsfile, pcu::PCU* PCUObj) -{ - pProgress progress = Progress_new(); - Progress_setDefaultCallback(progress); - gmi_model* mdl_ref = gmi_sim_load(nativefile, smdfile); - pGModel model = gmi_export_sim(mdl_ref); - pParMesh mesh = PM_load(smsfile, model, progress); - ma::Mesh* mesh_ref = apf::createMesh(mesh, PCUObj); - apf::Mesh2* m = apf::createMdsMesh(mdl_ref, mesh_ref); - return m; -} - int main(int argc, char* argv[]) { if (argc != 4) { @@ -43,11 +31,26 @@ int main(int argc, char* argv[]) gmi_sim_start(); gmi_register_sim(); - auto createMeshValues = [nativefile, smdfile, smsfile, PCUObj]() - { return createMesh(nativefile, smdfile, smsfile, PCUObj); }; + pProgress progress = Progress_new(); + Progress_setDefaultCallback(progress); + gmi_model* mdl_ref = gmi_sim_load(nativefile, smdfile); + pGModel model = gmi_export_sim(mdl_ref); + pParMesh mesh = PM_load(smsfile, model, progress); + ma::Mesh* mesh_ref = apf::createMesh(mesh, PCUObj); + + auto createMeshValues = [mdl_ref, mesh_ref]() + { return apf::createMdsMesh(mdl_ref, mesh_ref); }; adaptTests(createMeshValues); + M_release(mesh); + Progress_delete(progress); + gmi_sim_stop(); + SimPartitionedMesh_stop(); + Sim_unregisterAllKeys(); + SimModel_stop(); + MS_exit(); + delete PCUObj; MPI_Finalize(); } From 24dccb246104d92c64b6e0f361fcc3d9750a8f53 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Fri, 26 Sep 2025 23:00:02 -0400 Subject: [PATCH 180/181] simplify aniso_adapt --- test/aniso_adapt.cc | 7 +------ test/aniso_adapt_cap.cc | 26 +++++++++++--------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/test/aniso_adapt.cc b/test/aniso_adapt.cc index 7bbd9c6cb..e604564f1 100644 --- a/test/aniso_adapt.cc +++ b/test/aniso_adapt.cc @@ -3,11 +3,6 @@ #include #include "aniso_adapt.h" -ma::Mesh* createMesh(const char* modelfile, const char* meshfile, pcu::PCU *PCUObj) -{ - return apf::loadMdsMesh(modelfile,meshfile,PCUObj); -} - int main(int argc, char** argv) { PCU_ALWAYS_ASSERT(argc==3); @@ -20,7 +15,7 @@ int main(int argc, char** argv) gmi_register_mesh(); auto createMeshValues = [modelFile,meshFile,&PCUObj]() - { return createMesh(modelFile,meshFile,&PCUObj); }; + { return apf::loadMdsMesh(modelFile,meshFile,&PCUObj); }; adaptTests(createMeshValues); } diff --git a/test/aniso_adapt_cap.cc b/test/aniso_adapt_cap.cc index 246fd403e..9cc0bbec5 100644 --- a/test/aniso_adapt_cap.cc +++ b/test/aniso_adapt_cap.cc @@ -3,17 +3,6 @@ #include #include "aniso_adapt.h" -ma::Mesh* createMesh(const char* meshFile, pcu::PCU* PCUObj) -{ - gmi_model* model = gmi_load(meshFile); - ma::Mesh* apfCapMesh = apf::createCapMesh(model, PCUObj); - apf::disownCapModel(apfCapMesh); - ma::Mesh* apfMesh = apf::createMdsMesh(model, apfCapMesh, true); - apf::disownMdsModel(apfMesh); - apf::destroyMesh(apfCapMesh); - return apfMesh; -} - int main(int argc, char** argv) { MPI_Init(&argc, &argv); @@ -32,13 +21,20 @@ int main(int argc, char** argv) gmi_cap_start(); gmi_register_cap(); lion_set_verbosity(1); - const char* meshFile = argv[1]; - auto createMeshValues = [meshFile, &PCUObj]() - { return createMesh(meshFile, &PCUObj); }; - adaptTests(createMeshValues); + gmi_model* model = gmi_load(meshFile); //Freed in adaptTests + ma::Mesh* apfCapMesh = apf::createCapMesh(model, &PCUObj); + apf::disownCapModel(apfCapMesh); + ma::Mesh* mesh = apf::createMdsMesh(model, apfCapMesh, true); + apf::disownMdsModel(mesh); + apf::destroyMesh(apfCapMesh); + auto createMeshValues = [model, mesh]() + { return apf::createMdsMesh(model, mesh, true); }; + + adaptTests(createMeshValues); + apf::destroyMesh(mesh); gmi_cap_stop(); } MPI_Finalize(); From ab8c58052be0ff5b670d94c7be541530b630b6f1 Mon Sep 17 00:00:00 2001 From: Angelyr Date: Wed, 1 Oct 2025 17:05:47 -0400 Subject: [PATCH 181/181] improved comments --- ma/maMatch.cc | 2 +- ma/maSnap.cc | 6 ++++++ ma/maSnapper.cc | 13 ++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ma/maMatch.cc b/ma/maMatch.cc index 7309f5c5c..1a0582c1b 100644 --- a/ma/maMatch.cc +++ b/ma/maMatch.cc @@ -76,7 +76,7 @@ void matchNewElements(Refine* r) } /* we are starting to support a few operations on matched -meshes, sincluding snapping+UR. this should prevent snapping +meshes, including snapping+UR. this should prevent snapping from modifying any matched entities */ void preventMatchedCavityMods(Adapt* a) { diff --git a/ma/maSnap.cc b/ma/maSnap.cc index fef9a28de..3c4d92b76 100644 --- a/ma/maSnap.cc +++ b/ma/maSnap.cc @@ -904,6 +904,12 @@ int collect(Adapt* a, int val) { return a->mesh->getPCU()->Add(val); } +/* + This function follows the snapping procedure specified in Li's thesis, in which verticies + will be moved directly to the model boundary, however if the movement fails due to making + an element invalid, then several operations will be attempted in order to resolve invalid + elements. +*/ void snap(Adapt* a) { if (!a->input->shouldSnap) diff --git a/ma/maSnapper.cc b/ma/maSnapper.cc index 6a4558ba8..2f3a426d2 100644 --- a/ma/maSnapper.cc +++ b/ma/maSnapper.cc @@ -27,10 +27,9 @@ namespace ma { -Snapper::Snapper(Adapt* a, Tag* st) : splitCollapse(a), doubleSplitCollapse(a) +Snapper::Snapper(Adapt* a, Tag* st) : mesh(a->mesh), splitCollapse(a), doubleSplitCollapse(a) { adapt = a; - mesh = a->mesh; snapTag = st; collapse.Init(a); edgeSwap = makeEdgeSwap(a); @@ -134,11 +133,11 @@ static Vector projOnTriPlane(Adapt* a, Entity* vert, Vector normal, Vector v0) Given a poorly-shaped tetrahedron, a base triangle and the opposite vertex of the base, determine the following information: 1. the key mesh entities to apply local mesh modification - 2. area of the four faces - 3. the intersection of two intersected opposite edges in case two large dihedral angles - - return 0 : if an edge is degenerated - 1-7 : the index indicating the location of projection point + 2. area of the four face + + return 0 : if an edge is degenerated + 3,5,6 : the tetrahedron has two large dihedral angles. The opposite edges will be stored in ents[0], ents[1]. + 1,2,4,7 : the tetrahedron has three large angles. The largeest face is stored in ents[0]. */ int getTetStats(Adapt* a, Entity* vert, Entity* face, Entity* region, Entity* ents[4], double area[4]) {