@@ -67,12 +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) { // These options are *completely* incompatible
71- pin->SetBoolean (" boundaries" , " zero_polar_flux" , false );
72- }
7370 // Otherwise, those fluxes should be zero
74- 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 );
7572 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+ }
7677
7778 // Apply physical boundaries to conserved GRMHD variables rho u^r, T^mu_nu
7879 // Probably inadvisable?
@@ -174,8 +175,7 @@ std::shared_ptr<KHARMAPackage> KBoundaries::Initialize(ParameterInput *pin, std:
174175 // Ensure fluxes through the zero-size face at the pole are zero
175176 bool zero_flux = pin->GetOrAddBoolean (" boundaries" , " zero_flux_" + bname, zero_polar_flux && bdir == X2DIR );
176177 params.Add (" zero_flux_" + bname, zero_flux);
177-
178- // Ensure fluxes through the zero-size face at the pole are zero
178+ // OR allow them via faux-excision
179179 bool excise_flux = pin->GetOrAddBoolean (" boundaries" , " excise_flux_" + bname, excise_polar_flux && bdir == X2DIR );
180180 params.Add (" excise_flux_" + bname, excise_flux);
181181
@@ -194,11 +194,12 @@ std::shared_ptr<KHARMAPackage> KBoundaries::Initialize(ParameterInput *pin, std:
194194 bool clean_face_B = pin->GetOrAddBoolean (" boundaries" , " clean_face_B_" + bname, (btype == " outflow" ));
195195 params.Add (" clean_face_B_" +bname, clean_face_B);
196196 // Forcibly reconnect field loops that get trapped around the polar boundary
197- bool reconnect_B3 = pin->GetOrAddBoolean (" boundaries" , " reconnect_B3_" + bname, false );
197+ // Needed to keep excised-flux transmitting boundaries stable
198+ bool reconnect_B3 = pin->GetOrAddBoolean (" boundaries" , " reconnect_B3_" + bname, excise_flux);
198199 params.Add (" reconnect_B3_" +bname, reconnect_B3);
199200
200- // Special EMF averaging. Allows B slippage, e.g. around pole for transmitting conditions
201- // Useful for certain dirichlet conditions e.g. multizone
201+ // Special EMF averaging. Allows B3 to "slip" around the pole
202+ // Also useful to allow coherent motion even with Dirichlet boundaries, for e.g. multizone
202203 bool average_EMF = pin->GetOrAddBoolean (" boundaries" , " average_EMF_" + bname, (btype == " transmitting" ));
203204 params.Add (" average_EMF_" +bname, average_EMF);
204205 // Otherwise, always zero EMFs to prevent B field escaping the domain in polar/dirichlet bounds
@@ -705,6 +706,10 @@ TaskStatus KBoundaries::FixFlux(MeshData<Real> *md)
705706 if (pmb->boundary_flag [bface] == BoundaryFlag::user) {
706707 if (bdir != 2 ) throw std::runtime_error (" Excised polar fluxes only fully implemented in X2!" );
707708
709+ // Pack w/B to match indices with the `Flux.X` below
710+ // We won't *update* B field though
711+ auto &F = rc->PackVariablesAndFluxes ({Metadata::WithFluxes}, cons_map);
712+
708713 // Going to need the primitive vars
709714 PackIndexMap prims_map;
710715 std::vector<MetadataFlag> prims_flags = {Metadata::GetUserFlag (" Primitive" ), Metadata::Cell};
@@ -771,7 +776,8 @@ TaskStatus KBoundaries::FixFlux(MeshData<Real> *md)
771776
772777 // Use LLF flux
773778 PLOOP {
774- F.flux (dir, ip, k, j, i) = Flux::llf (Fl_all (ip, k, j, i), Fr_all (ip, k, j, i),
779+ if (ip != m_u.B1 && ip != m_u.B2 && ip != m_u.B3 )
780+ F.flux (dir, ip, k, j, i) = Flux::llf (Fl_all (ip, k, j, i), Fr_all (ip, k, j, i),
775781 cmax (dir-1 , k, j, i), cmin (dir-1 , k, j, i),
776782 Ul_all (ip, k, j, i), Ur_all (ip, k, j, i)) * 0.5 ;
777783 }
@@ -818,21 +824,19 @@ TaskStatus KBoundaries::FixFlux(MeshData<Real> *md)
818824
819825 // Use LLF flux
820826 PLOOP {
821- F.flux (bdir, ip, k, j, i) = Flux::llf (Fl_all (ip, k, j, i), Fr_all (ip, k, j, i),
822- cmax (bdir-1 , k, j, i), cmin (bdir-1 , k, j, i),
823- Ul_all (ip, k, j, i), Ur_all (ip, k, j, i));
824- // Reduce the X1 flux in a semi-consistent way
825- const int jc = (binner) ? j_cell + 1 : j_cell;
826- F.flux (X1DIR , ip, k, j_cell, i) *= 0.5
827- * (G.gdet (Loci::face1, j_cell, i) + G.gdet (Loci::corner, jc, i)) / 2 / G.gdet (Loci::face1, j_cell, i);
828- // This is also a decent guess, but less accurate than recalculating as above
829- // F.flux(X3DIR, ip, k, j_cell, i) *= 0.5
830- // * G.gdet(loc, j_cell, i) / G.gdet(Loci::center, j_cell, i);
827+ if (ip != m_u.B1 && ip != m_u.B2 && ip != m_u.B3 ) {
828+ F.flux (bdir, ip, k, j, i) = Flux::llf (Fl_all (ip, k, j, i), Fr_all (ip, k, j, i),
829+ cmax (bdir-1 , k, j, i), cmin (bdir-1 , k, j, i),
830+ Ul_all (ip, k, j, i), Ur_all (ip, k, j, i));
831+ // Reduce the X1 flux in a semi-consistent way
832+ const int jc = (binner) ? j_cell + 1 : j_cell;
833+ F.flux (X1DIR , ip, k, j_cell, i) *= 0.5
834+ * (G.gdet (Loci::face1, j_cell, i) + G.gdet (Loci::corner, jc, i)) / 2 / G.gdet (Loci::face1, j_cell, i);
835+ // This is also a decent guess, but less accurate than recalculating as above
836+ // F.flux(X3DIR, ip, k, j_cell, i) *= 0.5
837+ // * G.gdet(loc, j_cell, i) / G.gdet(Loci::center, j_cell, i);
838+ }
831839 }
832-
833- // Account for the half-size in the timestep later
834- cmax (bdir-1 , k, j, i) *= 2 ;
835- cmin (bdir-1 , k, j, i) *= 2 ;
836840 }
837841 );
838842 // Then average to make absolutely sure fluxes match
@@ -904,7 +908,9 @@ void KBoundaries::AddSource(MeshData<Real> *md, MeshData<Real> *mdudt, IndexDoma
904908 b.ks = b.ke = (binner) ? bi.ks : bi.ke ;
905909 }
906910
907- auto &dUdt = rc->PackVariables ({Metadata::WithFluxes});
911+ // The magnetic field is probably defined at faces; even if it's defined in cells,
912+ // we shouldn't be monkeying with it. We just do not adjust it here.
913+ auto &dUdt = rc->PackVariables ({Metadata::GetUserFlag (" HD" ), Metadata::WithFluxes});
908914 const auto & G = pmb->coords ;
909915 const Loci loc = (binner) ? Loci::outer_half : Loci::inner_half;
910916
0 commit comments