270 multiplicity.resize(size, 0);
271 DEBUG_init_multiplicity.resize(size, 0);
284 if (M0[i] != NOT_AN_ID) {
285 multiplicity[M0_nb_col] = multiplicity[i];
290 GEO::Logger::out(
"HexDom") <<
"M0 final size is " << M0.
size() <<
" x " << M0_nb_col << std::endl;
291 multiplicity.resize(M0_nb_col);
292 M1.resize(M0_nb_col);
303 while (M1[i].index != M1[M1[i].index].index) {
304 M1[i].a *= M1[M1[i].index].a;
305 M1[i].index = M1[M1[i].index].index;
312 FOR(i, M1.size())
if (M1[i].index == i) {
313 to_grp[i] = M1_nb_col;
318 index_t g = to_grp[M1[i].index];
319 new_multiplicity[g] = std::max(new_multiplicity[g], multiplicity[M1[i].index]);
322 multiplicity = new_multiplicity;
323 GEO::Logger::out(
"HexDom") <<
"M1 final size is " << M1.size() <<
" x " << M1_nb_col << std::endl;
324 M2.init_identity(M1_nb_col);
325 M2t.init_identity(M1_nb_col);
334 M2_nb_col = M2.M.size();
335 kernel_size = M2_nb_col;
336 multiplicity.resize(M2_nb_col);
337 GEO::Logger::out(
"HexDom") <<
"M2 final size is " << M2.nb_lines() <<
" x " << M2_nb_col << std::endl;
340 void end_pass(
index_t p_pass) {
345 else if (pass == 1) {
348 else if (pass == 2) {
351 check_multiplicity();
359 FOR(i, c.
size())
if (M0[c[i].index] != NOT_AN_ID) cM0.push_back(
Coeff(M0[c[i].index], c[i].a));
365 FOR(i, cM0.
size()) cM0M1.push_back(
Coeff(M1[cM0[i].index].index, cM0[i].a*M1[cM0[i].index].a));
366 order_AND_make_unique(cM0M1);
372 mult(cM0M1, M2, cM0M1M2);
385 FOR(nc, diffline.
size()) {
386 FOR(nl, M2col.
size()) {
387 index_t c = diffline[nc].index;
389 double coeff = diffline[nc].a*M2col[nl].a;
390 M2t.add(c, l, coeff);
401 M0[c[0].index] = NOT_AN_ID;
409 if (cM0M1.
size() == 0)
return true;
412 if (cM0M1.
size() == 2) {
413 FOR(i, 2)
if ((std::abs(cM0M1[i].a) != 1))
return false;
415 Coeff co[2] = {
Coeff(B.zero_col, 1.0),B.line[0] };
418 while (co[i].index != M1[co[i].index].index) {
419 co[i].a = co[i].a*M1[co[i].index].a;
420 co[i].index = M1[co[i].index].index;
424 if (multiplicity[co[0].index] < multiplicity[co[1].index])
425 M1[co[0].index] =
Coeff(co[1].index, co[1].a*co[0].a);
426 else M1[co[1].index] =
Coeff(co[0].index, co[1].a*co[0].a);
433 if (cM0M1M2.
size() == 0) {
439 FOR(i, cM0M1M2.
size()) {
440 if (cM0M1M2[i].a!=0 &&
441 double(multiplicity[cM0M1M2[i].index])* std::abs(cM0M1M2[i].a) <
442 double(multiplicity[cM0M1M2[ind_to_remove].index]) * std::abs(cM0M1M2[ind_to_remove].a)) {
447 inplace_mult_M2_by_B(B);
455 void check_multiplicity() {
456 std::cerr <<
" check_that multiplicity are respected\n";
457 FOR(x, M0.
size())
if (debug_var_multiplicity(x) < DEBUG_init_multiplicity[x]) {
459 plop(debug_var_multiplicity(x));
460 plop(DEBUG_init_multiplicity[x]);
467 plop(DEBUG_init_multiplicity[x]);
469 std::cerr<< res[i].a<<
" . "<< res[i].index<<
" ( mul= " << multiplicity[res[i].index] <<
" )\n";
476 if (M1.empty())
return cM0;
478 if (M2.M.empty())
return cM0M1;
479 return mult_by_M2(cM0M1);
482 double debug_var_multiplicity(
index_t x) {
483 double min_mult = 10000;
488 double(multiplicity[res[i].index]) * std::abs(res[i].a)
523 void set_multiplicity(
index_t id,
int period) {
525 M.multiplicity[id] = period;
526 M.DEBUG_init_multiplicity[id] = period;
530 void end_pass(index_t p_pass) {
535 void begin_constraint() {
536 new_constraint.clear();
539 void add_constraint_coeff(index_t
id,
double coeff) {
542 new_constraint.push_back(Coeff(
id, coeff));
546 bool end_constraint() {
547 return M.add_constraint(new_constraint);
549 vector<Coeff> new_constraint;
552 void start_new_iter() {
553 std::cerr <<
"New LS iteration \n";
554 bool first_iter = V.empty();
556 fixed.resize(M.kernel_size,
false);
557 V.resize(M.kernel_size);
560 nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
561 nlSolverParameteri(NL_NB_VARIABLES, NLint(M.kernel_size));
565 static const double auto_snap_threshold = 1.;
566 double snap_threshold = 1e20;
567 int nb_fixed_var = 0;
568 bool snap_size_has_changed =
false;
570 std::cerr <<
"Try enforce mutiplicity equality with snap size " << snap_size <<
"\n";
573 FOR(i, M.kernel_size) {
574 nlSetVariable(i, V[i]);
576 if (M.multiplicity[i] < snap_size)
continue;
577 if (M.multiplicity[i] ==0 )
continue;
578 if (M.M2t.nb_coeffs_in_line(i) == 0)
continue;
579 if (pass == 0 && fixed[i])
continue;
581 double snapped_val = double(M.multiplicity[i]) * nint(V[i] /
double(M.multiplicity[i]));
582 double dist = std::abs(snapped_val - val) / double(M.multiplicity[i]);
584 if (dist < snap_threshold
585 && snap_threshold>auto_snap_threshold) {
586 snap_threshold = std::max(dist + .001, auto_snap_threshold);
598 if (dist < snap_threshold && M.multiplicity[i] != 1000) {
599 if (!fixed[i]) nb_fixed_var++;
601 GEO::Logger::out(
"HexDom") <<
" i " << i <<
" snapped_val" << snapped_val <<
" (V[i] " << V[i] << std::endl;
602 nlSetVariable(i, snapped_val);
608 snap_size_has_changed =
false;
609 if (nb_fixed_var == 0) {
610 if (snap_size >= 1) {
611 snap_size_has_changed =
true;
616 }
while (snap_size_has_changed);
623 if (fixed.empty())
return false;
624 FOR(i, M.kernel_size)
625 if (M.multiplicity[i] > 0
627 && M.M2t.nb_coeffs_in_line(i) > 0) return false;
634 nlEnable(NL_VERBOSE);
636 FOR(i, M.kernel_size) {
637 V[i] = nlGetVariable(i);
639 nlDeleteContext(nlGetCurrent());
643 void begin_energy() { nlBegin(NL_ROW); }
644 void add_energy_coeff(index_t
id,
double coeff) {
649 vector<Coeff> line = M.get_line(
id);
650 FOR(m, line.size()) {
651 nlCoefficient(line[m].index, line[m].a*coeff);
654 void add_energy_rhs(
double rhs) { nlRightHandSide(rhs); }
656 void end_energy() { nlEnd(NL_ROW); }
659 double value(index_t i) {
662 vector<Coeff> line = M.get_line(i);
663 FOR(m, line.size()) {
664 res += V[line[m].index] * line[m].a;
669 double show_var(index_t i) {
672 vector<Coeff> line = M.get_line(i);
673 std::cerr <<
" var " << i <<
" = ";
674 FOR(m, line.size()) {
675 std::cerr << line[m].a <<
" X " << V[line[m].index] <<
" + ";
676 res += V[line[m].index] * line[m].a;
686 std::vector<double> V;
687 std::vector<bool> fixed;