405 if (P.I < 0) { std::cerr <<
"Missing required parameter: I (or N or Ni)\n"; exit(1); }
409 if (P.V < 0) { std::cerr <<
"Missing required parameter: V (or M or Nv)\n"; exit(1); }
411 P.Ni_max =
static_cast<int>(
optional_param(p,
"Ni_max",
static_cast<double>(P.I)));
414 P.physics_option =
static_cast<int>(
optional_param(p,
"physics_option_int", 0));
424 if (P.he_mode != (P.physics_option % 2)) {
425 std::cerr <<
"Inconsistent contract: he_mode=" << P.he_mode
426 <<
" but physics_option=" << P.physics_option
427 <<
" requires he_mode=" << (P.physics_option % 2) <<
"\n";
436 const bool qss = (P.he_kinetics == 1);
439 n_he_extra = qss ? P.V : P.V + 1;
441 n_he_extra = qss ? 1 : 2;
442 P.N_eq = P.I + P.V + n_he_extra + 5;
462 P.boundary_flux =
static_cast<int>(
optional_param(p,
"boundary_flux", 0.0));
465 P.KVV.resize(P.V); P.KVI.resize(P.V); P.GVV.resize(P.V);
466 P.KHeV.resize(P.V); P.Pr_VAC.resize(P.V); P.m13.resize(P.V);
467 P.KII.resize(P.I); P.KIV.resize(P.I); P.GII.resize(P.I);
468 P.k2_SIA.resize(P.I); P.Pr_SIA.resize(P.I);
469 P.K_1D_pref.resize(P.I);
470 P.K_IclV_ns.resize(P.I); P.K_IclV_ni.resize(P.I);
471 P.D_SIA_eff.resize(P.I); P.D_VAC_eff.resize(P.V);
475 for (
int k = 0; k < P.V; ++k) {
480 P.Pr_VAC[k] =
require_param(p,
"Pr_VAC_" + std::to_string(k));
485 for (
int k = 0; k < P.I; ++k) {
489 P.k2_SIA[k] =
require_param(p,
"k2_SIA_" + std::to_string(k));
490 P.Pr_SIA[k] =
require_param(p,
"Pr_SIA_" + std::to_string(k));
491 P.K_1D_pref[k] =
optional_param(p,
"K_1D_pref_" + std::to_string(k), 0.0);
492 P.K_IclV_ns[k] =
optional_param(p,
"K_IclV_ns_" + std::to_string(k), 0.0);
493 P.K_IclV_ni[k] =
optional_param(p,
"K_IclV_ni_" + std::to_string(k), 0.0);
497 for (
int k = 0; k < P.I; ++k)
498 P.D_SIA_eff[k] =
optional_param(p,
"D_SIA_eff_" + std::to_string(k), 0.0);
499 for (
int k = 0; k < P.V; ++k)
500 P.D_VAC_eff[k] =
optional_param(p,
"D_VAC_eff_" + std::to_string(k), 0.0);
501 P.loop_coal =
static_cast<int>(
optional_param(p,
"loop_coal", 0.0));
502 P.sia_emission_monomer =
static_cast<int>(
optional_param(p,
"sia_emission_monomer", 0.0));
503 P.D_loop_coal.assign(P.I, 0.0);
505 for (
int k = 0; k < P.I; ++k)
507 p,
"D_loop_coal_" + std::to_string(k), 0.0);
513 P.Z_i_loop_arr.clear();
514 if (p.count(
"Z_i_loop_arr_0")) {
515 P.Z_i_loop_arr.assign(P.I, P.Z_i_loop);
516 for (
int k = 0; k < P.I; ++k)
518 p,
"Z_i_loop_arr_" + std::to_string(k), P.Z_i_loop);
545 static_cast<double>(P.i_mobile)));
547 static_cast<double>(P.v_mobile)));
548 P.shape_function =
static_cast<int>(
optional_param(p,
"shape_function", 1.0));
551 P.n_mom = P.shape_function + 1;
557 P.sia_bin_lo.resize(P.I_bin);
558 P.sia_bin_hi.resize(P.I_bin);
559 for (
int k = 0; k < P.I_bin; ++k) {
560 P.sia_bin_lo[k] =
static_cast<int>(
562 P.sia_bin_hi[k] =
static_cast<int>(
565 P.vac_bin_lo.resize(P.V_bin);
566 P.vac_bin_hi.resize(P.V_bin);
567 for (
int k = 0; k < P.V_bin; ++k) {
568 P.vac_bin_lo[k] =
static_cast<int>(
570 P.vac_bin_hi[k] =
static_cast<int>(
579 if (P.physics_option >= 2) {
580 int n_sia = P.i_discrete + P.n_mom * P.I_bin;
581 int n_vac = P.v_discrete + P.n_mom * P.V_bin;
584 n_he = qss ? P.V_bin : P.V_bin + 1;
587 P.N_eq = n_sia + n_vac + n_he + 5;
598 P.cons_off = P.N_eq - 5;
599 P.loop_conversion =
static_cast<int>(
optional_param(p,
"loop_conversion", 0.0));
600 if (P.loop_conversion) {
601 P.sia100_off = P.N_eq;
602 P.sia100_len = (P.physics_option >= 2)
603 ? (P.i_discrete + P.n_mom * P.I_bin)
605 P.N_eq += P.sia100_len;
607 P.conv_n_loop_min =
static_cast<int>(
optional_param(p,
"n_loop_min", 4.0));
608 P.conv_n_j_min =
static_cast<int>(
optional_param(p,
"n_j_min_junc", 30.0));
616 P.conv_absorb_boost =
optional_param(p,
"conv_absorb_boost", 1.0);
617 P.Gamma_uni.assign(P.I, 0.0);
618 P.K_100_grow.assign(P.I, 0.0);
619 P.K_100_shrink.assign(P.I, 0.0);
620 P.G_100.assign(P.I, 0.0);
621 P.Lambda_net_100.assign(P.I, 0.0);
622 for (
int k = 0; k < P.I; ++k) {
623 P.Gamma_uni[k] =
optional_param(p,
"Gamma_uni_" + std::to_string(k), 0.0);
624 P.K_100_grow[k] =
optional_param(p,
"K_100_grow_" + std::to_string(k), 0.0);
625 P.K_100_shrink[k] =
optional_param(p,
"K_100_shrink_" + std::to_string(k), 0.0);
626 P.G_100[k] =
optional_param(p,
"G_100_" + std::to_string(k), 0.0);
627 P.Lambda_net_100[k] =
optional_param(p,
"lambda_net_100_" + std::to_string(k), 0.0);
634 P.Lambda_net_void.assign(P.V, 0.0);
635 for (
int k = 0; k < P.V; ++k)
636 P.Lambda_net_void[k] =
optional_param(p,
"lambda_net_void_" + std::to_string(k), 0.0);
639 for (
int k = 0; k < P.N_eq; ++k)
655 static_cast<double>(P.N_eq - 1)));
657 static_cast<double>(P.N_eq - 1)));
658 P.max_order =
static_cast<int>(
optional_param(p,
"max_order", 4.0));
663 P.window_mode =
static_cast<int>(
optional_param(p,
"window_mode", 0.0));
665 P.window_width =
static_cast<int>(
optional_param(p,
"window_width",
666 static_cast<double>(std::max(P.I, P.V))));
667 P.concentration_threshold =
optional_param(p,
"concentration_threshold", 1e-18);
668 P.window_pad =
static_cast<int>(
optional_param(p,
"window_pad", 10.0));
670 P.window_pad_v =
static_cast<int>(
optional_param(p,
"window_pad_v",
671 static_cast<double>(P.window_pad)));
672 P.window_expand_factor =
optional_param(p,
"window_expand_factor", 0.0);
673 P.window_check_every =
static_cast<int>(
optional_param(p,
"window_check_every", 1.0));
674 P.window_C_contract =
optional_param(p,
"window_C_contract", 0.0);
675 P.window_min_active_i =
static_cast<int>(
optional_param(p,
"window_min_active_i", 5.0));
679 P.Ni_extend_margin =
static_cast<int>(
optional_param(p,
"Ni_extend_margin", 0.0));
698 const bool gmres = (P.linsol == 2);
699 const bool full_domain = (P.window_mode == 0);
700 const bool has_coalescence = (P.i_mobile >= 2) || (P.v_mobile >= 2);
706 const bool use_woodbury = gmres && full_domain && has_coalescence
707 && !P.loop_conversion;
709 use_woodbury ? 1.0 : 0.0));
713 static_cast<double>(std::max(2 * P.i_mobile, 2 * P.v_mobile) + 1)));
716 static_cast<double>(P.i_mobile + P.v_mobile)));
720 if (P.prec_type == 1) {
721 P.prec_mobile_idx.resize(P.prec_rank);
723 for (
int k = 0; k < P.i_mobile; ++k)
724 P.prec_mobile_idx[k] = k;
727 const int vac_off = (P.physics_option >= 2)
728 ? (P.i_discrete + P.n_mom * P.I_bin)
730 for (
int k = 0; k < P.v_mobile; ++k)
731 P.prec_mobile_idx[P.i_mobile + k] = vac_off + k;