Skip to content

Commit ed2c670

Browse files
author
Ben Prather
committed
Disable B3 reconnection near outer boundary, unstable.
Also add enough density to always recover momenta after Kastaun inversion. Should eliminate "bad velocity" failures.
1 parent 0b32d3b commit ed2c670

5 files changed

Lines changed: 37 additions & 15 deletions

File tree

kharma/b_ct/b_ct.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ std::shared_ptr<KHARMAPackage> B_CT::Initialize(ParameterInput *pin, std::shared
7373
if (lazy_prolongation && pin->GetString("parthenon/mesh", "refinement") == "adaptive")
7474
throw std::runtime_error("Cannot use non-divergence-preserving prolongation in AMR!");
7575

76+
// TODO don't set this unless we're reconnecting at boundaries (can't just check, we load Boundaries pkg later)
77+
int reconnection_outer_buffer = pin->GetOrAddInteger("b_field", "reconnection_outer_buffer", 5);
78+
params.Add("reconnection_outer_buffer", reconnection_outer_buffer);
79+
7680
// FIELDS
7781

7882
// Flags for B fields on faces.

kharma/b_ct/b_ct_boundaries.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ void B_CT::ReconnectBoundaryB3(MeshBlockData<Real> *rc, IndexDomain domain, cons
299299

300300
const Real gam = pmb->packages.Get("GRMHD")->Param<Real>("gamma");
301301

302+
const int reconnection_outer_buffer = pmb->packages.Get("B_CT")->Param<int>("reconnection_outer_buffer");
303+
302304
const Floors::Prescription floors = pmb->packages.Get("Floors")->Param<Floors::Prescription>("prescription");
303305
// Don't be fooled, this function does *not* support/preserve EMHD values
304306
const EMHD::EMHD_parameters& emhd_params = EMHD::GetEMHDParameters(pmb->packages);
@@ -308,7 +310,7 @@ void B_CT::ReconnectBoundaryB3(MeshBlockData<Real> *rc, IndexDomain domain, cons
308310
IndexRange3 bi = KDomain::GetRange(rc, IndexDomain::interior, F3, coarse);
309311
const int jf = (binner) ? bi.js : bi.je; // j index of last zone next to pole
310312
parthenon::par_for_outer(DEFAULT_OUTER_LOOP_PATTERN, "reduce_B3_" + bname, pmb->exec_space,
311-
0, 1, 0, fpack.GetDim(4)-1, b.is, b.ie,
313+
0, 1, 0, fpack.GetDim(4)-1, b.is, b.ie - reconnection_outer_buffer,
312314
KOKKOS_LAMBDA(parthenon::team_mbr_t member, const int &v, const int& i) {
313315
// Sum the first rank of B3
314316
double B3_sum = 0.;

kharma/boundaries/boundaries.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,13 @@ std::shared_ptr<KHARMAPackage> KBoundaries::Initialize(ParameterInput *pin, std:
6767
// Option to excise a bit at the poles when calculating fluxes
6868
bool excise_polar_flux = pin->GetOrAddBoolean("boundaries", "excise_polar_flux", false);
6969
params.Add("excise_polar_flux", excise_polar_flux);
70-
if (excise_polar_flux) {
71-
// These options are opposites
72-
pin->SetBoolean("boundaries", "zero_polar_flux", false);
73-
// TODO check whether the user explicitly set these false and yell instead of silent override
74-
pin->SetBoolean("boundaries", "reconnect_B3_inner_x2", true);
75-
pin->SetBoolean("boundaries", "reconnect_B3_outer_x2", true);
76-
// These are themselves unstable, and don't help the wake much
77-
//pin->SetBoolean("boundaries", "cancel_T3_inner_x2", true);
78-
//pin->SetBoolean("boundaries", "cancel_T3_outer_x2", true);
79-
}
8070
// Otherwise, those fluxes should be zero
81-
bool zero_polar_flux = pin->GetOrAddBoolean("boundaries", "zero_polar_flux", spherical);
71+
bool zero_polar_flux = pin->GetOrAddBoolean("boundaries", "zero_polar_flux", spherical && !excise_polar_flux);
8272
params.Add("zero_polar_flux", zero_polar_flux);
73+
// Throw an error if both are set
74+
if (excise_polar_flux && zero_polar_flux) {
75+
throw std::runtime_error("Cannot set both boundaries/excise_polar_flux and boundaries/zero_polar_flux!");
76+
}
8377

8478
// Apply physical boundaries to conserved GRMHD variables rho u^r, T^mu_nu
8579
// Probably inadvisable?
@@ -199,7 +193,8 @@ std::shared_ptr<KHARMAPackage> KBoundaries::Initialize(ParameterInput *pin, std:
199193
bool clean_face_B = pin->GetOrAddBoolean("boundaries", "clean_face_B_" + bname, (btype == "outflow"));
200194
params.Add("clean_face_B_"+bname, clean_face_B);
201195
// Forcibly reconnect field loops that get trapped around the polar boundary
202-
bool reconnect_B3 = pin->GetOrAddBoolean("boundaries", "reconnect_B3_" + bname, false);
196+
// Needed to keep excised-flux transmitting boundaries stable
197+
bool reconnect_B3 = pin->GetOrAddBoolean("boundaries", "reconnect_B3_" + bname, excise_flux);
203198
params.Add("reconnect_B3_"+bname, reconnect_B3);
204199

205200
// Special EMF averaging. Allows B3 to "slip" around the pole

kharma/floors/floors.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class Prescription {
102102
// Constant sanity limits
103103
Real rho_min_const, u_min_const;
104104
// Purely geometric limits
105-
Real rho_min_geom, u_min_geom, r_char;
105+
Real rho_min_geom, u_min_geom, r_char, floors_switch_r;
106106
// Dynamic limits on magnetization/temperature
107107
Real bsq_over_rho_max, bsq_over_u_max, u_over_rho_max;
108108
// Limit entropy
@@ -113,7 +113,8 @@ class Prescription {
113113
bool use_r_char, temp_adjust_u, adjust_k;
114114
// Radius dependent floors?
115115
bool radius_dependent_floors;
116-
Real floors_switch_r;
116+
// Add density to respect the gamma ceiling?
117+
bool use_rho_to_slow;
117118
};
118119

119120
inline Prescription MakePrescription(parthenon::ParameterInput *pin, std::string block="floors")
@@ -163,6 +164,8 @@ inline Prescription MakePrescription(parthenon::ParameterInput *pin, std::string
163164
p.radius_dependent_floors = pin->GetOrAddBoolean("floors", "radius_dependent_floors", false);
164165
p.floors_switch_r = pin->GetOrAddReal("floors", "floors_switch_r", 50.);
165166

167+
p.use_rho_to_slow = pin->GetOrAddBoolean("floors", "use_rho_to_slow", true);
168+
166169
return p;
167170
}
168171

kharma/inverter/inverter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,24 @@ inline void BlockPerformInversion(MeshBlockData<Real> *rc, IndexDomain domain, b
203203
if (normal_frame_floors) {
204204
fflagl |= Floors::determine_floors(G, P, m_p, gam, k, j, i, inverter_floors, inverter_floors_inner,
205205
rhoflr_max, uflr_max);
206+
// Add a floor to density which controls wayward velocities
207+
if (inverter_floors.use_rho_to_slow) {
208+
// Calculate necessary rho
209+
const Real rho = std::max(P(m_p.RHO, k, j, i), rhoflr_max);
210+
const Real u = std::max(P(m_p.UU, k, j, i), uflr_max);
211+
const Real rhoh = rho + (gam + 1) * u;
212+
const Real S = m::sqrt(U(m_u.U1, k, j, i) * U(m_u.U1, k, j, i) +
213+
U(m_u.U2, k, j, i) * U(m_u.U2, k, j, i) +
214+
U(m_u.U3, k, j, i) * U(m_u.U3, k, j, i));
215+
const Real gamma = GRMHD::lorentz_calc(G, P, m_p, k, j, i, Loci::center);
216+
const Real rhoh_min = S / gamma * gamma * m::sqrt(1 - 1 / (gamma * gamma));
217+
if (rhoh < rhoh_min) {
218+
rhoflr_max = rho * rhoh_min/rhoh;
219+
uflr_max = u * rhoh_min/rhoh;
220+
}
221+
} // TODO try adding at different temperatures/only density or energy
222+
// TODO after adding here, we can use a much simpler solve:
223+
// Spar^2/(rhoh^2 W^4) + Sperp^2/(rhoh W^2 + B^2)^2 + 1/W^2 - 1 = 0
206224
} else {
207225
// Bare minimum floors for numerics, before applying the rest in user-selected frame
208226
rhoflr_max = inverter_floors.rho_min_const;

0 commit comments

Comments
 (0)