77 using namespace simplex;
78 using namespace operations;
79 using namespace operations::tri_mesh;
80 using namespace operations::tet_mesh;
81 using namespace operations::composite;
82 using namespace function;
83 using namespace invariants;
85 std::vector<std::pair<std::shared_ptr<Mesh>, std::string>>
wildmeshing2d(
90 if (!mesh->is_connectivity_valid()) {
91 throw std::runtime_error(
"input mesh for wildmeshing connectivity invalid");
101 auto pt_double_attribute =
105 wmtk::utils::cast_attribute<wmtk::Rational>(
112 auto pt_attribute = mesh->get_attribute_handle<
Rational>(
115 wmtk::utils::cast_attribute<wmtk::Rational>(pt_double_attribute, pt_attribute);
117 mesh->delete_attribute(pt_double_attribute);
121 wmtk::logger().trace(
"Getting rational point accessor");
122 auto pt_accessor = mesh->create_accessor(pt_attribute.as<
Rational>());
124 wmtk::logger().trace(
"Computing bounding box diagonal");
127 Eigen::VectorXd bmin(mesh->top_cell_dimension());
128 bmin.setConstant(std::numeric_limits<double>::max());
129 Eigen::VectorXd bmax(mesh->top_cell_dimension());
130 bmax.setConstant(std::numeric_limits<double>::lowest());
134 const auto p = pt_accessor.vector_attribute(v).cast<
double>();
135 for (int64_t d = 0; d < bmax.size(); ++d) {
136 bmin[d] = std::min(bmin[d], p[d]);
137 bmax[d] = std::max(bmax[d], p[d]);
142 const double bbdiag = (bmax - bmin).norm();
144 wmtk::logger().info(
"bbox max {}, bbox min {}, diag {}", bmax, bmin, bbdiag);
154 wmtk::logger().info(
"target edge length: {}", target_edge_length);
158 auto amips_attribute =
159 mesh->register_attribute<
double>(
"wildmeshing_amips", mesh->top_simplex_type(), 1);
160 auto amips_accessor = mesh->create_accessor(amips_attribute.as<
double>());
162 auto compute_amips = [](
const Eigen::MatrixX<Rational>& P) -> Eigen::VectorXd {
163 assert(P.rows() == 2 || P.rows() == 3);
164 assert(P.cols() == P.rows() + 1);
167 assert(P.rows() == 2);
168 std::array<double, 6> pts;
169 for (
size_t i = 0; i < 3; ++i) {
170 for (
size_t j = 0; j < 2; ++j) {
171 pts[2 * i + j] = P(j, i).to_double();
175 return Eigen::VectorXd::Constant(1, a);
178 assert(P.rows() == 3);
179 std::array<double, 12> pts;
180 for (
size_t i = 0; i < 4; ++i) {
181 for (
size_t j = 0; j < 3; ++j) {
182 pts[3 * i + j] = P(j, i).to_double();
186 return Eigen::VectorXd::Constant(1, a);
190 std::make_shared<wmtk::operations::SingleAttributeTransferStrategy<double, Rational>>(
194 amips_update->run_on_all();
196 double max_amips = std::numeric_limits<double>::lowest();
197 double min_amips = std::numeric_limits<double>::max();
199 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
201 double e = amips_accessor.scalar_attribute(t);
202 max_amips = std::max(max_amips, e);
203 min_amips = std::min(min_amips, e);
206 logger().info(
"Initial Max AMIPS Energy: {}, Min AMIPS Energy: {}", max_amips, min_amips);
224 auto target_edge_length_attribute = mesh->register_attribute<
double>(
225 "wildmeshing_target_edge_length",
232 const double min_edge_length = [&]() ->
double {
238 for (
const auto& e : options.
envelopes) {
239 r = std::max(r, e.thickness);
250 auto edge_length_attribute =
252 auto edge_length_accessor = mesh->create_accessor(edge_length_attribute.as<
double>());
254 auto compute_edge_length = [](
const Eigen::MatrixX<Rational>& P) -> Eigen::VectorXd {
255 assert(P.cols() == 2);
256 assert(P.rows() == 2 || P.rows() == 3);
257 return Eigen::VectorXd::Constant(1, sqrt((P.col(0) - P.col(1)).squaredNorm().to_double()));
259 auto edge_length_update =
260 std::make_shared<wmtk::operations::SingleAttributeTransferStrategy<double, Rational>>(
261 edge_length_attribute,
263 compute_edge_length);
264 edge_length_update->run_on_all();
270 auto frozen_vertex_attribute =
272 auto frozen_vertex_accessor = mesh->create_accessor(frozen_vertex_attribute.as<int64_t>());
274 auto input_ptr = mesh->get_child_meshes().front();
276 int64_t frozen_cnt = 0;
279 const auto& parent_v =
281 frozen_vertex_accessor.scalar_attribute(parent_v) = 1;
291 if (frozen_vertex_accessor.scalar_attribute(v) == 1) {
296 wmtk::logger().info(
"mesh has {} frozen vertices", frozen_cnt);
301 pass_through_attributes.push_back(edge_length_attribute);
302 pass_through_attributes.push_back(amips_attribute);
311 return -edge_length_accessor.scalar_attribute(s.tuple());
315 return edge_length_accessor.scalar_attribute(s.tuple());
325 auto envelope_invariant = std::make_shared<InvariantCollection>(*mesh);
326 std::vector<std::shared_ptr<AttributeTransferStrategyBase>> update_child_position,
327 update_parent_position;
328 std::vector<std::shared_ptr<Mesh>> envelopes;
329 std::vector<MeshConstrainPair> mesh_constraint_pairs;
331 std::vector<std::pair<std::shared_ptr<Mesh>, std::string>> multimesh_meshes;
333 for (
const auto& e : options.
envelopes) {
334 auto constrained_mesh = e.envelope_constrained_mesh;
335 auto geometry_mesh = e.envelope_geometry_mesh;
338 "wildmeshing2d: registered {} mesh as envelope constraints",
341 const bool geometry_has_double_pos =
343 const bool geometry_has_rational_pos =
345 assert(geometry_has_double_pos || geometry_has_rational_pos);
347 auto geometry_pt_handle = geometry_has_double_pos
348 ? geometry_mesh->get_attribute_handle<
double>(
349 e.geometry_position_name,
351 : geometry_mesh->get_attribute_handle<
Rational>(
352 e.geometry_position_name,
355 auto constrained_pt_handle = constrained_mesh->get_attribute_handle<
Rational>(
356 e.constrained_position_name,
359 multimesh_meshes.push_back(std::make_pair(constrained_mesh, e.envelope_name));
360 pass_through_attributes.emplace_back(constrained_pt_handle);
362 mesh_constraint_pairs.emplace_back(geometry_pt_handle, constrained_pt_handle);
364 envelope_invariant->add(std::make_shared<EnvelopeInvariant>(
366 e.thickness * bbdiag,
367 constrained_pt_handle));
370 constrained_pt_handle,
375 constrained_pt_handle));
384 auto inversion_invariant =
385 std::make_shared<SimplexInversionInvariant<Rational>>(*mesh, pt_attribute.as<
Rational>());
387 std::shared_ptr<function::PerSimplexFunction>
amips =
388 std::make_shared<AMIPS>(*mesh, pt_attribute);
391 auto function_invariant =
392 std::make_shared<MaxFunctionInvariant>(mesh->top_simplex_type(),
amips);
394 auto link_condition = std::make_shared<MultiMeshLinkConditionInvariant>(*mesh);
396 auto todo_larger = std::make_shared<TodoLargerInvariant>(
398 edge_length_attribute.as<
double>(),
399 target_edge_length_attribute.as<
double>(),
402 auto todo_smaller = std::make_shared<TodoSmallerInvariant>(
404 edge_length_attribute.as<
double>(),
405 target_edge_length_attribute.as<
double>(),
409 auto interior_edge = std::make_shared<InteriorEdgeInvariant>(*mesh);
411 for (
const auto& em : multimesh_meshes) {
412 interior_edge->add_boundary(*(em.first));
415 auto invariant_separate_substructures =
416 std::make_shared<invariants::SeparateSubstructuresInvariant>(*mesh);
418 auto frozen_vertex_invariant = std::make_shared<invariants::FrozenVertexInvariant>(
420 frozen_vertex_attribute.as<int64_t>());
421 auto frozen_opp_vertex_invariant = std::make_shared<invariants::FrozenOppVertexInvariant>(
423 frozen_vertex_attribute.as<int64_t>());
428 auto visited_edge_flag =
431 auto update_flag_func = [](
const Eigen::MatrixX<Rational>& P) -> Eigen::VectorX<char> {
432 assert(P.cols() == 2);
433 assert(P.rows() == 2 || P.rows() == 3);
434 return Eigen::VectorX<char>::Constant(1,
char(1));
437 std::make_shared<wmtk::operations::SingleAttributeTransferStrategy<char, Rational>>(
482 std::vector<std::shared_ptr<Operation>> ops;
483 std::vector<std::string> ops_name;
488 auto rounding_pt_attribute = mesh->get_attribute_handle_typed<
Rational>(
491 auto rounding = std::make_shared<Rounding>(*mesh, rounding_pt_attribute);
492 rounding->add_invariant(
493 std::make_shared<RoundedInvariant>(*mesh, pt_attribute.as<
Rational>(),
true));
494 rounding->add_invariant(inversion_invariant);
500 auto split = std::make_shared<EdgeSplit>(*mesh);
501 split->set_priority(long_edges_first);
503 split->add_invariant(todo_larger);
504 split->add_invariant(inversion_invariant);
506 split->set_new_attribute_strategy(pt_attribute);
508 split->set_new_attribute_strategy(
513 split->set_new_attribute_strategy(
514 frozen_vertex_attribute,
517 split->set_new_attribute_strategy(
518 target_edge_length_attribute,
522 for (
const auto& attr : pass_through_attributes) {
523 split->set_new_attribute_strategy(
530 split->add_transfer_strategy(edge_length_update);
531 split->add_transfer_strategy(tag_update);
536 auto split_then_round = std::make_shared<AndOperationSequence>(*mesh);
537 split_then_round->add_operation(split);
538 split_then_round->add_operation(rounding);
540 for (
auto& s : update_child_position) {
541 split_then_round->add_transfer_strategy(s);
545 auto split_unrounded = std::make_shared<EdgeSplit>(*mesh);
546 split_unrounded->set_priority(long_edges_first);
548 split_unrounded->add_invariant(todo_larger);
550 auto split_unrounded_transfer_strategy =
551 std::make_shared<SplitNewAttributeStrategy<Rational>>(pt_attribute);
552 split_unrounded_transfer_strategy->set_strategy(
553 [](
const Eigen::VectorX<Rational>& a,
const std::bitset<2>&) {
554 return std::array<Eigen::VectorX<Rational>, 2>{{a, a}};
556 split_unrounded_transfer_strategy->set_rib_strategy(
557 [](
const Eigen::VectorX<Rational>& p0_d,
558 const Eigen::VectorX<Rational>& p1_d,
559 const std::bitset<2>& bs) -> Eigen::VectorX<Rational> {
560 Eigen::VectorX<Rational> p0(p0_d.size());
561 Eigen::VectorX<Rational> p1(p1_d.size());
562 for (
int i = 0; i < p0_d.size(); ++i) {
566 if (bs[0] == bs[1]) {
567 return (p0 + p1) /
Rational(2,
false);
576 split_unrounded->set_new_attribute_strategy(pt_attribute, split_unrounded_transfer_strategy);
578 split_unrounded->set_new_attribute_strategy(
582 split_unrounded->set_new_attribute_strategy(
583 frozen_vertex_attribute,
586 for (
const auto& attr : pass_through_attributes) {
587 split_unrounded->set_new_attribute_strategy(
592 split_unrounded->set_new_attribute_strategy(
593 target_edge_length_attribute,
597 split_unrounded->add_transfer_strategy(amips_update);
598 split_unrounded->add_transfer_strategy(edge_length_update);
599 split_unrounded->add_transfer_strategy(tag_update);
604 auto split_sequence = std::make_shared<OrOperationSequence>(*mesh);
605 split_sequence->add_operation(split_then_round);
606 split_sequence->add_operation(split_unrounded);
610 split_sequence->set_priority(long_edges_first);
614 ops.emplace_back(split_sequence);
615 ops_name.emplace_back(
"SPLIT");
617 ops.emplace_back(rounding);
618 ops_name.emplace_back(
"rounding");
625 auto clps_strat1 = std::make_shared<CollapseNewAttributeStrategy<Rational>>(pt_attribute);
628 clps_strat1->set_strategy(CollapseBasicStrategy::CopyOther);
630 auto clps_strat2 = std::make_shared<CollapseNewAttributeStrategy<Rational>>(pt_attribute);
633 clps_strat2->set_strategy(CollapseBasicStrategy::CopyTuple);
639 auto setup_collapse = [&](std::shared_ptr<EdgeCollapse>& collapse) {
640 collapse->add_invariant(invariant_separate_substructures);
641 collapse->add_invariant(std::make_shared<MultiMeshMapValidInvariant>(*mesh));
643 collapse->add_invariant(inversion_invariant);
644 collapse->add_invariant(function_invariant);
645 collapse->add_invariant(envelope_invariant);
647 collapse->set_new_attribute_strategy(
651 collapse->add_transfer_strategy(tag_update);
653 for (
const auto& attr : pass_through_attributes) {
654 collapse->set_new_attribute_strategy(
658 collapse->set_new_attribute_strategy(
659 target_edge_length_attribute,
665 collapse->add_transfer_strategy(amips_update);
666 collapse->add_transfer_strategy(edge_length_update);
669 for (
auto& s : update_child_position) {
670 collapse->add_transfer_strategy(s);
674 auto collapse1 = std::make_shared<EdgeCollapse>(*mesh);
683 collapse1->add_invariant(frozen_vertex_invariant);
684 collapse1->set_new_attribute_strategy(pt_attribute, clps_strat1);
685 collapse1->set_new_attribute_strategy(
686 frozen_vertex_attribute,
687 CollapseBasicStrategy::CopyOther);
689 setup_collapse(collapse1);
691 auto collapse2 = std::make_shared<EdgeCollapse>(*mesh);
698 collapse2->add_invariant(frozen_opp_vertex_invariant);
699 collapse2->set_new_attribute_strategy(pt_attribute, clps_strat2);
700 collapse2->set_new_attribute_strategy(
701 frozen_vertex_attribute,
702 CollapseBasicStrategy::CopyTuple);
704 setup_collapse(collapse2);
706 auto collapse = std::make_shared<OrOperationSequence>(*mesh);
707 collapse->add_operation(collapse1);
708 collapse->add_operation(collapse2);
709 collapse->add_invariant(todo_smaller);
711 auto collapse_then_round = std::make_shared<AndOperationSequence>(*mesh);
712 collapse_then_round->add_operation(collapse);
713 collapse_then_round->add_operation(rounding);
715 collapse_then_round->set_priority(short_edges_first);
720 for (
auto& s : update_child_position) {
721 collapse_then_round->add_transfer_strategy(s);
725 ops.emplace_back(collapse_then_round);
726 ops_name.emplace_back(
"COLLAPSE");
728 ops.emplace_back(rounding);
729 ops_name.emplace_back(
"rounding");
739 std::shared_ptr<Invariant> simplex_invariant,
740 bool is_edge =
true) {
745 std::make_shared<Swap2dUnroundedVertexInvariant>(*mesh, pt_attribute.as<
Rational>()));
757 collapse.add_invariant(invariant_separate_substructures);
761 collapse.set_new_attribute_strategy(pt_attribute, CollapseBasicStrategy::CopyOther);
762 split.set_new_attribute_strategy(pt_attribute);
764 split.set_new_attribute_strategy(
769 collapse.set_new_attribute_strategy(
773 split.set_new_attribute_strategy(
774 frozen_vertex_attribute,
778 collapse.set_new_attribute_strategy(
779 frozen_vertex_attribute,
780 CollapseBasicStrategy::CopyOther);
782 split.set_new_attribute_strategy(
783 target_edge_length_attribute,
786 collapse.set_new_attribute_strategy(
787 target_edge_length_attribute,
797 for (
const auto& attr : pass_through_attributes) {
798 split.set_new_attribute_strategy(
802 collapse.set_new_attribute_strategy(
809 auto swap = std::make_shared<TriEdgeSwap>(*mesh);
810 setup_swap(*swap, swap->collapse(), swap->split(), interior_edge);
814 ops_name.push_back(
"swap");
816 ops.emplace_back(rounding);
817 ops_name.emplace_back(
"rounding");
867 auto smoothing = std::make_shared<AMIPSOptimizationSmoothing>(*mesh, pt_attribute);
868 smoothing->add_invariant(
869 std::make_shared<RoundedInvariant>(*mesh, pt_attribute.as<
Rational>()));
870 smoothing->add_invariant(frozen_vertex_invariant);
871 smoothing->add_invariant(inversion_invariant);
872 for (
auto& s : update_child_position) {
873 smoothing->add_transfer_strategy(s);
885 auto proj_smoothing = std::make_shared<ProjectOperation>(smoothing, mesh_constraint_pairs);
886 proj_smoothing->use_random_priority() =
true;
887 proj_smoothing->add_invariant(frozen_vertex_invariant);
888 proj_smoothing->add_invariant(envelope_invariant);
889 proj_smoothing->add_invariant(inversion_invariant);
893 proj_smoothing->add_transfer_strategy(amips_update);
894 proj_smoothing->add_transfer_strategy(edge_length_update);
895 for (
auto& s : update_parent_position) {
896 proj_smoothing->add_transfer_strategy(s);
899 for (
auto& s : update_child_position) {
900 proj_smoothing->add_transfer_strategy(s);
905 for (
int i = 0; i < 1; ++i) {
907 ops.push_back(proj_smoothing);
908 ops_name.push_back(
"SMOOTHING");
911 ops.emplace_back(rounding);
912 ops_name.emplace_back(
"rounding");
930 int64_t success = 10;
937 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
938 const auto vertices = mesh->orient_vertices(t);
939 std::vector<Vector2r> pos;
940 for (
int i = 0; i <
vertices.size(); ++i) {
941 pos.push_back(pt_accessor.const_vector_attribute(
vertices[i]));
950 logger().info(
"----------------------- Preprocess Collapse -----------------------");
952 logger().info(
"Executing collapse ...");
959 "Executed {}, {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, "
961 "preprocessing collapse",
972 int64_t unrounded = 0;
975 const auto p = pt_accessor.vector_attribute(v);
976 for (int64_t d = 0; d < 2; ++d) {
977 if (!p[d].is_rounded()) {
983 if (frozen_vertex_accessor.scalar_attribute(v) == 1) {
988 logger().info(
"Mesh has {} unrounded vertices", unrounded);
989 logger().error(
"Mesh has {} frozen vertices", frozen);
992 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
993 const auto vertices = mesh->orient_vertices(t);
994 std::vector<Vector2r> pos;
995 for (
int i = 0; i <
vertices.size(); ++i) {
996 pos.push_back(pt_accessor.const_vector_attribute(
vertices[i]));
1005 double max_energy = std::numeric_limits<double>::lowest();
1006 double min_energy = std::numeric_limits<double>::max();
1007 double avg_energy = 0;
1008 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
1010 double e = amips_accessor.scalar_attribute(t);
1011 max_energy = std::max(max_energy, e);
1012 min_energy = std::min(min_energy, e);
1016 avg_energy = avg_energy / mesh->get_all(mesh->top_simplex_type()).size();
1019 "Max AMIPS Energy: {}, Min AMIPS Energy: {}, Avg AMIPS Energy: {}",
1033 double old_max_energy = max_energy;
1034 double old_avg_energy = avg_energy;
1036 bool is_double =
false;
1037 for (int64_t i = 0; i < options.
max_passes; ++i) {
1038 logger().info(
"--------------------------- Pass {} ---------------------------", i);
1042 for (
auto& op : ops) {
1043 logger().info(
"Executing {} ...", ops_name[jj]);
1055 pass_stats += stats;
1057 "Executed {}, {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, "
1070 int64_t unrounded = 0;
1072 const auto p = pt_accessor.vector_attribute(v);
1073 for (int64_t d = 0; d < 2; ++d) {
1074 if (!p[d].is_rounded()) {
1081 logger().info(
"Mesh has {} unrounded vertices", unrounded);
1084 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
1085 const auto vertices = mesh->orient_vertices(t);
1086 std::vector<Vector2r> pos;
1087 for (
int i = 0; i <
vertices.size(); ++i) {
1088 pos.push_back(pt_accessor.const_vector_attribute(
vertices[i]));
1098 max_energy = std::numeric_limits<double>::lowest();
1099 min_energy = std::numeric_limits<double>::max();
1100 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
1102 double e = amips_accessor.scalar_attribute(t);
1103 max_energy = std::max(max_energy, e);
1104 min_energy = std::min(min_energy, e);
1108 avg_energy = avg_energy / mesh->get_all(mesh->top_simplex_type()).size();
1111 "Max AMIPS Energy: {}, Min AMIPS Energy: {}, Avg AMIPS Energy: {}",
1121 "Executed {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, executing: {}",
1139 assert(mesh->is_connectivity_valid());
1142 max_energy = std::numeric_limits<double>::lowest();
1143 min_energy = std::numeric_limits<double>::max();
1145 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
1147 double e = amips_accessor.scalar_attribute(t);
1148 max_energy = std::max(max_energy, e);
1149 min_energy = std::min(min_energy, e);
1153 avg_energy = avg_energy / mesh->get_all(mesh->top_simplex_type()).size();
1155 int64_t unrounded = 0;
1157 bool rational =
false;
1159 const auto p = pt_accessor.vector_attribute(v);
1160 for (int64_t d = 0; d < bmax.size(); ++d) {
1161 if (!p[d].is_rounded()) {
1169 is_double = !rational;
1172 logger().info(
"Mesh has {} unrounded vertices", unrounded);
1174 "Max AMIPS Energy: {}, Min AMIPS Energy: {}, Avg AMIPS Energy: {}",
1256 old_max_energy = max_energy;
1257 old_avg_energy = avg_energy;
1260 if (max_energy <= target_max_amips && is_double)
break;
1263 logger().info(
"----------------------- Postprocess Collapse -----------------------");
1265 logger().info(
"Executing collapse ...");
1269 "Executed {}, {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, "
1271 "preprocessing collapse",
1272 post_stats.number_of_performed_operations(),
1273 post_stats.number_of_successful_operations(),
1274 post_stats.number_of_failed_operations(),
1275 post_stats.collecting_time,
1276 post_stats.sorting_time,
1277 post_stats.executing_time);
1280 max_energy = std::numeric_limits<double>::lowest();
1281 min_energy = std::numeric_limits<double>::max();
1283 for (
const auto& t : mesh->get_all(mesh->top_simplex_type())) {
1285 double e = amips_accessor.scalar_attribute(t);
1286 max_energy = std::max(max_energy, e);
1287 min_energy = std::min(min_energy, e);
1291 avg_energy = avg_energy / mesh->get_all(mesh->top_simplex_type()).size();
1294 "Max AMIPS Energy: {}, Min AMIPS Energy: {}, Avg AMIPS Energy: {}",
1301 std::vector<std::pair<std::shared_ptr<Mesh>, std::string>> all_meshes;
1302 all_meshes.push_back(std::make_pair(mesh,
"main"));
1304 for (
const auto& p : multimesh_meshes) {
1305 all_meshes.push_back(p);
SchedulerStats run_operation_on_all(operations::Operation &op)
void set_update_frequency(std::optional< size_t > &&freq={})
int64_t number_of_failed_operations() const
Returns the number of failed operations performed by the scheduler.
int64_t number_of_performed_operations() const
Returns the number of performed operations performed by the scheduler.
int64_t number_of_successful_operations() const
Returns the number of successful operations performed by the scheduler.
void add_invariant(std::shared_ptr< Invariant > invariant)
void set_priority(const std::function< double(const simplex::Simplex &)> &func)
virtual PrimitiveType primitive_type() const =0
void add_transfer_strategy(const std::shared_ptr< const operations::AttributeTransferStrategyBase > &other)
std::pair< attribute::MeshAttributeHandle, attribute::MeshAttributeHandle > MeshConstrainPair
static Simplex vertex(const Mesh &m, const Tuple &t)
std::vector< std::pair< std::shared_ptr< Mesh >, std::string > > wildmeshing2d(const WildMeshingOptions &options)
void write(const Mesh &mesh, const std::string &out_dir, const std::string &name, const std::string &vname, const int64_t index, const bool intermediate_output)
auto amips(const Eigen::MatrixBase< Derived > &B)
double Tet_AMIPS_energy(const std::array< double, 12 > &T)
double Tri_AMIPS_energy(const std::array< double, 6 > &T)
void consolidate(Mesh &mesh)
std::shared_ptr< AttributeTransferStrategyBase > make_cast_attribute_transfer_strategy(const wmtk::attribute::MeshAttributeHandle &source, const wmtk::attribute::MeshAttributeHandle &target)
bool link_condition(const EdgeMesh &mesh, const Tuple &edge)
Check if the edge to collapse satisfying the link condition.
std::vector< Tuple > vertices(const Mesh &m, const Simplex &simplex)
int wmtk_orient2d(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y)
spdlog::logger & logger()
Retrieves the current logger.
std::vector< EnvelopeOptions > envelopes
bool replace_double_coordinate
std::string intermediate_output_path
double target_edge_length
std::string intermediate_output_name
std::vector< attribute::MeshAttributeHandle > pass_through
std::shared_ptr< Mesh > input_mesh
std::string input_mesh_position
size_t scheduler_update_frequency