From 1529075216cceddf50ec818fd1512dafe29df25c Mon Sep 17 00:00:00 2001 From: HPC user Date: Wed, 13 Dec 2023 23:33:08 +0100 Subject: [PATCH] Formatting --- src/pgen/blast.cpp | 6 +- src/pgen/cloud.cpp | 16 +- src/pgen/cluster.cpp | 507 +++++----- src/pgen/cluster/cluster_gravity.hpp | 71 +- src/pgen/cluster/cluster_gravity_original.hpp | 6 +- src/pgen/cluster/cluster_gravity_working.hpp | 47 +- .../cluster/entropy_isothermal_profiles.hpp | 19 +- src/pgen/cluster/entropy_profiles.hpp | 24 +- .../hydrostatic_equilibrium_sphere.cpp | 36 +- .../hydrostatic_equilibrium_sphere.hpp | 20 +- src/pgen/cluster/isothermal_sphere.cpp | 4 +- src/pgen/cluster/isothermal_sphere.hpp | 60 +- src/pgen/old_cluster/cluster_16nov.cpp | 890 ++++++++--------- src/pgen/old_cluster/cluster_17nov.cpp | 911 +++++++++--------- src/pgen/old_cluster/cluster_22nov.cpp | 778 +++++++-------- src/pgen/old_cluster/cluster_divartifact.cpp | 782 +++++++-------- src/pgen/old_cluster/cluster_modified.cpp | 129 ++- src/pgen/old_cluster/cluster_temp.cpp | 911 +++++++++--------- src/pgen/old_cluster/cluster_working.cpp | 296 +++--- 19 files changed, 2811 insertions(+), 2702 deletions(-) diff --git a/src/pgen/blast.cpp b/src/pgen/blast.cpp index c4aa0919..659af95f 100644 --- a/src/pgen/blast.cpp +++ b/src/pgen/blast.cpp @@ -131,16 +131,16 @@ void ProblemGenerator(MeshBlock *pmb, ParameterInput *pin) { Real drat = pin->GetOrAddReal("problem/blast", "density_ratio", 1.0); Real gamma = pin->GetOrAddReal("hydro", "gamma", 5 / 3); Real gm1 = gamma - 1.0; - + // get coordinates of center of blast, and convert to Cartesian if necessary Real x0 = pin->GetOrAddReal("problem/blast", "x1_0", 0.0); Real y0 = pin->GetOrAddReal("problem/blast", "x2_0", 0.0); Real z0 = pin->GetOrAddReal("problem/blast", "x3_0", 0.0); - + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + // initialize conserved variables auto &rc = pmb->meshblock_data.Get(); auto &u_dev = rc->Get("cons").data; diff --git a/src/pgen/cloud.cpp b/src/pgen/cloud.cpp index 086b9b38..f0899107 100644 --- a/src/pgen/cloud.cpp +++ b/src/pgen/cloud.cpp @@ -143,7 +143,7 @@ void InitUserMeshData(Mesh *mesh, ParameterInput *pin) { // \brief Problem Generator for the cloud in wind setup void ProblemGenerator(MeshBlock *pmb, ParameterInput *pin) { - + auto hydro_pkg = pmb->packages.Get("Hydro"); auto ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); auto jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); @@ -157,9 +157,9 @@ void ProblemGenerator(MeshBlock *pmb, ParameterInput *pin) { PARTHENON_FAIL("Requested to initialize magnetic fields by `cloud/plasma_beta > 0`, " "but `hydro/fluid` is not supporting MHD."); } - + auto steepness = pin->GetOrAddReal("problem/cloud", "cloud_steepness", 10); - + // initialize conserved variables auto &mbd = pmb->meshblock_data.Get(); auto &u_dev = mbd->Get("cons").data; @@ -192,13 +192,13 @@ void ProblemGenerator(MeshBlock *pmb, ParameterInput *pin) { u(IM2, k, j, i) = mom; // Can use rhoe_wind here as simulation is setup in pressure equil. u(IEN, k, j, i) = rhoe_wind + 0.5 * mom * mom / rho; - + if (mhd_enabled) { u(IB1, k, j, i) = Bx; u(IB2, k, j, i) = By; u(IEN, k, j, i) += 0.5 * (Bx * Bx + By * By); } - + // Init passive scalars for (auto n = nhydro; n < nhydro + nscalars; n++) { if (rad <= r_cloud) { @@ -241,14 +241,14 @@ void InflowWindX2(std::shared_ptr> &mbd, bool coarse) { } parthenon::AmrTag ProblemCheckRefinementBlock(MeshBlockData *mbd) { - + auto pmb = mbd->GetBlockPointer(); auto w = mbd->Get("prim").data; - + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto nhydro = hydro_pkg->Param("nhydro"); diff --git a/src/pgen/cluster.cpp b/src/pgen/cluster.cpp index 3f03755f..798a7f22 100644 --- a/src/pgen/cluster.cpp +++ b/src/pgen/cluster.cpp @@ -117,22 +117,22 @@ Real ClusterEstimateTimestep(MeshData *md) { //======================================================================================== void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hydro_pkg) { - + /************************************************************ * Read Uniform Gas ************************************************************/ - + const bool init_uniform_gas = pin->GetOrAddBoolean("problem/cluster/uniform_gas", "init_uniform_gas", false); hydro_pkg->AddParam<>("init_uniform_gas", init_uniform_gas); - + if (init_uniform_gas) { const Real uniform_gas_rho = pin->GetReal("problem/cluster/uniform_gas", "rho"); const Real uniform_gas_ux = pin->GetReal("problem/cluster/uniform_gas", "ux"); const Real uniform_gas_uy = pin->GetReal("problem/cluster/uniform_gas", "uy"); const Real uniform_gas_uz = pin->GetReal("problem/cluster/uniform_gas", "uz"); const Real uniform_gas_pres = pin->GetReal("problem/cluster/uniform_gas", "pres"); - + hydro_pkg->AddParam<>("uniform_gas_rho", uniform_gas_rho); hydro_pkg->AddParam<>("uniform_gas_ux", uniform_gas_ux); hydro_pkg->AddParam<>("uniform_gas_uy", uniform_gas_uy); @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -238,15 +236,15 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd /************************************************************ * Read SNIA Feedback ************************************************************/ - + SNIAFeedback snia_feedback(pin, hydro_pkg); - + /************************************************************ * Read Stellar Feedback ************************************************************/ - + StellarFeedback stellar_feedback(pin, hydro_pkg); - + /************************************************************ * Read Clips (ceilings and floors) ************************************************************/ @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -297,11 +295,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::string reduction_strs[] = {"stellar_mass", "added_dfloor_mass", "removed_eceil_energy", "removed_vceil_energy", "added_vAceil_mass"}; - + // Add a param for each reduction, then add it as a summation reduction for // history outputs auto hst_vars = hydro_pkg->Param(parthenon::hist_param_key); - + for (auto reduction_str : reduction_strs) { hydro_pkg->AddParam(reduction_str, 0.0, true); hst_vars.emplace_back(parthenon::HistoryOutputVar( @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,55 +509,57 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); - const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - + const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - - IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); - IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); - IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); + IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); + IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto init_perseus = pin->GetOrAddBoolean("problem/cluster/hydrostatic_equilibrium", "init_perseus", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto init_perseus = pin->GetOrAddBoolean( + "problem/cluster/hydrostatic_equilibrium", "init_perseus", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -566,50 +570,52 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - - } if (init_perseus) { - + } + if (init_perseus) { + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Units const Real mh = units.mh(); const Real k_boltzmann = units.k_boltzmann(); - - const Real mu = hydro_pkg->Param("mu"); + + const Real mu = hydro_pkg->Param("mu"); const Real mu_e = hydro_pkg->Param("mu_e"); - + // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + const Real re3 = r * 1e3; // Mpc to kpc - + // Get pressure and density from generated profile - const Real ne_r = 0.0192 * 1 / (1 + std::pow(re3 / 18, 3)) + - 0.046 * 1 / std::pow((1 + std::pow(re3 / 57, 2)),1.8) + - 0.0048 * 1 / std::pow((1 + std::pow(re3 / 200, 2)),0.87); // cgs units (cm-3) - const Real T_r = 8.12e7 * (1 + std::pow(re3 / 71, 3)) / (2.3 + std::pow(re3 / 71, 3)); // K - - const Real ne_r_cu = ne_r * std::pow(units.cm(),-3); // Code units, Mpc^-3 - - const Real rho_r = mu_e * mh * ne_r_cu; // From ne_r (conversion) - const Real P_r = k_boltzmann * (mu_e / mu) * ne_r_cu * T_r; // From T_r (conversion) - + const Real ne_r = + 0.0192 * 1 / (1 + std::pow(re3 / 18, 3)) + + 0.046 * 1 / std::pow((1 + std::pow(re3 / 57, 2)), 1.8) + + 0.0048 * 1 / + std::pow((1 + std::pow(re3 / 200, 2)), 0.87); // cgs units (cm-3) + const Real T_r = + 8.12e7 * (1 + std::pow(re3 / 71, 3)) / (2.3 + std::pow(re3 / 71, 3)); // K + + const Real ne_r_cu = ne_r * std::pow(units.cm(), -3); // Code units, Mpc^-3 + + const Real rho_r = mu_e * mh * ne_r_cu; // From ne_r (conversion) + const Real P_r = + k_boltzmann * (mu_e / mu) * ne_r_cu * T_r; // From T_r (conversion) + u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else { - + /************************************************************ * Initialize a HydrostaticEquilibriumSphere ************************************************************/ @@ -617,34 +623,32 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile - const Real P_r = P_rho_profile.P_from_r(r); + const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - - //u(IDN, k, j, i) = rho_r; + + // u(IDN, k, j, i) = rho_r; u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -652,7 +656,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -662,14 +666,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -686,22 +690,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -709,7 +713,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -723,7 +726,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -739,7 +742,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -751,66 +754,74 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - - auto hydro_pkg = pmb->packages.Get("Hydro"); + + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool spherical_cloud = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_cloud", false); - const bool cluster_cloud = pin->GetOrAddBoolean("problem/cluster/init_perturb", "cluster_cloud", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool spherical_cloud = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_cloud", false); + const bool cluster_cloud = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "cluster_cloud", false); + Real passive_scalar = 0.0; // Not useful here - + if (cluster_cloud == true) { - - const Real x_cloud = pin->GetOrAddReal("problem/cluster/init_perturb", "x_cloud", 0.0); // 0.0 pc - const Real y_cloud = pin->GetOrAddReal("problem/cluster/init_perturb", "y_cloud", 5e-2); // 100 pc - const Real r_cloud = pin->GetOrAddReal("problem/cluster/init_perturb", "r_cloud", 1e-4); // 100 pc - const Real rho_cloud = pin->GetOrAddReal("problem/cluster/init_perturb", "rho_cloud", 150.0); // 1e-24 g/cm^3 - const Real steepness = pin->GetOrAddReal("problem/cluster/init_perturb", "steep_cloud", 10.0); - - Real passive_scalar = 0.0; // Useless - + + const Real x_cloud = + pin->GetOrAddReal("problem/cluster/init_perturb", "x_cloud", 0.0); // 0.0 pc + const Real y_cloud = + pin->GetOrAddReal("problem/cluster/init_perturb", "y_cloud", 5e-2); // 100 pc + const Real r_cloud = + pin->GetOrAddReal("problem/cluster/init_perturb", "r_cloud", 1e-4); // 100 pc + const Real rho_cloud = pin->GetOrAddReal("problem/cluster/init_perturb", "rho_cloud", + 150.0); // 1e-24 g/cm^3 + const Real steepness = + pin->GetOrAddReal("problem/cluster/init_perturb", "steep_cloud", 10.0); + + Real passive_scalar = 0.0; // Useless + /* for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; auto &coords = pmb->coords; - + Real r_min = 1e6; - + for (int k = kb.s; k <= kb.e; k++) { for (int j = jb.s; j <= jb.e; j++) { for (int i = ib.s; i <= ib.e; i++) { - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); - + if (r < r_min) {r_min = r;} - + } } } @@ -820,119 +831,124 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::AmrTag::same;} } */ - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x - x_cloud) + SQR(y - y_cloud) + SQR(z)); - - Real rho = rho_cloud * (1.0 - std::tanh(steepness * (r / r_cloud - 1.0))); + + Real rho = rho_cloud * (1.0 - std::tanh(steepness * (r / r_cloud - 1.0))); u(IDN, k, j, i) += rho; - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real box_size_over_two = pin->GetOrAddReal("problem/cluster/init_perturb", "xmax", 0.250); - - // Loading files - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real box_size_over_two = + pin->GetOrAddReal("problem/cluster/init_perturb", "xmax", 0.250); + + // Loading files + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 512; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - - // Setting up the perturbations - + + // Setting up the perturbations + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); - - // Getting the corresponding index in the - const Real rho_init_index_x = floor((x + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); - const Real rho_init_index_y = floor((y + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); - const Real rho_init_index_z = floor((z + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); - - //const Real damping = 1 - std::exp(r - box_size_over_two); - - if ((rho_init_index_x >= 0) && (rho_init_index_x <= rho_init_size - 1) && (rho_init_index_y >= 0) && (rho_init_index_y <= rho_init_size - 1) && (rho_init_index_z >= 0) && (rho_init_index_z <= rho_init_size - 1)) { - - // Case where the box is filled with perturbations of equal mean amplitude - - //u(IDN, k, j, i) += perturb_amplitude * rho_init[rho_init_index_x][rho_init_index_y][rho_init_index_z] * (u(IDN, k, j, i) / 29.6) * std::max(0.0,damping); - u(IDN, k, j, i) += perturb_amplitude * rho_init[rho_init_index_x][rho_init_index_y][rho_init_index_z]; - + + // Getting the corresponding index in the + const Real rho_init_index_x = floor( + (x + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); + const Real rho_init_index_y = floor( + (y + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); + const Real rho_init_index_z = floor( + (z + box_size_over_two) / (2 * box_size_over_two) * (rho_init_size - 1)); + + // const Real damping = 1 - std::exp(r - box_size_over_two); + + if ((rho_init_index_x >= 0) && (rho_init_index_x <= rho_init_size - 1) && + (rho_init_index_y >= 0) && (rho_init_index_y <= rho_init_size - 1) && + (rho_init_index_z >= 0) && (rho_init_index_z <= rho_init_size - 1)) { + + // Case where the box is filled with perturbations of equal mean amplitude + + // u(IDN, k, j, i) += perturb_amplitude * + // rho_init[rho_init_index_x][rho_init_index_y][rho_init_index_z] * (u(IDN, k, + // j, i) / 29.6) * std::max(0.0,damping); + u(IDN, k, j, i) += + perturb_amplitude * + rho_init[rho_init_index_x][rho_init_index_y][rho_init_index_z]; } - }, passive_scalar); - - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real v2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { @@ -944,11 +960,11 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_REQUIRE( u(IM1, k, j, i) == 0.0 && u(IM2, k, j, i) == 0.0 && u(IM3, k, j, i) == 0.0, "Found existing non-zero velocity when setting velocity perturbations."); - + u(IM1, k, j, i) = rho * perturb_pack(b, 0, k, j, i); u(IM2, k, j, i) = rho * perturb_pack(b, 1, k, j, i); u(IM3, k, j, i) = rho * perturb_pack(b, 2, k, j, i); - + // No need to touch the energy yet as we'll normalize later lsum += (SQR(u(IM1, k, j, i)) + SQR(u(IM2, k, j, i)) + SQR(u(IM3, k, j, i))) * @@ -960,12 +976,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -980,14 +996,15 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ - const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto r_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "r_scale", 0.1); - + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto r_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "r_scale", 0.1); + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -995,45 +1012,45 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - + // Modifying the magnetic potential so that it follows the rho profile - + /* pmb->par_for( "Init sigma_b", 0, num_blocks - 1, kb.s-1, kb.e+1, jb.s-1, jb.e+1, ib.s-1, ib.e+1, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + perturb_pack(b, 0, k, j, i) *= 1 / (1 + (r / r_scale)); perturb_pack(b, 1, k, j, i) *= 1 / (1 + (r / r_scale)); perturb_pack(b, 2, k, j, i) *= 1 / (1 + (r / r_scale)); - + }); */ - + pmb->par_reduce( "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { @@ -1065,17 +1082,17 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { coords.CellVolume(k, j, i); }, b2_sum); - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - + pmb->par_for( "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -1147,15 +1164,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { @@ -1179,11 +1196,11 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { KOKKOS_LAMBDA(const int k, const int j, const int i) { // get gas properties const Real rho = prim(IDN, k, j, i); - const Real P = prim(IPR, k, j, i); - const Real Bx = prim(IB1, k, j, i); - const Real By = prim(IB2, k, j, i); - const Real Bz = prim(IB3, k, j, i); - const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); + const Real P = prim(IPR, k, j, i); + const Real Bx = prim(IB1, k, j, i); + const Real By = prim(IB2, k, j, i); + const Real Bz = prim(IB3, k, j, i); + const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); // compute Alfven mach number const Real v_A = std::sqrt(B2 / rho); diff --git a/src/pgen/cluster/cluster_gravity.hpp b/src/pgen/cluster/cluster_gravity.hpp index dd7c20a0..7210aa46 100644 --- a/src/pgen/cluster/cluster_gravity.hpp +++ b/src/pgen/cluster/cluster_gravity.hpp @@ -17,7 +17,7 @@ namespace cluster { // Types of BCG's -enum class BCG {NONE, HERNQUIST, VAUCOULEURS, ISOTHERMAL}; +enum class BCG { NONE, HERNQUIST, VAUCOULEURS, ISOTHERMAL }; // Hernquiest BCG: Hernquist 1990 DOI:10.1086/168845 /************************************************************ @@ -56,7 +56,7 @@ class ClusterGravity { // Static Helper functions to calculate constants to minimize in-kernel work // ie. compute the constants characterizing the profile (M_nfw, etc...) - + static parthenon::Real calc_R_nfw_s(const parthenon::Real rho_crit, const parthenon::Real m_nfw_200, const parthenon::Real c_nfw) { @@ -118,9 +118,9 @@ class ClusterGravity { // calculate the BCG density profile ClusterGravity(parthenon::ParameterInput *pin) { Units units(pin); - + gravitationnal_const_ = units.gravitational_constant(); - + // Determine which element to include include_nfw_g_ = pin->GetOrAddBoolean("problem/cluster/gravity", "include_nfw_g", false); @@ -135,14 +135,14 @@ class ClusterGravity { } else if (which_bcg_g_str == "VAUCOULEURS") { which_bcg_g_ = BCG::VAUCOULEURS; } - - else { + + else { std::stringstream msg; msg << "### FATAL ERROR in function [InitUserMeshData]" << std::endl << "Unknown BCG type " << which_bcg_g_str << std::endl; PARTHENON_FAIL(msg); } - + include_smbh_g_ = pin->GetOrAddBoolean("problem/cluster/gravity", "include_smbh_g", false); @@ -151,7 +151,7 @@ class ClusterGravity { "problem/cluster", "hubble_parameter", 70 * units.km_s() / units.mpc()); const parthenon::Real rho_crit = 3 * hubble_parameter * hubble_parameter / (8 * M_PI * units.gravitational_constant()); - + const auto He_mass_fraction = pin->GetReal("hydro", "He_mass_fraction"); const auto mu = 1 / (He_mass_fraction * 3. / 4. + (1 - He_mass_fraction) * 2); const parthenon::Real M_nfw_200 = @@ -160,33 +160,33 @@ class ClusterGravity { pin->GetOrAddReal("problem/cluster/gravity", "c_nfw", 6.81); r_nfw_s_ = calc_R_nfw_s(rho_crit, M_nfw_200, c_nfw); g_const_nfw_ = calc_g_const_nfw(units.gravitational_constant(), M_nfw_200, c_nfw); - + // Initialize the BCG Profile alpha_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "alpha_bcg_s", 0.1); - beta_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "beta_bcg_s", 1.43); + beta_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "beta_bcg_s", 1.43); const parthenon::Real M_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); r_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - T_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); // Temperature in the isothermal case - + T_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", + 10000); // Temperature in the isothermal case + if (which_bcg_g_str == "ISOTHERMAL") { - + g_const_bcg_ = 2 * units.k_boltzmann() * T_bcg_s_ / (mu * units.mh()); - } - + if (which_bcg_g_str == "VAUCOULEURS") { - + g_const_bcg_ = 1; - + } - + else { - - g_const_bcg_ = calc_g_const_bcg(units.gravitational_constant(), which_bcg_g_, M_bcg_s, - r_bcg_s_, alpha_bcg_s_, beta_bcg_s_); + + g_const_bcg_ = calc_g_const_bcg(units.gravitational_constant(), which_bcg_g_, + M_bcg_s, r_bcg_s_, alpha_bcg_s_, beta_bcg_s_); } - + const parthenon::Real m_smbh = pin->GetOrAddReal("problem/cluster/gravity", "m_smbh", 3.4e8 * units.msun()); g_const_smbh_ = calc_g_const_smbh(units.gravitational_constant(), m_smbh), @@ -199,21 +199,21 @@ class ClusterGravity { : ClusterGravity(pin) { hydro_pkg->AddParam<>("cluster_gravity", *this); } - + // Inline functions to compute gravitational acceleration KOKKOS_INLINE_FUNCTION parthenon::Real g_from_r(const parthenon::Real r_in) const __attribute__((always_inline)) { - + const parthenon::Real r = std::max(r_in, smoothing_r_); const parthenon::Real r2 = r * r; - + parthenon::Real g_r = 0; - + // Add NFW gravity if (include_nfw_g_) { g_r += g_const_nfw_ * (log(1 + r / r_nfw_s_) - r / (r + r_nfw_s_)) / r2; } - + // Add BCG gravity switch (which_bcg_g_) { case BCG::NONE: @@ -223,23 +223,24 @@ class ClusterGravity { case BCG::ISOTHERMAL: g_r += g_const_bcg_ / r; case BCG::VAUCOULEURS: - + // From Matthews et al. 2005 parthenon::Real vaucouleurs_K1 = std::pow(1e3 * r, 0.5975) / (3.206e-7); - parthenon::Real vaucouleurs_K2 = std::pow(1e3 * r, 1.849) / (1.861e-6); - parthenon::Real vaucouleurs_K = std::pow(std::pow(vaucouleurs_K1, 0.9) + std::pow(vaucouleurs_K2, 0.9),-1/0.9); - + parthenon::Real vaucouleurs_K2 = std::pow(1e3 * r, 1.849) / (1.861e-6); + parthenon::Real vaucouleurs_K = std::pow( + std::pow(vaucouleurs_K1, 0.9) + std::pow(vaucouleurs_K2, 0.9), -1 / 0.9); + vaucouleurs_K *= (3.15576e+16 * 3.15576e+16 / 3.085677580962325e+24); g_r += 0.8 * vaucouleurs_K; - + break; } - + // Add SMBH, point mass gravity if (include_smbh_g_) { g_r += g_const_smbh_ / r2; } - + return g_r; } // Inline functions to compute density @@ -249,7 +250,7 @@ class ClusterGravity { const parthenon::Real r = std::max(r_in, smoothing_r_); parthenon::Real rho = 0; - + // Add NFW gravity if (include_nfw_g_) { rho += rho_const_nfw_ / (r * pow(r + r_nfw_s_, 2)); diff --git a/src/pgen/cluster/cluster_gravity_original.hpp b/src/pgen/cluster/cluster_gravity_original.hpp index 91acb6de..54192d63 100644 --- a/src/pgen/cluster/cluster_gravity_original.hpp +++ b/src/pgen/cluster/cluster_gravity_original.hpp @@ -54,7 +54,7 @@ class ClusterGravity { // Static Helper functions to calculate constants to minimize in-kernel work // ie. compute the constants characterizing the profile (M_nfw, etc...) - + static parthenon::Real calc_R_nfw_s(const parthenon::Real rho_crit, const parthenon::Real m_nfw_200, const parthenon::Real c_nfw) { @@ -148,7 +148,7 @@ class ClusterGravity { pin->GetOrAddReal("problem/cluster/gravity", "c_nfw", 6.81); r_nfw_s_ = calc_R_nfw_s(rho_crit, M_nfw_200, c_nfw); g_const_nfw_ = calc_g_const_nfw(units.gravitational_constant(), M_nfw_200, c_nfw); - + // Initialize the BCG Profile alpha_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "alpha_bcg_s", 0.1); beta_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "beta_bcg_s", 1.43); @@ -157,7 +157,7 @@ class ClusterGravity { r_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); g_const_bcg_ = calc_g_const_bcg(units.gravitational_constant(), which_bcg_g_, M_bcg_s, r_bcg_s_, alpha_bcg_s_, beta_bcg_s_); - + const parthenon::Real m_smbh = pin->GetOrAddReal("problem/cluster/gravity", "m_smbh", 3.4e8 * units.msun()); g_const_smbh_ = calc_g_const_smbh(units.gravitational_constant(), m_smbh), diff --git a/src/pgen/cluster/cluster_gravity_working.hpp b/src/pgen/cluster/cluster_gravity_working.hpp index ef6b6fb3..0e988134 100644 --- a/src/pgen/cluster/cluster_gravity_working.hpp +++ b/src/pgen/cluster/cluster_gravity_working.hpp @@ -17,7 +17,7 @@ namespace cluster { // Types of BCG's -enum class BCG {NONE, HERNQUIST, ISOTHERMAL}; +enum class BCG { NONE, HERNQUIST, ISOTHERMAL }; // Hernquiest BCG: Hernquist 1990 DOI:10.1086/168845 /************************************************************ @@ -56,7 +56,7 @@ class ClusterGravity { // Static Helper functions to calculate constants to minimize in-kernel work // ie. compute the constants characterizing the profile (M_nfw, etc...) - + static parthenon::Real calc_R_nfw_s(const parthenon::Real rho_crit, const parthenon::Real m_nfw_200, const parthenon::Real c_nfw) { @@ -118,9 +118,9 @@ class ClusterGravity { // calculate the BCG density profile ClusterGravity(parthenon::ParameterInput *pin) { Units units(pin); - + gravitationnal_const_ = units.gravitational_constant(); - + // Determine which element to include include_nfw_g_ = pin->GetOrAddBoolean("problem/cluster/gravity", "include_nfw_g", false); @@ -133,14 +133,14 @@ class ClusterGravity { } else if (which_bcg_g_str == "ISOTHERMAL") { which_bcg_g_ = BCG::ISOTHERMAL; } - - else { + + else { std::stringstream msg; msg << "### FATAL ERROR in function [InitUserMeshData]" << std::endl << "Unknown BCG type " << which_bcg_g_str << std::endl; PARTHENON_FAIL(msg); } - + include_smbh_g_ = pin->GetOrAddBoolean("problem/cluster/gravity", "include_smbh_g", false); @@ -149,7 +149,7 @@ class ClusterGravity { "problem/cluster", "hubble_parameter", 70 * units.km_s() / units.mpc()); const parthenon::Real rho_crit = 3 * hubble_parameter * hubble_parameter / (8 * M_PI * units.gravitational_constant()); - + const auto He_mass_fraction = pin->GetReal("hydro", "He_mass_fraction"); const auto mu = 1 / (He_mass_fraction * 3. / 4. + (1 - He_mass_fraction) * 2); const parthenon::Real M_nfw_200 = @@ -158,27 +158,28 @@ class ClusterGravity { pin->GetOrAddReal("problem/cluster/gravity", "c_nfw", 6.81); r_nfw_s_ = calc_R_nfw_s(rho_crit, M_nfw_200, c_nfw); g_const_nfw_ = calc_g_const_nfw(units.gravitational_constant(), M_nfw_200, c_nfw); - + // Initialize the BCG Profile alpha_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "alpha_bcg_s", 0.1); - beta_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "beta_bcg_s", 1.43); + beta_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "beta_bcg_s", 1.43); const parthenon::Real M_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); r_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - T_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); // Temperature in the isothermal case - + T_bcg_s_ = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", + 10000); // Temperature in the isothermal case + if (which_bcg_g_str == "ISOTHERMAL") { - + g_const_bcg_ = 2 * units.k_boltzmann() * T_bcg_s_ / (mu * units.mh()); - + } - + else { - - g_const_bcg_ = calc_g_const_bcg(units.gravitational_constant(), which_bcg_g_, M_bcg_s, - r_bcg_s_, alpha_bcg_s_, beta_bcg_s_); + + g_const_bcg_ = calc_g_const_bcg(units.gravitational_constant(), which_bcg_g_, + M_bcg_s, r_bcg_s_, alpha_bcg_s_, beta_bcg_s_); } - + const parthenon::Real m_smbh = pin->GetOrAddReal("problem/cluster/gravity", "m_smbh", 3.4e8 * units.msun()); g_const_smbh_ = calc_g_const_smbh(units.gravitational_constant(), m_smbh), @@ -205,7 +206,7 @@ class ClusterGravity { if (include_nfw_g_) { g_r += g_const_nfw_ * (log(1 + r / r_nfw_s_) - r / (r + r_nfw_s_)) / r2; } - + // Add BCG gravity switch (which_bcg_g_) { case BCG::NONE: @@ -216,12 +217,12 @@ class ClusterGravity { g_r += g_const_bcg_ / r; break; } - + // Add SMBH, point mass gravity if (include_smbh_g_) { g_r += g_const_smbh_ / r2; } - + return g_r; } // Inline functions to compute density @@ -231,7 +232,7 @@ class ClusterGravity { const parthenon::Real r = std::max(r_in, smoothing_r_); parthenon::Real rho = 0; - + // Add NFW gravity if (include_nfw_g_) { rho += rho_const_nfw_ / (r * pow(r + r_nfw_s_, 2)); diff --git a/src/pgen/cluster/entropy_isothermal_profiles.hpp b/src/pgen/cluster/entropy_isothermal_profiles.hpp index 8b5c805f..db254fc4 100644 --- a/src/pgen/cluster/entropy_isothermal_profiles.hpp +++ b/src/pgen/cluster/entropy_isothermal_profiles.hpp @@ -20,24 +20,21 @@ template class ISOEntropyProfile { public: - // Entropy Profile parthenon::T_isothermal_; - - ISOEntropyProfile(parthenon::ParameterInput *pin, GravitationalField gravitational_field) { - - Units units(pin); - + ISOEntropyProfile(parthenon::ParameterInput *pin, + GravitationalField gravitational_field) { + + Units units(pin); } - + // Get entropy from radius, using broken power law profile for entropy - KOKKOS_INLINE_FUNCTION parthenon::Real K_from_r(const parthenon::Real r) const { + KOKKOS_INLINE_FUNCTION parthenon::Real K_from_r(const parthenon::Real r) const { - const parthenon::Real k = 1; - return k; + const parthenon::Real k = 1; + return k; } - }; } // namespace cluster diff --git a/src/pgen/cluster/entropy_profiles.hpp b/src/pgen/cluster/entropy_profiles.hpp index 9b6a09ba..500e560a 100644 --- a/src/pgen/cluster/entropy_profiles.hpp +++ b/src/pgen/cluster/entropy_profiles.hpp @@ -21,26 +21,24 @@ class ACCEPTEntropyProfile { public: // Entropy Profile parthenon::Real k_0_, k_100_, r_k_, alpha_k_; - + ACCEPTEntropyProfile(parthenon::ParameterInput *pin) { - + Units units(pin); - k_0_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "k_0", - 20 * units.kev() * units.cm() * units.cm()); - k_100_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "k_100", + k_0_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "k_0", + 20 * units.kev() * units.cm() * units.cm()); + k_100_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "k_100", 120 * units.kev() * units.cm() * units.cm()); - r_k_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "r_k", 100 * units.kpc()); + r_k_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "r_k", 100 * units.kpc()); alpha_k_ = pin->GetOrAddReal("problem/cluster/entropy_profile", "alpha_k", 1.75); } - + // Get entropy from radius, using broken power law profile for entropy - KOKKOS_INLINE_FUNCTION parthenon::Real K_from_r(const parthenon::Real r) const { - - const parthenon::Real k = k_0_ + k_100_ * pow(r / r_k_, alpha_k_); - return k; - + KOKKOS_INLINE_FUNCTION parthenon::Real K_from_r(const parthenon::Real r) const { + + const parthenon::Real k = k_0_ + k_100_ * pow(r / r_k_, alpha_k_); + return k; } - }; } // namespace cluster diff --git a/src/pgen/cluster/hydrostatic_equilibrium_sphere.cpp b/src/pgen/cluster/hydrostatic_equilibrium_sphere.cpp index 3504cd35..e0cba3df 100644 --- a/src/pgen/cluster/hydrostatic_equilibrium_sphere.cpp +++ b/src/pgen/cluster/hydrostatic_equilibrium_sphere.cpp @@ -155,23 +155,23 @@ HydrostaticEquilibriumSphere::generate_P_rho // Make sure to include R_fix_ Real r_start = r_fix_; Real r_end = r_fix_; - + for (int k = kb.s; k <= kb.e; k++) { for (int j = jb.s; j <= jb.e; j++) { for (int i = ib.s; i <= ib.e; i++) { - - // Integrate from r_start to r_end. If r_fix out of the domain, integrate from r_fix to r_max. - // Either: + + // Integrate from r_start to r_end. If r_fix out of the domain, integrate from + // r_fix to r_max. Either: // ==================== Integration domain ==================== - + // r_end = r_max --------- r_min ------ r_fix - + // or: - + // r_end ------------------------------ r_fix --------- r_min. - + // ============================================================ - + const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); @@ -180,16 +180,16 @@ HydrostaticEquilibriumSphere::generate_P_rho } } } - + // Add some room for R_start and R_end r_start = std::max(0.0, r_start - r_sampling_ * dr); r_end += r_sampling_ * dr; - + // Compute number of cells needed const auto n_r = static_cast(ceil((r_end - r_start) / dr)); // Make R_end consistent r_end = r_start + dr * (n_r - 1); - + return generate_P_rho_profile(r_start, r_end, n_r); } @@ -200,31 +200,31 @@ template PRhoProfile HydrostaticEquilibriumSphere::generate_P_rho_profile( const Real r_start, const Real r_end, const unsigned int n_r) const { - + // Array of radii along which to compute the profile ParArray1D device_r("PRhoProfile r", n_r); auto r = Kokkos::create_mirror_view(device_r); const Real dr = (r_end - r_start) / (n_r - 1.0); - + // Use a linear R - possibly adapt if using a mesh with logrithmic r for (int i = 0; i < n_r; i++) { r(i) = r_start + i * dr; } - + /************************************************************ * Integrate Pressure inward and outward from virial radius ************************************************************/ // Create array for pressure ParArray1D device_p("PRhoProfile p", n_r); auto p = Kokkos::create_mirror_view(device_p); - + const Real k_fix = entropy_profile_.K_from_r(r_fix_); const Real p_fix = P_from_rho_K(rho_fix_, k_fix); - + // Integrate P inward from R_fix_ Real r_i = r_fix_; // Start Ri at R_fix_ first Real p_i = p_fix; // Start with pressure at R_fix_ - + // Find the index in R right before R_fix_ int i_fix = static_cast(floor((n_r - 1) / (r_end - r_start) * (r_fix_ - r_start))); if (r_fix_ < r(i_fix) - kRTol || r_fix_ > r(i_fix + 1) + kRTol) { diff --git a/src/pgen/cluster/hydrostatic_equilibrium_sphere.hpp b/src/pgen/cluster/hydrostatic_equilibrium_sphere.hpp index 3d82258b..8b7cf584 100644 --- a/src/pgen/cluster/hydrostatic_equilibrium_sphere.hpp +++ b/src/pgen/cluster/hydrostatic_equilibrium_sphere.hpp @@ -36,26 +36,26 @@ class HydrostaticEquilibriumSphere { // Graviational field and entropy profile const GravitationalField gravitational_field_; const EntropyProfile entropy_profile_; - + // Physical constants parthenon::Real mh_, k_boltzmann_; - + // Density to fix baryons at a radius (change to temperature?) parthenon::Real r_fix_, rho_fix_; - + // Molecular weights parthenon::Real mu_, mu_e_; - + // R mesh sampling parameter parthenon::Real r_sampling_; - + /************************************************************ * Functions to build the cluster model * * Using lambda functions to make picking up model parameters seamlessly * Read A_from_B as "A as a function of B" ************************************************************/ - + // Get pressure from density and entropy, using ideal gas law and definition // of entropy KOKKOS_INLINE_FUNCTION parthenon::Real P_from_rho_K(const parthenon::Real rho, @@ -63,7 +63,7 @@ class HydrostaticEquilibriumSphere { const parthenon::Real p = k * pow(rho / mh_, 5. / 3.) / (mu_ * pow(mu_e_, 2. / 3.)); return p; } - + // Get density from pressure and entropy, using ideal gas law and definition // of entropy KOKKOS_INLINE_FUNCTION parthenon::Real rho_from_P_K(const parthenon::Real p, @@ -71,13 +71,13 @@ class HydrostaticEquilibriumSphere { const parthenon::Real rho = pow(mu_ * p / k, 3. / 5.) * mh_ * pow(mu_e_, 2. / 5); return rho; } - + // Get total number density from density KOKKOS_INLINE_FUNCTION parthenon::Real n_from_rho(const parthenon::Real rho) const { const parthenon::Real n = rho / (mu_ * mh_); return n; } - + // Get electron number density from density KOKKOS_INLINE_FUNCTION parthenon::Real ne_from_rho(const parthenon::Real rho) const { const parthenon::Real ne = mu_ / mu_e_ * n_from_rho(rho); @@ -114,7 +114,7 @@ class HydrostaticEquilibriumSphere { return dP_dr; } }; - + // Takes one rk4 step from t0 to t1, taking y0 and returning y1, using y'(t) = f(t,y) template parthenon::Real step_rk4(const parthenon::Real t0, const parthenon::Real t1, diff --git a/src/pgen/cluster/isothermal_sphere.cpp b/src/pgen/cluster/isothermal_sphere.cpp index d51a1850..15b6d768 100644 --- a/src/pgen/cluster/isothermal_sphere.cpp +++ b/src/pgen/cluster/isothermal_sphere.cpp @@ -207,11 +207,11 @@ HydrostaticEquilibriumSphere::generate_P_rho const Real k_fix = entropy_profile_.K_from_r(r_fix_); const Real p_fix = P_from_rho_K(rho_fix_, k_fix); - + // Integrate P inward from R_fix_ Real r_i = r_fix_; // Start Ri at R_fix_ first Real p_i = p_fix; // Start with pressure at R_fix_ - + // Find the index in R right before R_fix_ int i_fix = static_cast(floor((n_r - 1) / (r_end - r_start) * (r_fix_ - r_start))); if (r_fix_ < r(i_fix) - kRTol || r_fix_ > r(i_fix + 1) + kRTol) { diff --git a/src/pgen/cluster/isothermal_sphere.hpp b/src/pgen/cluster/isothermal_sphere.hpp index b99ef68b..ebe6b7f7 100644 --- a/src/pgen/cluster/isothermal_sphere.hpp +++ b/src/pgen/cluster/isothermal_sphere.hpp @@ -32,52 +32,47 @@ class IsothermalSphere { private: // Graviational field and entropy profile const GravitationalField gravitational_field_; - + // Physical constants parthenon::Real mh_, k_boltzmann_; // Molecular weights parthenon::Real mu_ - - /************************************************************ - * Functions to build the cluster model - * - * Using lambda functions to make picking up model parameters seamlessly - * Read A_from_B as "A as a function of B" - ************************************************************/ - - // Get the dP/dr from radius and pressure, which we will // - /************************************************************ - * dP_dr_from_r_P_functor - * - * Functor class giving dP/dr (r,P) - * which is used to compute the HSE profile - ************************************************************/ - - public: - KOKKOS_INLINE_FUNCTION parthenon::Real rho_from_r(const parthenon::Real r) const { + + /************************************************************ + * Functions to build the cluster model + * + * Using lambda functions to make picking up model parameters seamlessly + * Read A_from_B as "A as a function of B" + ************************************************************/ + + // Get the dP/dr from radius and pressure, which we will // + /************************************************************ + * dP_dr_from_r_P_functor + * + * Functor class giving dP/dr (r,P) + * which is used to compute the HSE profile + ************************************************************/ + + public : KOKKOS_INLINE_FUNCTION parthenon::Real + rho_from_r(const parthenon::Real r) const { using parthenon::Real; - - - functor( - const IsothermalSphere &sphere) - : sphere_(sphere) {} + + functor(const IsothermalSphere &sphere) : sphere_(sphere) {} parthenon::Real operator()(const parthenon::Real r) const { - + const parthenon::Real rho = sphere_.gravitational_field_.rho_from_r(r); return rho; } }; - + public: - IsothermalSphere(parthenon::ParameterInput *pin, - parthenon::StateDescriptor *hydro_pkg, - GravitationalField gravitational_field); + IsothermalSphere(parthenon::ParameterInput *pin, parthenon::StateDescriptor *hydro_pkg, + GravitationalField gravitational_field); PProfile generate_P_profile(parthenon::IndexRange ib, parthenon::IndexRange jb, - parthenon::IndexRange kb, - parthenon::UniformCartesian coords) const; + parthenon::IndexRange kb, parthenon::UniformCartesian coords) const; }; template @@ -88,8 +83,7 @@ class PProfile { const IsothermalSphere sphere_; public: - PProfile( - const IsothermalSphere &sphere) + PProfile(const IsothermalSphere &sphere) : r_(r), p_(p), sphere_(sphere), n_r_(r_.extent(0)), r_start_(r_start), r_end_(r_end) {} diff --git a/src/pgen/old_cluster/cluster_16nov.cpp b/src/pgen/old_cluster/cluster_16nov.cpp index 18657bf6..13a079a9 100644 --- a/src/pgen/old_cluster/cluster_16nov.cpp +++ b/src/pgen/old_cluster/cluster_16nov.cpp @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,59 +509,63 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - - // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the 2*n_ghost ghost cells - parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), - pmc->cellbounds.ncellsk(IndexDomain::entire), - pmc->cellbounds.ncellsj(IndexDomain::entire), - pmc->cellbounds.ncellsi(IndexDomain::entire)); - + + // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the + // 2*n_ghost ghost cells + parthenon::ParArray4D hydrostatic_rho( + "hydrostatic_rho", md->NumBlocks(), pmc->cellbounds.ncellsk(IndexDomain::entire), + pmc->cellbounds.ncellsj(IndexDomain::entire), + pmc->cellbounds.ncellsi(IndexDomain::entire)); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; - + auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto isothermal_sphere = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); - const auto isothermal_hernquist = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto isothermal_sphere = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); + const auto isothermal_hernquist = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -570,81 +576,83 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else if (isothermal_sphere) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real mu = hydro_pkg->Param("mu"); - const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); - const Real grav_const = units.gravitational_constant(); - - std::cout << "Entering isothermal sphere generation \n" ; - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real mu = hydro_pkg->Param("mu"); + const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); + const Real grav_const = units.gravitational_constant(); + + std::cout << "Entering isothermal sphere generation \n"; + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real rho_r = prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); - const Real P_r = (prefactor/2) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real rho_r = + prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); + const Real P_r = (prefactor / 2) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else if (isothermal_hernquist) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real m_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); - const Real r_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); - const Real mu = hydro_pkg->Param("mu"); - const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); - const Real grav_const = units.gravitational_constant(); - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real m_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); + const Real r_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); + const Real mu = hydro_pkg->Param("mu"); + const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); + const Real grav_const = units.gravitational_constant(); + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real phi_r = - grav_const * m_bcg_s / (r_effective + r_bcg_s); - const Real rho_r = rho_0 * std::exp( - mu * units.mh() / (units.k_boltzmann() * T_bcg_s) * phi_r); - const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real phi_r = -grav_const * m_bcg_s / (r_effective + r_bcg_s); + const Real rho_r = rho_0 * std::exp(-mu * units.mh() / + (units.k_boltzmann() * T_bcg_s) * phi_r); + const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } - + else { /************************************************************ * Initialize a HydrostaticEquilibriumSphere @@ -653,9 +661,9 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", @@ -665,24 +673,23 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - + // Updating hydrostatic_rho table hydrostatic_rho(b, k, j, i) = rho_r; - }); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -690,7 +697,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -700,14 +707,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -724,22 +731,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -747,7 +754,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -761,7 +767,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -777,7 +783,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -789,180 +795,191 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - - // Create an homogeneous sphere of a density superior or inferior to the background density - + + // Create an homogeneous sphere of a density superior or inferior to the background + // density + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 256; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Case where the box is filled with perturbations of equal mean amplitude - if (full_box){ - - u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * (u(IDN, k, j, i) / 29.6); - + if (full_box) { + + u(IDN, k, j, i) += perturb_amplitude * + rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * + (u(IDN, k, j, i) / 29.6); + } - - // Mean amplitude of the perturbations is modulated by the + + // Mean amplitude of the perturbations is modulated by the else { - - const Real x = coords.Xc<1>(i); - const Real y = coords.Xc<2>(j); - const Real z = coords.Xc<3>(k); - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_effective = std::max(r,r_smoothing); - - //u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; - + + const Real x = coords.Xc<1>(i); + const Real y = coords.Xc<2>(j); + const Real z = coords.Xc<3>(k); + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_effective = std::max(r, r_smoothing); + + // u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; } - }, passive_scalar); - } - + /************************************************************ * Setting up a perturbed density field (hardcoded version) ************************************************************/ - + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); - const auto background_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); - + const auto background_rho = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); + if (mu_rho != 0.0) { - + auto few_modes_ft_rho = hydro_pkg->Param("cluster/few_modes_ft_rho"); - + // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft_rho.SetPhases(pmb.get(), pin); - } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft_rho.Generate(md, dt, "tmp_perturb"); - + Real v2_sum_rho = 0.0; // used for normalization - + auto perturb_pack_rho = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - - Real perturb = 0.0 ; - - perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + SQR(perturb_pack_rho(b, 1, k, j, i)) + SQR(perturb_pack_rho(b, 2, k, j, i))); + + Real perturb = 0.0; + + perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + + SQR(perturb_pack_rho(b, 1, k, j, i)) + + SQR(perturb_pack_rho(b, 2, k, j, i))); u(IDN, k, j, i) = background_rho + mu_rho * perturb; - }, v2_sum_rho); @@ -970,22 +987,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum_rho, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain @@ -1023,12 +1038,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -1043,16 +1058,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto density_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); - const auto standard_B = pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); - const auto r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); - + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto density_scale = + pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); + const auto standard_B = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); + const auto r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -1060,181 +1079,183 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - - // Defining a new table that will contains the values of the perturbed magnetic field, and magnetic energy + + // Defining a new table that will contains the values of the perturbed magnetic field, + // and magnetic energy parthenon::ParArray5D dB("turbulent magnetic field", num_blocks, 4, - pmb->cellbounds.ncellsk(IndexDomain::entire), - pmb->cellbounds.ncellsj(IndexDomain::entire), - pmb->cellbounds.ncellsi(IndexDomain::entire)); - - if (standard_B){ - + pmb->cellbounds.ncellsk(IndexDomain::entire), + pmb->cellbounds.ncellsj(IndexDomain::entire), + pmb->cellbounds.ncellsi(IndexDomain::entire)); + + if (standard_B) { + pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - // The following restriction could be lifted, but requires refactoring of the - // logic for the normalization/reduction below - PARTHENON_REQUIRE( - u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - "Found existing non-zero B when setting magnetic field perturbations."); - u(IB1, k, j, i) = - (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0; - u(IB2, k, j, i) = - (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0; - u(IB3, k, j, i) = - (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0; + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + // The following restriction could be lifted, but requires refactoring of the + // logic for the normalization/reduction below + PARTHENON_REQUIRE( + u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && + u(IB3, k, j, i) == 0.0, + "Found existing non-zero B when setting magnetic field perturbations."); + u(IB1, k, j, i) = + (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0; + u(IB2, k, j, i) = + (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0; + u(IB3, k, j, i) = + (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0; + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * + coords.CellVolume(k, j, i); + }, + b2_sum); - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * - coords.CellVolume(k, j, i); - }, - b2_sum); - } else { - - - - pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - - auto pmbl = md->GetBlockData(b)->GetBlockPointer(); - auto hydro_pkgl = pmbl->packages.Get("Hydro"); - - const Real x = coords.Xc<1>(i); - const Real xp = coords.Xc<1>(i+1); - const Real xm = coords.Xc<1>(i-1); - const Real y = coords.Xc<1>(j); - const Real yp = coords.Xc<1>(j+1); - const Real ym = coords.Xc<1>(j-1); - const Real z = coords.Xc<1>(k); - const Real zp = coords.Xc<1>(k+1); - const Real zm = coords.Xc<1>(k-1); - - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_ip = std::sqrt(SQR(xp) + SQR(y) + SQR(z)); - const Real r_im = std::sqrt(SQR(xm) + SQR(y) + SQR(z)); - const Real r_jp = std::sqrt(SQR(x) + SQR(yp) + SQR(z)); - const Real r_jm = std::sqrt(SQR(x) + SQR(ym) + SQR(z)); - const Real r_kp = std::sqrt(SQR(x) + SQR(y) + SQR(zp)); - const Real r_km = std::sqrt(SQR(x) + SQR(y) + SQR(zm)); - - // Re-generating the hydrostatic sphere - const auto &he_sphere = - hydro_pkgl - ->Param>( - "hydrostatic_equilibirum_sphere"); - - const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - const auto rho_central = P_rho_profile.rho_from_r(r_smoothing); - const auto rho_ip = P_rho_profile.rho_from_r(r_ip); - const auto rho_im = P_rho_profile.rho_from_r(r_im); - const auto rho_jp = P_rho_profile.rho_from_r(r_jp); - const auto rho_jm = P_rho_profile.rho_from_r(r_jm); - const auto rho_kp = P_rho_profile.rho_from_r(r_kp); - const auto rho_km = P_rho_profile.rho_from_r(r_km); - - // const Real rho_r = P_rho_profile.rho_from_r(r); - - // Normalization condition here, which we want to lift. To do so, we'll need - // to copy the values of the magnetic field into a new array, which we will - // use to store the perturbed magnetic field and then rescale it, until values - // are added to u = cons(b) - - //PARTHENON_REQUIRE( - // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - // "Found existing non-zero B when setting magnetic field perturbations."); - - // First, needs to rescale the perturb_pack, ie. the magnetic field potential - Real perturb2_k_jp_i,perturb2_k_jm_i,perturb1_kp_j_i,perturb1_km_j_i; - Real perturb0_kp_j_i,perturb0_km_j_i,perturb2_k_j_ip,perturb2_k_j_im; - Real perturb1_k_j_ip,perturb1_k_j_im,perturb0_k_jp_i,perturb0_k_jm_i; - - // Rescaling the magnetic potential - - perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(rho_jp, alpha_b); - perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(rho_jm, alpha_b); - perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(rho_kp, alpha_b); - perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(rho_km, alpha_b); - perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(rho_kp, alpha_b); - perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(rho_km, alpha_b); - perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(rho_ip, alpha_b); - perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(rho_im, alpha_b); - perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(rho_ip, alpha_b); - perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(rho_im, alpha_b); - perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(rho_jp, alpha_b); - perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(rho_jm, alpha_b); - - // Then, compute the curl of the magnetic field - - Real curlBx,curlBy,curlBz; - - curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - - (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0 ; - curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - - (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0 ; - curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - - (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0 ; - - dB(b,0, k, j, i) = curlBx; - dB(b,1, k, j, i) = curlBy; - dB(b,2, k, j, i) = curlBz; - - lsum += (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); - - /* - gradBx = (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 ; - - gradBy = (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 ; - - gradBz = (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 ; - - dB(b,0, k, j, i) = gradBx * std::pow(hydrostatic_rho(b,k,j,i) / 29.6, alpha_b); - dB(b,1, k, j, i) = gradBy * std::pow(hydrostatic_rho(b,k,j,i) / 29.6, alpha_b); - dB(b,2, k, j, i) = gradBz * std::pow(hydrostatic_rho(b,k,j,i) / 29.6, alpha_b); - - - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(gradBx) + SQR(gradBy) + SQR(gradBz)) * - coords.CellVolume(k, j, i); - */ - }, - b2_sum); + + pmb->par_reduce( + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + + auto pmbl = md->GetBlockData(b)->GetBlockPointer(); + auto hydro_pkgl = pmbl->packages.Get("Hydro"); + + const Real x = coords.Xc<1>(i); + const Real xp = coords.Xc<1>(i + 1); + const Real xm = coords.Xc<1>(i - 1); + const Real y = coords.Xc<1>(j); + const Real yp = coords.Xc<1>(j + 1); + const Real ym = coords.Xc<1>(j - 1); + const Real z = coords.Xc<1>(k); + const Real zp = coords.Xc<1>(k + 1); + const Real zm = coords.Xc<1>(k - 1); + + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_ip = std::sqrt(SQR(xp) + SQR(y) + SQR(z)); + const Real r_im = std::sqrt(SQR(xm) + SQR(y) + SQR(z)); + const Real r_jp = std::sqrt(SQR(x) + SQR(yp) + SQR(z)); + const Real r_jm = std::sqrt(SQR(x) + SQR(ym) + SQR(z)); + const Real r_kp = std::sqrt(SQR(x) + SQR(y) + SQR(zp)); + const Real r_km = std::sqrt(SQR(x) + SQR(y) + SQR(zm)); + + // Re-generating the hydrostatic sphere + const auto &he_sphere = hydro_pkgl->Param< + HydrostaticEquilibriumSphere>( + "hydrostatic_equilibirum_sphere"); + + const auto P_rho_profile = + he_sphere.generate_P_rho_profile(ib, jb, kb, coords); + const auto rho_central = P_rho_profile.rho_from_r(r_smoothing); + const auto rho_ip = P_rho_profile.rho_from_r(r_ip); + const auto rho_im = P_rho_profile.rho_from_r(r_im); + const auto rho_jp = P_rho_profile.rho_from_r(r_jp); + const auto rho_jm = P_rho_profile.rho_from_r(r_jm); + const auto rho_kp = P_rho_profile.rho_from_r(r_kp); + const auto rho_km = P_rho_profile.rho_from_r(r_km); + + // const Real rho_r = P_rho_profile.rho_from_r(r); + + // Normalization condition here, which we want to lift. To do so, we'll need + // to copy the values of the magnetic field into a new array, which we will + // use to store the perturbed magnetic field and then rescale it, until values + // are added to u = cons(b) + + // PARTHENON_REQUIRE( + // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == + // 0.0, "Found existing non-zero B when setting magnetic field + // perturbations."); + + // First, needs to rescale the perturb_pack, ie. the magnetic field potential + Real perturb2_k_jp_i, perturb2_k_jm_i, perturb1_kp_j_i, perturb1_km_j_i; + Real perturb0_kp_j_i, perturb0_km_j_i, perturb2_k_j_ip, perturb2_k_j_im; + Real perturb1_k_j_ip, perturb1_k_j_im, perturb0_k_jp_i, perturb0_k_jm_i; + + // Rescaling the magnetic potential + + perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(rho_jp, alpha_b); + perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(rho_jm, alpha_b); + perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(rho_kp, alpha_b); + perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(rho_km, alpha_b); + perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(rho_kp, alpha_b); + perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(rho_km, alpha_b); + perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(rho_ip, alpha_b); + perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(rho_im, alpha_b); + perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(rho_ip, alpha_b); + perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(rho_im, alpha_b); + perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(rho_jp, alpha_b); + perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(rho_jm, alpha_b); + + // Then, compute the curl of the magnetic field + + Real curlBx, curlBy, curlBz; + + curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - + (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0; + curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - + (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0; + curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - + (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0; + + dB(b, 0, k, j, i) = curlBx; + dB(b, 1, k, j, i) = curlBy; + dB(b, 2, k, j, i) = curlBz; + + lsum += + (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); + + /* + gradBx = (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 ; + + gradBy = (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 ; + + gradBz = (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 ; + + dB(b,0, k, j, i) = gradBx * std::pow(hydrostatic_rho(b,k,j,i) / 29.6, + alpha_b); dB(b,1, k, j, i) = gradBy * std::pow(hydrostatic_rho(b,k,j,i) + / 29.6, alpha_b); dB(b,2, k, j, i) = gradBz * + std::pow(hydrostatic_rho(b,k,j,i) / 29.6, alpha_b); + + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(gradBx) + SQR(gradBy) + SQR(gradBz)) * + coords.CellVolume(k, j, i); + */ + }, + b2_sum); } - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); @@ -1244,45 +1265,44 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - - if (standard_B){ - + + if (standard_B) { + pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); - u(IB1, k, j, i) /= b_norm; - u(IB2, k, j, i) /= b_norm; - u(IB3, k, j, i) /= b_norm; + u(IB1, k, j, i) /= b_norm; + u(IB2, k, j, i) /= b_norm; + u(IB3, k, j, i) /= b_norm; + + u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + + SQR(u(IB3, k, j, i))); + }); - u(IEN, k, j, i) += - 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); - }); - } else { - - pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - dB(b, 0, k, j, i) /= b_norm; - dB(b, 1, k, j, i) /= b_norm; - dB(b, 2, k, j, i) /= b_norm; - - // Computing energy - dB(b, 3, k, j, i) += - 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + SQR(dB(b, 2, k, j, i))); - - // Updating the MHD vector - - u(IB1, k, j, i) += dB(b, 0, k, j, i); - u(IB2, k, j, i) += dB(b, 1, k, j, i); - u(IB3, k, j, i) += dB(b, 2, k, j, i); - u(IEN, k, j, i) += dB(b, 3, k, j, i); - - }); + + pmb->par_for( + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + dB(b, 0, k, j, i) /= b_norm; + dB(b, 1, k, j, i) /= b_norm; + dB(b, 2, k, j, i) /= b_norm; + + // Computing energy + dB(b, 3, k, j, i) += 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + + SQR(dB(b, 2, k, j, i))); + + // Updating the MHD vector + + u(IB1, k, j, i) += dB(b, 0, k, j, i); + u(IB2, k, j, i) += dB(b, 1, k, j, i); + u(IB3, k, j, i) += dB(b, 2, k, j, i); + u(IEN, k, j, i) += dB(b, 3, k, j, i); + }); } } } @@ -1343,15 +1363,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { diff --git a/src/pgen/old_cluster/cluster_17nov.cpp b/src/pgen/old_cluster/cluster_17nov.cpp index 44f1bbfc..97b75d81 100644 --- a/src/pgen/old_cluster/cluster_17nov.cpp +++ b/src/pgen/old_cluster/cluster_17nov.cpp @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,59 +509,63 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - - // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the 2*n_ghost ghost cells - parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), - pmc->cellbounds.ncellsk(IndexDomain::entire), - pmc->cellbounds.ncellsj(IndexDomain::entire), - pmc->cellbounds.ncellsi(IndexDomain::entire)); - + + // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the + // 2*n_ghost ghost cells + parthenon::ParArray4D hydrostatic_rho( + "hydrostatic_rho", md->NumBlocks(), pmc->cellbounds.ncellsk(IndexDomain::entire), + pmc->cellbounds.ncellsj(IndexDomain::entire), + pmc->cellbounds.ncellsi(IndexDomain::entire)); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; - + auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto isothermal_sphere = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); - const auto isothermal_hernquist = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto isothermal_sphere = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); + const auto isothermal_hernquist = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -570,81 +576,83 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else if (isothermal_sphere) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real mu = hydro_pkg->Param("mu"); - const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); - const Real grav_const = units.gravitational_constant(); - - std::cout << "Entering isothermal sphere generation \n" ; - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real mu = hydro_pkg->Param("mu"); + const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); + const Real grav_const = units.gravitational_constant(); + + std::cout << "Entering isothermal sphere generation \n"; + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real rho_r = prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); - const Real P_r = (prefactor/2) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real rho_r = + prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); + const Real P_r = (prefactor / 2) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else if (isothermal_hernquist) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real m_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); - const Real r_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); - const Real mu = hydro_pkg->Param("mu"); - const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); - const Real grav_const = units.gravitational_constant(); - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real m_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); + const Real r_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); + const Real mu = hydro_pkg->Param("mu"); + const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); + const Real grav_const = units.gravitational_constant(); + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real phi_r = - grav_const * m_bcg_s / (r_effective + r_bcg_s); - const Real rho_r = rho_0 * std::exp( - mu * units.mh() / (units.k_boltzmann() * T_bcg_s) * phi_r); - const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real phi_r = -grav_const * m_bcg_s / (r_effective + r_bcg_s); + const Real rho_r = rho_0 * std::exp(-mu * units.mh() / + (units.k_boltzmann() * T_bcg_s) * phi_r); + const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } - + else { /************************************************************ * Initialize a HydrostaticEquilibriumSphere @@ -653,9 +661,9 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", @@ -665,24 +673,23 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - + // Updating hydrostatic_rho table hydrostatic_rho(b, k, j, i) = rho_r; - }); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -690,7 +697,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -700,14 +707,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -724,22 +731,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -747,7 +754,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -761,7 +767,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -777,7 +783,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -789,180 +795,191 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - - // Create an homogeneous sphere of a density superior or inferior to the background density - + + // Create an homogeneous sphere of a density superior or inferior to the background + // density + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 256; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Case where the box is filled with perturbations of equal mean amplitude - if (full_box){ - - u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * (u(IDN, k, j, i) / 29.6); - + if (full_box) { + + u(IDN, k, j, i) += perturb_amplitude * + rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * + (u(IDN, k, j, i) / 29.6); + } - - // Mean amplitude of the perturbations is modulated by the + + // Mean amplitude of the perturbations is modulated by the else { - - const Real x = coords.Xc<1>(i); - const Real y = coords.Xc<2>(j); - const Real z = coords.Xc<3>(k); - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_effective = std::max(r,r_smoothing); - - //u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; - + + const Real x = coords.Xc<1>(i); + const Real y = coords.Xc<2>(j); + const Real z = coords.Xc<3>(k); + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_effective = std::max(r, r_smoothing); + + // u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; } - }, passive_scalar); - } - + /************************************************************ * Setting up a perturbed density field (hardcoded version) ************************************************************/ - + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); - const auto background_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); - + const auto background_rho = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); + if (mu_rho != 0.0) { - + auto few_modes_ft_rho = hydro_pkg->Param("cluster/few_modes_ft_rho"); - + // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft_rho.SetPhases(pmb.get(), pin); - } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft_rho.Generate(md, dt, "tmp_perturb"); - + Real v2_sum_rho = 0.0; // used for normalization - + auto perturb_pack_rho = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - - Real perturb = 0.0 ; - - perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + SQR(perturb_pack_rho(b, 1, k, j, i)) + SQR(perturb_pack_rho(b, 2, k, j, i))); + + Real perturb = 0.0; + + perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + + SQR(perturb_pack_rho(b, 1, k, j, i)) + + SQR(perturb_pack_rho(b, 2, k, j, i))); u(IDN, k, j, i) = background_rho + mu_rho * perturb; - }, v2_sum_rho); @@ -970,22 +987,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum_rho, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain @@ -1023,12 +1038,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -1043,17 +1058,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto density_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); - const auto standard_B = pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); - const auto r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); - const auto rho_type = pin->GetOrAddInteger("problem/cluster/init_perturb", "rho_type", 0); // test - + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto density_scale = + pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); + const auto standard_B = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); + const auto r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); + const auto rho_type = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rho_type", 0); // test + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -1061,189 +1081,193 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - - // Defining a new table that will contains the values of the perturbed magnetic field, and magnetic energy + + // Defining a new table that will contains the values of the perturbed magnetic field, + // and magnetic energy parthenon::ParArray5D dB("turbulent magnetic field", num_blocks, 4, - pmb->cellbounds.ncellsk(IndexDomain::entire), - pmb->cellbounds.ncellsj(IndexDomain::entire), - pmb->cellbounds.ncellsi(IndexDomain::entire)); - - if (standard_B){ - + pmb->cellbounds.ncellsk(IndexDomain::entire), + pmb->cellbounds.ncellsj(IndexDomain::entire), + pmb->cellbounds.ncellsi(IndexDomain::entire)); + + if (standard_B) { + pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - // The following restriction could be lifted, but requires refactoring of the - // logic for the normalization/reduction below - PARTHENON_REQUIRE( - u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - "Found existing non-zero B when setting magnetic field perturbations."); - u(IB1, k, j, i) = - (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0; - u(IB2, k, j, i) = - (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0; - u(IB3, k, j, i) = - (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0; + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + // The following restriction could be lifted, but requires refactoring of the + // logic for the normalization/reduction below + PARTHENON_REQUIRE( + u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && + u(IB3, k, j, i) == 0.0, + "Found existing non-zero B when setting magnetic field perturbations."); + u(IB1, k, j, i) = + (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0; + u(IB2, k, j, i) = + (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0; + u(IB3, k, j, i) = + (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0; + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * + coords.CellVolume(k, j, i); + }, + b2_sum); - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * - coords.CellVolume(k, j, i); - }, - b2_sum); - } else { - - // Idea: separate into two loops, one par_for and one par_reduce - - std::cout << "Setting up perturbed magnetic field." << std::endl; - - for (int b = 0; b < md->NumBlocks(); b++) { - - std::cout << "Treating block number " << b << " out of " << md->NumBlocks() << std::endl; - - auto pmb = md->GetBlockData(b)->GetBlockPointer(); - auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - - IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); - IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); - IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - - // Computation of the P_rho_profile require entire domain of the block (boundary conditions for curl computation) - IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); - IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); - IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - - // Initialize the conserved variables - auto &u = pmb->meshblock_data.Get()->Get("cons").data; - auto &coords = pmb->coords; - - const auto &he_sphere = - hydro_pkg - ->Param>( - "hydrostatic_equilibirum_sphere"); - - const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); - - // initialize conserved variables - parthenon::par_for( - DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::MagneticPerturbations", - parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - - const Real x = coords.Xc<1>(i); - const Real xp = coords.Xc<1>(i+1); - const Real xm = coords.Xc<1>(i-1); - const Real y = coords.Xc<2>(j); - const Real yp = coords.Xc<2>(j+1); - const Real ym = coords.Xc<2>(j-1); - const Real z = coords.Xc<3>(k); - const Real zp = coords.Xc<3>(k+1); - const Real zm = coords.Xc<3>(k-1); - - const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_ip = sqrt(SQR(xp) + SQR(y) + SQR(z)); - const Real r_im = sqrt(SQR(xm) + SQR(y) + SQR(z)); - const Real r_jp = sqrt(SQR(x) + SQR(yp) + SQR(z)); - const Real r_jm = sqrt(SQR(x) + SQR(ym) + SQR(z)); - const Real r_kp = sqrt(SQR(x) + SQR(y) + SQR(zp)); - const Real r_km = sqrt(SQR(x) + SQR(y) + SQR(zm)); - - const auto rho = P_rho_profile.rho_from_r(r); - const auto rho_ip = P_rho_profile.rho_from_r(r_ip); - const auto rho_im = P_rho_profile.rho_from_r(r_im); - const auto rho_jp = P_rho_profile.rho_from_r(r_jp); - const auto rho_jm = P_rho_profile.rho_from_r(r_jm); - const auto rho_kp = P_rho_profile.rho_from_r(r_kp); - const auto rho_km = P_rho_profile.rho_from_r(r_km); - - // const Real rho_r = P_rho_profile.rho_from_r(r); - - // Normalization condition here, which we want to lift. To do so, we'll need - // to copy the values of the magnetic field into a new array, which we will - // use to store the perturbed magnetic field and then rescale it, until values - // are added to u = cons(b) - - //PARTHENON_REQUIRE( - // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - // "Found existing non-zero B when setting magnetic field perturbations."); - - // First, needs to rescale the perturb_pack, ie. the magnetic field potential - Real perturb2_k_jp_i,perturb2_k_jm_i,perturb1_kp_j_i,perturb1_km_j_i; - Real perturb0_kp_j_i,perturb0_km_j_i,perturb2_k_j_ip,perturb2_k_j_im; - Real perturb1_k_j_ip,perturb1_k_j_im,perturb0_k_jp_i,perturb0_k_jm_i; - - // Rescaling the magnetic potential - - perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(r_jp, alpha_b); - perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(r_jm, alpha_b); - perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(r_kp, alpha_b); - perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(r_km, alpha_b); - perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(r_kp, alpha_b); - perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(r_km, alpha_b); - perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(r_ip, alpha_b); - perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(r_im, alpha_b); - perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(r_ip, alpha_b); - perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(r_im, alpha_b); - perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(r_jp, alpha_b); - perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(r_jm, alpha_b); - - // Then, compute the curl of the magnetic field - - Real curlBx,curlBy,curlBz; - - curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - - (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0 ; - curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - - (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0 ; - curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - - (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0 ; - - dB(b,0, k, j, i) = curlBx; - dB(b,1, k, j, i) = curlBy; - dB(b,2, k, j, i) = curlBz; - - }); - } - - pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - const auto &coords = cons.GetCoords(b); - - Real curlBx,curlBy,curlBz; - - curlBx = dB(b,0, k, j, i); - curlBy = dB(b,1, k, j, i); - curlBz = dB(b,2, k, j, i); - - lsum += (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); - }, - b2_sum); + + // Idea: separate into two loops, one par_for and one par_reduce + + std::cout << "Setting up perturbed magnetic field." << std::endl; + + for (int b = 0; b < md->NumBlocks(); b++) { + + std::cout << "Treating block number " << b << " out of " << md->NumBlocks() + << std::endl; + + auto pmb = md->GetBlockData(b)->GetBlockPointer(); + auto hydro_pkg = pmb->packages.Get("Hydro"); + auto units = hydro_pkg->Param("units"); + + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); + IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); + IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); + + // Computation of the P_rho_profile require entire domain of the block (boundary + // conditions for curl computation) + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); + IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); + IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); + + // Initialize the conserved variables + auto &u = pmb->meshblock_data.Get()->Get("cons").data; + auto &coords = pmb->coords; + + const auto &he_sphere = hydro_pkg->Param< + HydrostaticEquilibriumSphere>( + "hydrostatic_equilibirum_sphere"); + + const auto P_rho_profile = + he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); + + // initialize conserved variables + parthenon::par_for( + DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::MagneticPerturbations", + parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { + const Real x = coords.Xc<1>(i); + const Real xp = coords.Xc<1>(i + 1); + const Real xm = coords.Xc<1>(i - 1); + const Real y = coords.Xc<2>(j); + const Real yp = coords.Xc<2>(j + 1); + const Real ym = coords.Xc<2>(j - 1); + const Real z = coords.Xc<3>(k); + const Real zp = coords.Xc<3>(k + 1); + const Real zm = coords.Xc<3>(k - 1); + + const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_ip = sqrt(SQR(xp) + SQR(y) + SQR(z)); + const Real r_im = sqrt(SQR(xm) + SQR(y) + SQR(z)); + const Real r_jp = sqrt(SQR(x) + SQR(yp) + SQR(z)); + const Real r_jm = sqrt(SQR(x) + SQR(ym) + SQR(z)); + const Real r_kp = sqrt(SQR(x) + SQR(y) + SQR(zp)); + const Real r_km = sqrt(SQR(x) + SQR(y) + SQR(zm)); + + const auto rho = P_rho_profile.rho_from_r(r); + const auto rho_ip = P_rho_profile.rho_from_r(r_ip); + const auto rho_im = P_rho_profile.rho_from_r(r_im); + const auto rho_jp = P_rho_profile.rho_from_r(r_jp); + const auto rho_jm = P_rho_profile.rho_from_r(r_jm); + const auto rho_kp = P_rho_profile.rho_from_r(r_kp); + const auto rho_km = P_rho_profile.rho_from_r(r_km); + + // const Real rho_r = P_rho_profile.rho_from_r(r); + + // Normalization condition here, which we want to lift. To do so, we'll need + // to copy the values of the magnetic field into a new array, which we will + // use to store the perturbed magnetic field and then rescale it, until + // values are added to u = cons(b) + + // PARTHENON_REQUIRE( + // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) + // == 0.0, "Found existing non-zero B when setting magnetic field + // perturbations."); + + // First, needs to rescale the perturb_pack, ie. the magnetic field + // potential + Real perturb2_k_jp_i, perturb2_k_jm_i, perturb1_kp_j_i, perturb1_km_j_i; + Real perturb0_kp_j_i, perturb0_km_j_i, perturb2_k_j_ip, perturb2_k_j_im; + Real perturb1_k_j_ip, perturb1_k_j_im, perturb0_k_jp_i, perturb0_k_jm_i; + + // Rescaling the magnetic potential + + perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(r_jp, alpha_b); + perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(r_jm, alpha_b); + perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(r_kp, alpha_b); + perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(r_km, alpha_b); + perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(r_kp, alpha_b); + perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(r_km, alpha_b); + perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(r_ip, alpha_b); + perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(r_im, alpha_b); + perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(r_ip, alpha_b); + perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(r_im, alpha_b); + perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(r_jp, alpha_b); + perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(r_jm, alpha_b); + + // Then, compute the curl of the magnetic field + + Real curlBx, curlBy, curlBz; + + curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - + (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0; + curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - + (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0; + curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - + (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0; + + dB(b, 0, k, j, i) = curlBx; + dB(b, 1, k, j, i) = curlBy; + dB(b, 2, k, j, i) = curlBz; + }); + } + + pmb->par_reduce( + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + + Real curlBx, curlBy, curlBz; + + curlBx = dB(b, 0, k, j, i); + curlBy = dB(b, 1, k, j, i); + curlBz = dB(b, 2, k, j, i); + + lsum += + (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); + }, + b2_sum); } - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); @@ -1253,45 +1277,44 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - - if (standard_B){ - + + if (standard_B) { + pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); - u(IB1, k, j, i) /= b_norm; - u(IB2, k, j, i) /= b_norm; - u(IB3, k, j, i) /= b_norm; + u(IB1, k, j, i) /= b_norm; + u(IB2, k, j, i) /= b_norm; + u(IB3, k, j, i) /= b_norm; + + u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + + SQR(u(IB3, k, j, i))); + }); - u(IEN, k, j, i) += - 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); - }); - } else { - - pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - dB(b, 0, k, j, i) /= b_norm; - dB(b, 1, k, j, i) /= b_norm; - dB(b, 2, k, j, i) /= b_norm; - - // Computing energy - dB(b, 3, k, j, i) += - 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + SQR(dB(b, 2, k, j, i))); - - // Updating the MHD vector - - u(IB1, k, j, i) += dB(b, 0, k, j, i); - u(IB2, k, j, i) += dB(b, 1, k, j, i); - u(IB3, k, j, i) += dB(b, 2, k, j, i); - u(IEN, k, j, i) += dB(b, 3, k, j, i); - - }); + + pmb->par_for( + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + dB(b, 0, k, j, i) /= b_norm; + dB(b, 1, k, j, i) /= b_norm; + dB(b, 2, k, j, i) /= b_norm; + + // Computing energy + dB(b, 3, k, j, i) += 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + + SQR(dB(b, 2, k, j, i))); + + // Updating the MHD vector + + u(IB1, k, j, i) += dB(b, 0, k, j, i); + u(IB2, k, j, i) += dB(b, 1, k, j, i); + u(IB3, k, j, i) += dB(b, 2, k, j, i); + u(IEN, k, j, i) += dB(b, 3, k, j, i); + }); } } } @@ -1352,15 +1375,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { diff --git a/src/pgen/old_cluster/cluster_22nov.cpp b/src/pgen/old_cluster/cluster_22nov.cpp index a9c60b4a..64880be7 100644 --- a/src/pgen/old_cluster/cluster_22nov.cpp +++ b/src/pgen/old_cluster/cluster_22nov.cpp @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,67 +509,71 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); - const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - - parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho",grid_size + 4,grid_size + 4,grid_size + 4); - - //parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), - // pmc->cellbounds.ncellsk(IndexDomain::entire), - // pmc->cellbounds.ncellsj(IndexDomain::entire), - // pmc->cellbounds.ncellsi(IndexDomain::entire)); - + const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); + + parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", grid_size + 4, + grid_size + 4, grid_size + 4); + + // parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), + // pmc->cellbounds.ncellsk(IndexDomain::entire), + // pmc->cellbounds.ncellsj(IndexDomain::entire), + // pmc->cellbounds.ncellsi(IndexDomain::entire)); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - - IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); - IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); - IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); + IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); + IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto isothermal_sphere = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); - const auto isothermal_hernquist = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto isothermal_sphere = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); + const auto isothermal_hernquist = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -578,83 +584,85 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else if (isothermal_sphere) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real mu = hydro_pkg->Param("mu"); - const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); - const Real grav_const = units.gravitational_constant(); - - std::cout << "Entering isothermal sphere generation \n" ; - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real mu = hydro_pkg->Param("mu"); + const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); + const Real grav_const = units.gravitational_constant(); + + std::cout << "Entering isothermal sphere generation \n"; + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real rho_r = prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); - const Real P_r = (prefactor/2) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real rho_r = + prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); + const Real P_r = (prefactor / 2) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else if (isothermal_hernquist) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real m_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); - const Real r_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); - const Real mu = hydro_pkg->Param("mu"); - const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); - const Real grav_const = units.gravitational_constant(); - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real m_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); + const Real r_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); + const Real mu = hydro_pkg->Param("mu"); + const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); + const Real grav_const = units.gravitational_constant(); + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real phi_r = - grav_const * m_bcg_s / (r_effective + r_bcg_s); - const Real rho_r = rho_0 * std::exp( - mu * units.mh() / (units.k_boltzmann() * T_bcg_s) * phi_r); - const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real phi_r = -grav_const * m_bcg_s / (r_effective + r_bcg_s); + const Real rho_r = rho_0 * std::exp(-mu * units.mh() / + (units.k_boltzmann() * T_bcg_s) * phi_r); + const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } - + else { - + /************************************************************ * Initialize a HydrostaticEquilibriumSphere ************************************************************/ @@ -662,38 +670,36 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - - const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); - + + const auto P_rho_profile = + he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile - const Real P_r = P_rho_profile.P_from_r(r); + const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - - //u(IDN, k, j, i) = rho_r; + + // u(IDN, k, j, i) = rho_r; u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - + // Updating hydrostatic_rho table hydrostatic_rho(gks + k, gjs + j, gis + i) = rho_r; - }); - } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -701,7 +707,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -711,14 +717,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -735,22 +741,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -758,7 +764,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -772,7 +777,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -788,7 +793,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -800,159 +805,168 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - - // Create an homogeneous sphere of a density superior or inferior to the background density - + + // Create an homogeneous sphere of a density superior or inferior to the background + // density + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 260; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Case where the box is filled with perturbations of equal mean amplitude - if (full_box){ - - u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * (u(IDN, k, j, i) / 29.6); - hydrostatic_rho(gks + k, gjs + j, gis + i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * (u(IDN, k, j, i) / 29.6); + if (full_box) { + + u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * + (u(IDN, k, j, i) / 29.6); + hydrostatic_rho(gks + k, gjs + j, gis + i) += + perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * + (u(IDN, k, j, i) / 29.6); } - - }, passive_scalar); - - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real v2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { @@ -979,12 +993,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -999,16 +1013,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ - const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto density_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); - const auto standard_B = pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); - const auto r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); - + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto density_scale = + pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); + const auto standard_B = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); + const auto r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -1016,136 +1034,137 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - - // Defining a new table that will contains the values of the perturbed magnetic field, and magnetic energy + + // Defining a new table that will contains the values of the perturbed magnetic field, + // and magnetic energy parthenon::ParArray5D dB("turbulent magnetic field", num_blocks, 4, - pmb->cellbounds.ncellsk(IndexDomain::entire), - pmb->cellbounds.ncellsj(IndexDomain::entire), - pmb->cellbounds.ncellsi(IndexDomain::entire)); - + pmb->cellbounds.ncellsk(IndexDomain::entire), + pmb->cellbounds.ncellsj(IndexDomain::entire), + pmb->cellbounds.ncellsi(IndexDomain::entire)); + // Modifying the magnetic potential so that it follows the rho profile pmb->par_for( - "Init sigma_b", 0, num_blocks - 1, kb.s-1, kb.e+1, jb.s-1, jb.e+1, ib.s-1, ib.e+1, + "Init sigma_b", 0, num_blocks - 1, kb.s - 1, kb.e + 1, jb.s - 1, jb.e + 1, + ib.s - 1, ib.e + 1, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - - auto pmb = md->GetBlockData(b)->GetBlockPointer(); + + auto pmb = md->GetBlockData(b)->GetBlockPointer(); const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + perturb_pack(b, 0, k, j, i) *= u(IDN, k, j, i); perturb_pack(b, 1, k, j, i) *= u(IDN, k, j, i); perturb_pack(b, 2, k, j, i) *= u(IDN, k, j, i); - - //perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - //perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - //perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - - //perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - //perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - //perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - - }); - - if (standard_B){ - + + // perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + // + i),alpha_b); perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(gks + + // k, gjs + j, gis + i),alpha_b); perturb_pack(b, 2, k, j, i) *= + // std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); + + // perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + // perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + // perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + }); + + if (standard_B) { + std::cout << "Entering standard B" << std::endl; - + pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - - // The following restriction could be lifted, but requires refactoring of the - // logic for the normalization/reduction below - - PARTHENON_REQUIRE( - u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - "Found existing non-zero B when setting magnetic field perturbations."); - u(IB1, k, j, i) = - (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0; - u(IB2, k, j, i) = - (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0; - u(IB3, k, j, i) = - (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0; - - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * - coords.CellVolume(k, j, i); - }, - b2_sum); - + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + + // The following restriction could be lifted, but requires refactoring of the + // logic for the normalization/reduction below + + PARTHENON_REQUIRE( + u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && + u(IB3, k, j, i) == 0.0, + "Found existing non-zero B when setting magnetic field perturbations."); + u(IB1, k, j, i) = + (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0; + u(IB2, k, j, i) = + (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0; + u(IB3, k, j, i) = + (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0; + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * + coords.CellVolume(k, j, i); + }, + b2_sum); + } else { - - pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - - // First, needs to rescale the perturb_pack, ie. the magnetic field potential - Real perturb2_k_jp_i,perturb2_k_jm_i,perturb1_kp_j_i,perturb1_km_j_i; - Real perturb0_kp_j_i,perturb0_km_j_i,perturb2_k_j_ip,perturb2_k_j_im; - Real perturb1_k_j_ip,perturb1_k_j_im,perturb0_k_jp_i,perturb0_k_jm_i; - - perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i); - perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i); - perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i); - perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i); - perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i); - perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i); - perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1); - perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1); - perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1); - perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1); - perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i); - perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i); - - // Then, compute the curl of the magnetic field - - Real curlBx,curlBy,curlBz; - - curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - - (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0 ; - curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - - (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0 ; - curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - - (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0 ; - - dB(b, 0, k, j, i) = curlBx; - dB(b, 1, k, j, i) = curlBy; - dB(b, 2, k, j, i) = curlBz; - - lsum += (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); - - }, - b2_sum); + + pmb->par_reduce( + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + + // First, needs to rescale the perturb_pack, ie. the magnetic field potential + Real perturb2_k_jp_i, perturb2_k_jm_i, perturb1_kp_j_i, perturb1_km_j_i; + Real perturb0_kp_j_i, perturb0_km_j_i, perturb2_k_j_ip, perturb2_k_j_im; + Real perturb1_k_j_ip, perturb1_k_j_im, perturb0_k_jp_i, perturb0_k_jm_i; + + perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i); + perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i); + perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i); + perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i); + perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i); + perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i); + perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1); + perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1); + perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1); + perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1); + perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i); + perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i); + + // Then, compute the curl of the magnetic field + + Real curlBx, curlBy, curlBz; + + curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - + (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0; + curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - + (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0; + curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - + (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0; + + dB(b, 0, k, j, i) = curlBx; + dB(b, 1, k, j, i) = curlBy; + dB(b, 2, k, j, i) = curlBz; + + lsum += + (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); + }, + b2_sum); } - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); @@ -1155,45 +1174,44 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - - if (standard_B){ - + + if (standard_B) { + pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - u(IB1, k, j, i) /= b_norm; - u(IB2, k, j, i) /= b_norm; - u(IB3, k, j, i) /= b_norm; - - u(IEN, k, j, i) += - 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); - }); - + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + u(IB1, k, j, i) /= b_norm; + u(IB2, k, j, i) /= b_norm; + u(IB3, k, j, i) /= b_norm; + + u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + + SQR(u(IB3, k, j, i))); + }); + } else { - - pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - dB(b, 0, k, j, i) /= b_norm; - dB(b, 1, k, j, i) /= b_norm; - dB(b, 2, k, j, i) /= b_norm; - - // Computing energy - dB(b, 3, k, j, i) += - 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + SQR(dB(b, 2, k, j, i))); - - // Updating the MHD vector - - u(IB1, k, j, i) += dB(b, 0, k, j, i); - u(IB2, k, j, i) += dB(b, 1, k, j, i); - u(IB3, k, j, i) += dB(b, 2, k, j, i); - u(IEN, k, j, i) += dB(b, 3, k, j, i); - - }); + + pmb->par_for( + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + dB(b, 0, k, j, i) /= b_norm; + dB(b, 1, k, j, i) /= b_norm; + dB(b, 2, k, j, i) /= b_norm; + + // Computing energy + dB(b, 3, k, j, i) += 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + + SQR(dB(b, 2, k, j, i))); + + // Updating the MHD vector + + u(IB1, k, j, i) += dB(b, 0, k, j, i); + u(IB2, k, j, i) += dB(b, 1, k, j, i); + u(IB3, k, j, i) += dB(b, 2, k, j, i); + u(IEN, k, j, i) += dB(b, 3, k, j, i); + }); } } } @@ -1254,15 +1272,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { @@ -1286,11 +1304,11 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { KOKKOS_LAMBDA(const int k, const int j, const int i) { // get gas properties const Real rho = prim(IDN, k, j, i); - const Real P = prim(IPR, k, j, i); - const Real Bx = prim(IB1, k, j, i); - const Real By = prim(IB2, k, j, i); - const Real Bz = prim(IB3, k, j, i); - const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); + const Real P = prim(IPR, k, j, i); + const Real Bx = prim(IB1, k, j, i); + const Real By = prim(IB2, k, j, i); + const Real Bz = prim(IB3, k, j, i); + const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); // compute Alfven mach number const Real v_A = std::sqrt(B2 / rho); diff --git a/src/pgen/old_cluster/cluster_divartifact.cpp b/src/pgen/old_cluster/cluster_divartifact.cpp index bea9a3de..2d5a1036 100644 --- a/src/pgen/old_cluster/cluster_divartifact.cpp +++ b/src/pgen/old_cluster/cluster_divartifact.cpp @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,67 +509,71 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); - const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - - //parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho",grid_size + 4,grid_size + 4,grid_size + 4); - - parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), - pmc->cellbounds.ncellsk(IndexDomain::entire), - pmc->cellbounds.ncellsj(IndexDomain::entire), - pmc->cellbounds.ncellsi(IndexDomain::entire)); - + const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); + + // parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho",grid_size + 4,grid_size + // + 4,grid_size + 4); + + parthenon::ParArray4D hydrostatic_rho( + "hydrostatic_rho", md->NumBlocks(), pmc->cellbounds.ncellsk(IndexDomain::entire), + pmc->cellbounds.ncellsj(IndexDomain::entire), + pmc->cellbounds.ncellsi(IndexDomain::entire)); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - - IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); - IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); - IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); + IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); + IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto isothermal_sphere = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); - const auto isothermal_hernquist = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto isothermal_sphere = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); + const auto isothermal_hernquist = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -578,83 +584,85 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else if (isothermal_sphere) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real mu = hydro_pkg->Param("mu"); - const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); - const Real grav_const = units.gravitational_constant(); - - std::cout << "Entering isothermal sphere generation \n" ; - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real mu = hydro_pkg->Param("mu"); + const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); + const Real grav_const = units.gravitational_constant(); + + std::cout << "Entering isothermal sphere generation \n"; + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real rho_r = prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); - const Real P_r = (prefactor/2) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real rho_r = + prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); + const Real P_r = (prefactor / 2) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else if (isothermal_hernquist) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real m_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); - const Real r_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); - const Real mu = hydro_pkg->Param("mu"); - const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); - const Real grav_const = units.gravitational_constant(); - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real m_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); + const Real r_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); + const Real mu = hydro_pkg->Param("mu"); + const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); + const Real grav_const = units.gravitational_constant(); + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real phi_r = - grav_const * m_bcg_s / (r_effective + r_bcg_s); - const Real rho_r = rho_0 * std::exp( - mu * units.mh() / (units.k_boltzmann() * T_bcg_s) * phi_r); - const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real phi_r = -grav_const * m_bcg_s / (r_effective + r_bcg_s); + const Real rho_r = rho_0 * std::exp(-mu * units.mh() / + (units.k_boltzmann() * T_bcg_s) * phi_r); + const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } - + else { - + /************************************************************ * Initialize a HydrostaticEquilibriumSphere ************************************************************/ @@ -662,38 +670,36 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - - const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); - + + const auto P_rho_profile = + he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", - parthenon::DevExecSpace(), kb.s-1, kb.e+1, jb.s-1, jb.e+1, ib.s-1, ib.e+1, - KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - + parthenon::DevExecSpace(), kb.s - 1, kb.e + 1, jb.s - 1, jb.e + 1, ib.s - 1, + ib.e + 1, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile - const Real P_r = P_rho_profile.P_from_r(r); + const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - - //u(IDN, k, j, i) = rho_r; + + // u(IDN, k, j, i) = rho_r; u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - + // Updating hydrostatic_rho table hydrostatic_rho(b, k, j, i) = rho_r; - }); - } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -701,7 +707,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -711,14 +717,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -735,22 +741,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -758,7 +764,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -772,7 +777,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -788,7 +793,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -800,159 +805,168 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - - // Create an homogeneous sphere of a density superior or inferior to the background density - + + // Create an homogeneous sphere of a density superior or inferior to the background + // density + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 260; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Case where the box is filled with perturbations of equal mean amplitude - if (full_box){ - - u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * (u(IDN, k, j, i) / 29.6); - hydrostatic_rho(gks + k, gjs + j, gis + i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * (u(IDN, k, j, i) / 29.6); + if (full_box) { + + u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * + (u(IDN, k, j, i) / 29.6); + hydrostatic_rho(gks + k, gjs + j, gis + i) += + perturb_amplitude * rho_init[gks + k][gjs + j][gis + i] * + (u(IDN, k, j, i) / 29.6); } - - }, passive_scalar); - - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real v2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { @@ -979,12 +993,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -999,16 +1013,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ - const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto density_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); - const auto standard_B = pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); - const auto r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); - + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto density_scale = + pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); + const auto standard_B = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); + const auto r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -1016,136 +1034,137 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - - // Defining a new table that will contains the values of the perturbed magnetic field, and magnetic energy + + // Defining a new table that will contains the values of the perturbed magnetic field, + // and magnetic energy parthenon::ParArray5D dB("turbulent magnetic field", num_blocks, 4, - pmb->cellbounds.ncellsk(IndexDomain::entire), - pmb->cellbounds.ncellsj(IndexDomain::entire), - pmb->cellbounds.ncellsi(IndexDomain::entire)); - + pmb->cellbounds.ncellsk(IndexDomain::entire), + pmb->cellbounds.ncellsj(IndexDomain::entire), + pmb->cellbounds.ncellsi(IndexDomain::entire)); + // Modifying the magnetic potential so that it follows the rho profile pmb->par_for( - "Init sigma_b", 0, num_blocks - 1, kb.s-1, kb.e+1, jb.s-1, jb.e+1, ib.s-1, ib.e+1, + "Init sigma_b", 0, num_blocks - 1, kb.s - 1, kb.e + 1, jb.s - 1, jb.e + 1, + ib.s - 1, ib.e + 1, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - - auto pmb = md->GetBlockData(b)->GetBlockPointer(); + + auto pmb = md->GetBlockData(b)->GetBlockPointer(); const auto gis = pmb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmb->loc.lx2() * pmb->block_size.nx2; - const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; - + const auto gks = pmb->loc.lx3() * pmb->block_size.nx3; + perturb_pack(b, 0, k, j, i) *= hydrostatic_rho(b, k, j, i); perturb_pack(b, 1, k, j, i) *= hydrostatic_rho(b, k, j, i); perturb_pack(b, 2, k, j, i) *= hydrostatic_rho(b, k, j, i); - - //perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - //perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - //perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); - - //perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - //perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - //perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); - - }); - - if (standard_B){ - + + // perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(gks + k, gjs + j, gis + // + i),alpha_b); perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(gks + + // k, gjs + j, gis + i),alpha_b); perturb_pack(b, 2, k, j, i) *= + // std::pow(hydrostatic_rho(gks + k, gjs + j, gis + i),alpha_b); + + // perturb_pack(b, 0, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + // perturb_pack(b, 1, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + // perturb_pack(b, 2, k, j, i) *= std::pow(hydrostatic_rho(b, k, j, i),alpha_b); + }); + + if (standard_B) { + std::cout << "Entering standard B" << std::endl; - + pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - - // The following restriction could be lifted, but requires refactoring of the - // logic for the normalization/reduction below - - PARTHENON_REQUIRE( - u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - "Found existing non-zero B when setting magnetic field perturbations."); - u(IB1, k, j, i) = - (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0; - u(IB2, k, j, i) = - (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0; - u(IB3, k, j, i) = - (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0; - - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * - coords.CellVolume(k, j, i); - }, - b2_sum); - + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + + // The following restriction could be lifted, but requires refactoring of the + // logic for the normalization/reduction below + + PARTHENON_REQUIRE( + u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && + u(IB3, k, j, i) == 0.0, + "Found existing non-zero B when setting magnetic field perturbations."); + u(IB1, k, j, i) = + (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0; + u(IB2, k, j, i) = + (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0; + u(IB3, k, j, i) = + (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0; + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * + coords.CellVolume(k, j, i); + }, + b2_sum); + } else { - - pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - - // First, needs to rescale the perturb_pack, ie. the magnetic field potential - Real perturb2_k_jp_i,perturb2_k_jm_i,perturb1_kp_j_i,perturb1_km_j_i; - Real perturb0_kp_j_i,perturb0_km_j_i,perturb2_k_j_ip,perturb2_k_j_im; - Real perturb1_k_j_ip,perturb1_k_j_im,perturb0_k_jp_i,perturb0_k_jm_i; - - perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i); - perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i); - perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i); - perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i); - perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i); - perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i); - perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1); - perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1); - perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1); - perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1); - perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i); - perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i); - - // Then, compute the curl of the magnetic field - - Real curlBx,curlBy,curlBz; - - curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - - (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0 ; - curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - - (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0 ; - curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - - (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0 ; - - dB(b, 0, k, j, i) = curlBx; - dB(b, 1, k, j, i) = curlBy; - dB(b, 2, k, j, i) = curlBz; - - lsum += (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); - - }, - b2_sum); + + pmb->par_reduce( + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + + // First, needs to rescale the perturb_pack, ie. the magnetic field potential + Real perturb2_k_jp_i, perturb2_k_jm_i, perturb1_kp_j_i, perturb1_km_j_i; + Real perturb0_kp_j_i, perturb0_km_j_i, perturb2_k_j_ip, perturb2_k_j_im; + Real perturb1_k_j_ip, perturb1_k_j_im, perturb0_k_jp_i, perturb0_k_jm_i; + + perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i); + perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i); + perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i); + perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i); + perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i); + perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i); + perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1); + perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1); + perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1); + perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1); + perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i); + perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i); + + // Then, compute the curl of the magnetic field + + Real curlBx, curlBy, curlBz; + + curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - + (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0; + curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - + (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0; + curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - + (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0; + + dB(b, 0, k, j, i) = curlBx; + dB(b, 1, k, j, i) = curlBy; + dB(b, 2, k, j, i) = curlBz; + + lsum += + (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); + }, + b2_sum); } - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); @@ -1155,45 +1174,44 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - - if (standard_B){ - + + if (standard_B) { + pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - u(IB1, k, j, i) /= b_norm; - u(IB2, k, j, i) /= b_norm; - u(IB3, k, j, i) /= b_norm; - - u(IEN, k, j, i) += - 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); - }); - + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + u(IB1, k, j, i) /= b_norm; + u(IB2, k, j, i) /= b_norm; + u(IB3, k, j, i) /= b_norm; + + u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + + SQR(u(IB3, k, j, i))); + }); + } else { - - pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - dB(b, 0, k, j, i) /= b_norm; - dB(b, 1, k, j, i) /= b_norm; - dB(b, 2, k, j, i) /= b_norm; - - // Computing energy - dB(b, 3, k, j, i) += - 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + SQR(dB(b, 2, k, j, i))); - - // Updating the MHD vector - - u(IB1, k, j, i) += dB(b, 0, k, j, i); - u(IB2, k, j, i) += dB(b, 1, k, j, i); - u(IB3, k, j, i) += dB(b, 2, k, j, i); - u(IEN, k, j, i) += dB(b, 3, k, j, i); - - }); + + pmb->par_for( + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + dB(b, 0, k, j, i) /= b_norm; + dB(b, 1, k, j, i) /= b_norm; + dB(b, 2, k, j, i) /= b_norm; + + // Computing energy + dB(b, 3, k, j, i) += 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + + SQR(dB(b, 2, k, j, i))); + + // Updating the MHD vector + + u(IB1, k, j, i) += dB(b, 0, k, j, i); + u(IB2, k, j, i) += dB(b, 1, k, j, i); + u(IB3, k, j, i) += dB(b, 2, k, j, i); + u(IEN, k, j, i) += dB(b, 3, k, j, i); + }); } } } @@ -1254,15 +1272,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { @@ -1286,11 +1304,11 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { KOKKOS_LAMBDA(const int k, const int j, const int i) { // get gas properties const Real rho = prim(IDN, k, j, i); - const Real P = prim(IPR, k, j, i); - const Real Bx = prim(IB1, k, j, i); - const Real By = prim(IB2, k, j, i); - const Real Bz = prim(IB3, k, j, i); - const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); + const Real P = prim(IPR, k, j, i); + const Real Bx = prim(IB1, k, j, i); + const Real By = prim(IB2, k, j, i); + const Real Bz = prim(IB3, k, j, i); + const Real B2 = (SQR(Bx) + SQR(By) + SQR(Bz)); // compute Alfven mach number const Real v_A = std::sqrt(B2 / rho); diff --git a/src/pgen/old_cluster/cluster_modified.cpp b/src/pgen/old_cluster/cluster_modified.cpp index 623a7e88..feca9e8a 100644 --- a/src/pgen/old_cluster/cluster_modified.cpp +++ b/src/pgen/old_cluster/cluster_modified.cpp @@ -26,7 +26,6 @@ // #include // HDF5 #include "../../external/HighFive/include/highfive/H5Easy.hpp" - // Parthenon headers #include "kokkos_abstraction.hpp" #include "mesh/domain.hpp" @@ -279,7 +278,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ @@ -407,25 +405,19 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - - - - - - - + /************************************************************ * Read Density perturbation ************************************************************/ - - //const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - //hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + // const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", + // "init_perturb_rho", false); hydro_pkg->AddParam<>("init_perturb_rho", + // init_perturb_rho); + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -524,14 +516,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + std::cout << "Setting uniform gas"; - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -542,7 +534,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else { /************************************************************ @@ -552,9 +544,9 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", @@ -684,10 +676,10 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - /************************************************************ + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); @@ -695,77 +687,83 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - - /************************************************************ + const auto num_blocks = md->NumBlocks(); + + /************************************************************ * Set initial density perturbations ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + if (init_perturb_rho == true) { - - // File load - - auto init_perturb_rho_file = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_file"); - auto init_perturb_rho_keys = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); - + + // File load + + auto init_perturb_rho_file = + pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_file"); + auto init_perturb_rho_keys = + pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); + hydro_pkg->AddParam<>("cluster/init_perturb_rho_file", init_perturb_rho_file); - hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); - + hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); + std::cout << "Setting density perturbation"; - + // Read HDF5 file containing the density std::string filename_rho = "/work/bbd0833/test/rho.h5"; std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - auto rho_init = H5Easy::load, 64>, 64>>(file, keys_rho); - + auto rho_init = H5Easy::load, 64>, 64>>( + file, keys_rho); + parthenon::par_for( - DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", - parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IDN, k, j, i) = rho_init[k-2][j-2][i-2]; - }); - + DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", + parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { + u(IDN, k, j, i) = rho_init[k - 2][j - 2][i - 2]; + }); + /* - auto init_perturb_rho_file = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_file"); - auto init_perturb_rho_keys = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); - + auto init_perturb_rho_file = pin->GetString("problem/cluster/init_perturb", + "init_perturb_rho_file"); auto init_perturb_rho_keys = + pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); + hydro_pkg->AddParam<>("cluster/init_perturb_rho_file", init_perturb_rho_file); - hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); - + hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); + std::cout << "Setting density perturbation"; - + // Read HDF5 file containing the density std::string filename_rho = "/work/bbd0833/test/rho.h5"; std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - auto rho_init = H5Easy::load, 64>, 64>>(file, keys_rho); - + auto rho_init = H5Easy::load, 64>, + 64>>(file, keys_rho); + Real passive_scalar = 0.0; // Useless - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Adding the value of the density field - + u(IDN, k, j, i) = rho_init[k-2][j-2][i-2]; if (rho_init[k-2][j-2][i-2] < 0.0) { - std::cout << "Negative density for rho_init[" << k-2 << "][" << j-2 << "][" << i-2 << "]: " << rho_init[k-2][j-2][i-2] << "\n";} - + std::cout << "Negative density for rho_init[" << k-2 << "][" << j-2 << "][" << i-2 << + "]: " << rho_init[k-2][j-2][i-2] << "\n";} + }, passive_scalar); - + */ } - - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ @@ -778,7 +776,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain @@ -971,15 +968,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { diff --git a/src/pgen/old_cluster/cluster_temp.cpp b/src/pgen/old_cluster/cluster_temp.cpp index 44f1bbfc..97b75d81 100644 --- a/src/pgen/old_cluster/cluster_temp.cpp +++ b/src/pgen/old_cluster/cluster_temp.cpp @@ -152,7 +152,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -175,49 +175,47 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ - + // Build cluster_gravity object ClusterGravity cluster_gravity(pin, hydro_pkg); - + // Include gravity as a source term during evolution const bool gravity_srcterm = pin->GetBoolean("problem/cluster/gravity", "gravity_srcterm"); hydro_pkg->AddParam<>("gravity_srcterm", gravity_srcterm); - + /************************************************************ * Read Initial Entropy Profile ************************************************************/ - + // Create hydrostatic sphere with ACCEPT entropy profile ACCEPTEntropyProfile entropy_profile(pin); - + HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - + // Create hydrostatic sphere with ISOTHERMAL entropy profile - - - + /************************************************************ - * Read Precessing Jet Coordinate system - ************************************************************/ - + * Read Precessing Jet Coordinate system + ************************************************************/ + JetCoordsFactory jet_coords_factory(pin, hydro_pkg); - + /************************************************************ * Read AGN Feedback ************************************************************/ - + AGNFeedback agn_feedback(pin, hydro_pkg); - + /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -226,7 +224,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - + // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? bool magnetic_tower_power_scaling = @@ -280,7 +278,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam("cluster_vceil", vceil); hydro_pkg->AddParam("cluster_vAceil", vAceil); hydro_pkg->AddParam("cluster_clip_r", clip_r); - + /************************************************************ * Start running reductions into history outputs for clips, stellar mass, cold * gas, and AGN extent @@ -335,16 +333,16 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hst_vars.emplace_back(parthenon::HistoryOutputVar( parthenon::UserHistoryOperation::max, LocalReduceAGNExtent, "agn_extent")); } - + hydro_pkg->UpdateParam(parthenon::hist_param_key, hst_vars); - + /************************************************************ * Add derived fields * NOTE: these must be filled in UserWorkBeforeOutput ************************************************************/ - + auto m = Metadata({Metadata::Cell, Metadata::OneCopy}, std::vector({1})); - + // log10 of cell-centered radius hydro_pkg->AddField("log10_cell_radius", m); // entropy @@ -353,12 +351,12 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { // alfven Mach number v_A/c_s hydro_pkg->AddField("mach_alfven", m); @@ -366,46 +364,51 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - + /************************************************************ * Read Density perturbation ************************************************************/ - - const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); // Mean density of perturbations - + + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", + 0.0); // Mean density of perturbations + if (mu_rho != 0.0) { - - auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", "k_min_rho"); // Minimum wavenumber of perturbation + + auto k_min_rho = pin->GetReal("problem/cluster/init_perturb", + "k_min_rho"); // Minimum wavenumber of perturbation auto num_modes_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_rho", 40); auto sol_weight_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "sol_weight_rho", 1.0); - uint32_t rseed_rho = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); - + uint32_t rseed_rho = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_rho", 1); + // Computing the kmax ie. the Nyquist limit - auto grid_ni = pin->GetOrAddInteger("parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis + auto grid_ni = pin->GetOrAddInteger( + "parthenon/mesh", "nx1", 64); // Assuming cubic grid with equal size in each axis auto k_max_rho = grid_ni / 2; - + const auto t_corr_rho = 1e-10; - auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog(num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes - - auto few_modes_ft_rho = FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, - k_vec_rho, k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); - + auto k_vec_rho = utils::few_modes_ft_log::MakeRandomModesLog( + num_modes_rho, k_min_rho, k_max_rho, rseed_rho); // Generating random modes + + auto few_modes_ft_rho = + FewModesFTLog(pin, hydro_pkg, "cluster_perturb_rho", num_modes_rho, k_vec_rho, + k_min_rho, k_max_rho, sol_weight_rho, t_corr_rho, rseed_rho); + hydro_pkg->AddParam<>("cluster/few_modes_ft_rho", few_modes_ft_rho); - + // Add field for initial perturation (must not need to be consistent but defining it // this way is easier for now) Metadata m({Metadata::Cell, Metadata::Derived, Metadata::OneCopy}, std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); - } - + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -423,7 +426,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_v = Lx / l_peak_v; } - + auto num_modes_v = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_v", 40); auto sol_weight_v = @@ -445,11 +448,11 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd std::vector({3})); hydro_pkg->AddField("tmp_perturb", m); } - + /************************************************************ * Read Magnetic field perturbation - ************************************************************/ - + ************************************************************/ + const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); if (sigma_b != 0.0) { PARTHENON_REQUIRE_THROWS(hydro_pkg->Param("fluid") == Fluid::glmmhd, @@ -469,7 +472,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Note that this assumes a cubic box k_peak_b = Lx / l_peak_b; } - + auto num_modes_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "num_modes_b", 40); uint32_t rseed_b = pin->GetOrAddInteger("problem/cluster/init_perturb", "rseed_b", 2); @@ -495,7 +498,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -507,59 +509,63 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd //======================================================================================== void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { - + // This could be more optimized, but require a refactor of init routines being called. // However, given that it's just called during initial setup, this should not be a // performance concern. - - // Defining a table within which the values of the hydrostatic density profile will be stored + + // Defining a table within which the values of the hydrostatic density profile will be + // stored auto pmc = md->GetBlockData(0)->GetBlockPointer(); const auto grid_size = pin->GetOrAddInteger("problem/cluster/mesh", "nx1", 256); - - // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the 2*n_ghost ghost cells - parthenon::ParArray4D hydrostatic_rho("hydrostatic_rho", md->NumBlocks(), - pmc->cellbounds.ncellsk(IndexDomain::entire), - pmc->cellbounds.ncellsj(IndexDomain::entire), - pmc->cellbounds.ncellsi(IndexDomain::entire)); - + + // Here, the pmc-> contains the number of cells of each MESHBLOCK, including the + // 2*n_ghost ghost cells + parthenon::ParArray4D hydrostatic_rho( + "hydrostatic_rho", md->NumBlocks(), pmc->cellbounds.ncellsk(IndexDomain::entire), + pmc->cellbounds.ncellsj(IndexDomain::entire), + pmc->cellbounds.ncellsi(IndexDomain::entire)); + for (int b = 0; b < md->NumBlocks(); b++) { - + auto pmb = md->GetBlockData(b)->GetBlockPointer(); auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - + auto units = hydro_pkg->Param("units"); + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + // Initialize the conserved variables auto &u = pmb->meshblock_data.Get()->Get("cons").data; - + auto &coords = pmb->coords; - + // Get Adiabatic Index const Real gam = pin->GetReal("hydro", "gamma"); const Real gm1 = (gam - 1.0); - + /************************************************************ * Initialize the initial hydro state ************************************************************/ - const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); - const auto isothermal_sphere = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); - const auto isothermal_hernquist = pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); - + const auto &init_uniform_gas = hydro_pkg->Param("init_uniform_gas"); + const auto isothermal_sphere = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_sphere", false); + const auto isothermal_hernquist = + pin->GetOrAddBoolean("problem/cluster/gravity", "isothermal_hernquist", false); + if (init_uniform_gas) { const Real rho = hydro_pkg->Param("uniform_gas_rho"); const Real ux = hydro_pkg->Param("uniform_gas_ux"); const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -570,81 +576,83 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else if (isothermal_sphere) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real mu = hydro_pkg->Param("mu"); - const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); - const Real grav_const = units.gravitational_constant(); - - std::cout << "Entering isothermal sphere generation \n" ; - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real mu = hydro_pkg->Param("mu"); + const Real prefactor = 2 * units.k_boltzmann() * T_bcg_s / (mu * units.mh()); + const Real grav_const = units.gravitational_constant(); + + std::cout << "Entering isothermal sphere generation \n"; + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real rho_r = prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); - const Real P_r = (prefactor/2) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real rho_r = + prefactor * 1 / (4 * M_PI * grav_const * r_effective * r_effective); + const Real P_r = (prefactor / 2) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } else if (isothermal_hernquist) { - - const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); - const Real m_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); - const Real r_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); - const Real mu = hydro_pkg->Param("mu"); - const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); - const Real grav_const = units.gravitational_constant(); - + + const Real T_bcg_s = pin->GetOrAddReal("problem/cluster/gravity", "T_bcg_s", 10000); + const Real m_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "m_bcg_s", 7.5e10 * units.msun()); + const Real r_bcg_s = + pin->GetOrAddReal("problem/cluster/gravity", "r_bcg_s", 4 * units.kpc()); + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 0.0); + const Real mu = hydro_pkg->Param("mu"); + const Real rho_0 = pin->GetOrAddReal("problem/cluster/gravity", "rho_0", 1e3); + const Real grav_const = units.gravitational_constant(); + // Generating the profile parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::IsothermalSphere", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - // Calculate radius const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - - const Real r_effective = std::max(r_smoothing,r); - - const Real phi_r = - grav_const * m_bcg_s / (r_effective + r_bcg_s); - const Real rho_r = rho_0 * std::exp( - mu * units.mh() / (units.k_boltzmann() * T_bcg_s) * phi_r); - const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; - + + const Real r_effective = std::max(r_smoothing, r); + + const Real phi_r = -grav_const * m_bcg_s / (r_effective + r_bcg_s); + const Real rho_r = rho_0 * std::exp(-mu * units.mh() / + (units.k_boltzmann() * T_bcg_s) * phi_r); + const Real P_r = units.k_boltzmann() * T_bcg_s / (mu * units.mh()) * rho_r; + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - }); - + } - + else { /************************************************************ * Initialize a HydrostaticEquilibriumSphere @@ -653,9 +661,9 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", @@ -665,24 +673,23 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real r = sqrt(coords.Xc<1>(i) * coords.Xc<1>(i) + coords.Xc<2>(j) * coords.Xc<2>(j) + coords.Xc<3>(k) * coords.Xc<3>(k)); - + // Get pressure and density from generated profile const Real P_r = P_rho_profile.P_from_r(r); const Real rho_r = P_rho_profile.rho_from_r(r); - + // Fill conserved states, 0 initial velocity u(IDN, k, j, i) = rho_r; u(IM1, k, j, i) = 0.0; u(IM2, k, j, i) = 0.0; u(IM3, k, j, i) = 0.0; u(IEN, k, j, i) = P_r / gm1; - + // Updating hydrostatic_rho table hydrostatic_rho(b, k, j, i) = rho_r; - }); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -690,7 +697,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { parthenon::ParArray4D A("A", 3, pmb->cellbounds.ncellsk(IndexDomain::entire), pmb->cellbounds.ncellsj(IndexDomain::entire), pmb->cellbounds.ncellsi(IndexDomain::entire)); - + IndexRange a_ib = ib; a_ib.s -= 1; a_ib.e += 1; @@ -700,14 +707,14 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { IndexRange a_kb = kb; a_kb.s -= 1; a_kb.e += 1; - + /************************************************************ * Initialize an initial magnetic tower ************************************************************/ const auto &magnetic_tower = hydro_pkg->Param("magnetic_tower"); - + magnetic_tower.AddInitialFieldToPotential(pmb.get(), a_kb, a_jb, a_ib, A); - + /************************************************************ * Add dipole magnetic field to the magnetic potential ************************************************************/ @@ -724,22 +731,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); - + const Real r3 = pow(SQR(x) + SQR(y) + SQR(z), 3. / 2); - + const Real m_cross_r_x = my * z - mz * y; const Real m_cross_r_y = mz * x - mx * z; const Real m_cross_r_z = mx * y - mx * y; - + // To check whether there is some component before initiating perturbations std::cout << "A(0, k, j, i)=" << A(0, k, j, i) << std::endl; - + A(0, k, j, i) += m_cross_r_x / (4 * M_PI * r3); A(1, k, j, i) += m_cross_r_y / (4 * M_PI * r3); A(2, k, j, i) += m_cross_r_z / (4 * M_PI * r3); }); } - + /************************************************************ * Apply the potential to the conserved variables ************************************************************/ @@ -747,7 +754,6 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::ApplyMagneticPotential", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - u(IB1, k, j, i) = (A(2, k, j + 1, i) - A(2, k, j - 1, i)) / coords.Dxc<2>(j) / 2.0 - (A(1, k + 1, j, i) - A(1, k - 1, j, i)) / coords.Dxc<3>(k) / 2.0; @@ -761,7 +767,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); }); - + /************************************************************ * Add uniform magnetic field to the conserved variables ************************************************************/ @@ -777,7 +783,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real bx_i = u(IB1, k, j, i); const Real by_i = u(IB2, k, j, i); const Real bz_i = u(IB3, k, j, i); - + u(IB1, k, j, i) += bx; u(IB2, k, j, i) += by; u(IB3, k, j, i) += bz; @@ -789,180 +795,191 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { }); // end if(init_uniform_b_field) } - + } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - - /************************************************************ + + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - + const auto num_blocks = md->NumBlocks(); + /************************************************************ * Set initial density perturbations (read from HDF5 file) ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - - // Create an homogeneous sphere of a density superior or inferior to the background density - + + // Create an homogeneous sphere of a density superior or inferior to the background + // density + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", "init_perturb_rho_file","none"); - - const Real r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); - const Real perturb_amplitude = pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); - + + auto filename_rho = pin->GetOrAddString("problem/cluster/init_perturb", + "init_perturb_rho_file", "none"); + + const Real r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 1e-6); + const Real perturb_amplitude = + pin->GetOrAddReal("problem/cluster/init_perturb", "perturb_amplitude", 1); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.01); + std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - + const int rho_init_size = 256; - auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>(file, keys_rho); - + auto rho_init = H5Easy::load, rho_init_size>, rho_init_size>>( + file, keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "Entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1() * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2() * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3() * pmb->block_size.nx3; const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Case where the box is filled with perturbations of equal mean amplitude - if (full_box){ - - u(IDN, k, j, i) += perturb_amplitude * rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * (u(IDN, k, j, i) / 29.6); - + if (full_box) { + + u(IDN, k, j, i) += perturb_amplitude * + rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * + (u(IDN, k, j, i) / 29.6); + } - - // Mean amplitude of the perturbations is modulated by the + + // Mean amplitude of the perturbations is modulated by the else { - - const Real x = coords.Xc<1>(i); - const Real y = coords.Xc<2>(j); - const Real z = coords.Xc<3>(k); - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_effective = std::max(r,r_smoothing); - - //u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; - + + const Real x = coords.Xc<1>(i); + const Real y = coords.Xc<2>(j); + const Real z = coords.Xc<3>(k); + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_effective = std::max(r, r_smoothing); + + // u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; } - }, passive_scalar); - } - + /************************************************************ * Setting up a perturbed density field (hardcoded version) ************************************************************/ - + const auto mu_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "mu_rho", 0.0); - const auto background_rho = pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); - + const auto background_rho = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_rho", 0.0); + if (mu_rho != 0.0) { - + auto few_modes_ft_rho = hydro_pkg->Param("cluster/few_modes_ft_rho"); - + // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft_rho.SetPhases(pmb.get(), pin); - } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_v) const Real dt = 1.0; few_modes_ft_rho.Generate(md, dt, "tmp_perturb"); - + Real v2_sum_rho = 0.0; // used for normalization - + auto perturb_pack_rho = md->PackVariables(std::vector{"tmp_perturb"}); - + pmb->par_reduce( "Init sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - - Real perturb = 0.0 ; - - perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + SQR(perturb_pack_rho(b, 1, k, j, i)) + SQR(perturb_pack_rho(b, 2, k, j, i))); + + Real perturb = 0.0; + + perturb = std::sqrt(SQR(perturb_pack_rho(b, 0, k, j, i)) + + SQR(perturb_pack_rho(b, 1, k, j, i)) + + SQR(perturb_pack_rho(b, 2, k, j, i))); u(IDN, k, j, i) = background_rho + mu_rho * perturb; - }, v2_sum_rho); @@ -970,22 +987,20 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum_rho, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain @@ -1023,12 +1038,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &v2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); #endif // MPI_PARALLEL - + const auto Lx = pmesh->mesh_size.x1max - pmesh->mesh_size.x1min; const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto v_norm = std::sqrt(v2_sum / (Lx * Ly * Lz) / (SQR(sigma_v))); - + pmb->par_for( "Norm sigma_v", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { @@ -1043,17 +1058,22 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IDN, k, j, i); }); } - + /************************************************************ * Set initial magnetic field perturbations (resets magnetic field field) ************************************************************/ const auto sigma_b = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_b", 0.0); - const auto alpha_b = pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0/3.0); - const auto density_scale = pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); - const auto standard_B = pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); - const auto r_smoothing = pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); - const auto rho_type = pin->GetOrAddInteger("problem/cluster/init_perturb", "rho_type", 0); // test - + const auto alpha_b = + pin->GetOrAddReal("problem/cluster/init_perturb", "alpha_b", 2.0 / 3.0); + const auto density_scale = + pin->GetOrAddReal("problem/cluster/init_perturb", "density_scale", 29.6); + const auto standard_B = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "standard_B", true); + const auto r_smoothing = + pin->GetOrAddReal("problem/cluster/gravity", "g_smoothing_radius", 5e-3); + const auto rho_type = + pin->GetOrAddInteger("problem/cluster/init_perturb", "rho_type", 0); // test + if (sigma_b != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_b"); // Init phases on all blocks @@ -1061,189 +1081,193 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); } - + // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital b_hat is 0 and the b_hat_new will contain // the perturbation (and is normalized in the following to get the desired sigma_b) const Real dt = 1.0; few_modes_ft.Generate(md, dt, "tmp_perturb"); - + Real b2_sum = 0.0; // used for normalization - + auto perturb_pack = md->PackVariables(std::vector{"tmp_perturb"}); - - // Defining a new table that will contains the values of the perturbed magnetic field, and magnetic energy + + // Defining a new table that will contains the values of the perturbed magnetic field, + // and magnetic energy parthenon::ParArray5D dB("turbulent magnetic field", num_blocks, 4, - pmb->cellbounds.ncellsk(IndexDomain::entire), - pmb->cellbounds.ncellsj(IndexDomain::entire), - pmb->cellbounds.ncellsi(IndexDomain::entire)); - - if (standard_B){ - + pmb->cellbounds.ncellsk(IndexDomain::entire), + pmb->cellbounds.ncellsj(IndexDomain::entire), + pmb->cellbounds.ncellsi(IndexDomain::entire)); + + if (standard_B) { + pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - const auto &coords = cons.GetCoords(b); - const auto &u = cons(b); - // The following restriction could be lifted, but requires refactoring of the - // logic for the normalization/reduction below - PARTHENON_REQUIRE( - u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - "Found existing non-zero B when setting magnetic field perturbations."); - u(IB1, k, j, i) = - (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0 - - (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0; - u(IB2, k, j, i) = - (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / - coords.Dxc<3>(k) / 2.0 - - (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0; - u(IB3, k, j, i) = - (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / - coords.Dxc<1>(i) / 2.0 - - (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / - coords.Dxc<2>(j) / 2.0; + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + const auto &u = cons(b); + // The following restriction could be lifted, but requires refactoring of the + // logic for the normalization/reduction below + PARTHENON_REQUIRE( + u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && + u(IB3, k, j, i) == 0.0, + "Found existing non-zero B when setting magnetic field perturbations."); + u(IB1, k, j, i) = + (perturb_pack(b, 2, k, j + 1, i) - perturb_pack(b, 2, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0 - + (perturb_pack(b, 1, k + 1, j, i) - perturb_pack(b, 1, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0; + u(IB2, k, j, i) = + (perturb_pack(b, 0, k + 1, j, i) - perturb_pack(b, 0, k - 1, j, i)) / + coords.Dxc<3>(k) / 2.0 - + (perturb_pack(b, 2, k, j, i + 1) - perturb_pack(b, 2, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0; + u(IB3, k, j, i) = + (perturb_pack(b, 1, k, j, i + 1) - perturb_pack(b, 1, k, j, i - 1)) / + coords.Dxc<1>(i) / 2.0 - + (perturb_pack(b, 0, k, j + 1, i) - perturb_pack(b, 0, k, j - 1, i)) / + coords.Dxc<2>(j) / 2.0; + + // No need to touch the energy yet as we'll normalize later + lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * + coords.CellVolume(k, j, i); + }, + b2_sum); - // No need to touch the energy yet as we'll normalize later - lsum += (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))) * - coords.CellVolume(k, j, i); - }, - b2_sum); - } else { - - // Idea: separate into two loops, one par_for and one par_reduce - - std::cout << "Setting up perturbed magnetic field." << std::endl; - - for (int b = 0; b < md->NumBlocks(); b++) { - - std::cout << "Treating block number " << b << " out of " << md->NumBlocks() << std::endl; - - auto pmb = md->GetBlockData(b)->GetBlockPointer(); - auto hydro_pkg = pmb->packages.Get("Hydro"); - auto units = hydro_pkg->Param("units"); - - IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); - IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); - IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - - // Computation of the P_rho_profile require entire domain of the block (boundary conditions for curl computation) - IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); - IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); - IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); - - // Initialize the conserved variables - auto &u = pmb->meshblock_data.Get()->Get("cons").data; - auto &coords = pmb->coords; - - const auto &he_sphere = - hydro_pkg - ->Param>( - "hydrostatic_equilibirum_sphere"); - - const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); - - // initialize conserved variables - parthenon::par_for( - DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::MagneticPerturbations", - parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { - - const Real x = coords.Xc<1>(i); - const Real xp = coords.Xc<1>(i+1); - const Real xm = coords.Xc<1>(i-1); - const Real y = coords.Xc<2>(j); - const Real yp = coords.Xc<2>(j+1); - const Real ym = coords.Xc<2>(j-1); - const Real z = coords.Xc<3>(k); - const Real zp = coords.Xc<3>(k+1); - const Real zm = coords.Xc<3>(k-1); - - const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); - const Real r_ip = sqrt(SQR(xp) + SQR(y) + SQR(z)); - const Real r_im = sqrt(SQR(xm) + SQR(y) + SQR(z)); - const Real r_jp = sqrt(SQR(x) + SQR(yp) + SQR(z)); - const Real r_jm = sqrt(SQR(x) + SQR(ym) + SQR(z)); - const Real r_kp = sqrt(SQR(x) + SQR(y) + SQR(zp)); - const Real r_km = sqrt(SQR(x) + SQR(y) + SQR(zm)); - - const auto rho = P_rho_profile.rho_from_r(r); - const auto rho_ip = P_rho_profile.rho_from_r(r_ip); - const auto rho_im = P_rho_profile.rho_from_r(r_im); - const auto rho_jp = P_rho_profile.rho_from_r(r_jp); - const auto rho_jm = P_rho_profile.rho_from_r(r_jm); - const auto rho_kp = P_rho_profile.rho_from_r(r_kp); - const auto rho_km = P_rho_profile.rho_from_r(r_km); - - // const Real rho_r = P_rho_profile.rho_from_r(r); - - // Normalization condition here, which we want to lift. To do so, we'll need - // to copy the values of the magnetic field into a new array, which we will - // use to store the perturbed magnetic field and then rescale it, until values - // are added to u = cons(b) - - //PARTHENON_REQUIRE( - // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) == 0.0, - // "Found existing non-zero B when setting magnetic field perturbations."); - - // First, needs to rescale the perturb_pack, ie. the magnetic field potential - Real perturb2_k_jp_i,perturb2_k_jm_i,perturb1_kp_j_i,perturb1_km_j_i; - Real perturb0_kp_j_i,perturb0_km_j_i,perturb2_k_j_ip,perturb2_k_j_im; - Real perturb1_k_j_ip,perturb1_k_j_im,perturb0_k_jp_i,perturb0_k_jm_i; - - // Rescaling the magnetic potential - - perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(r_jp, alpha_b); - perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(r_jm, alpha_b); - perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(r_kp, alpha_b); - perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(r_km, alpha_b); - perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(r_kp, alpha_b); - perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(r_km, alpha_b); - perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(r_ip, alpha_b); - perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(r_im, alpha_b); - perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(r_ip, alpha_b); - perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(r_im, alpha_b); - perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(r_jp, alpha_b); - perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(r_jm, alpha_b); - - // Then, compute the curl of the magnetic field - - Real curlBx,curlBy,curlBz; - - curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - - (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0 ; - curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - - (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0 ; - curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - - (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0 ; - - dB(b,0, k, j, i) = curlBx; - dB(b,1, k, j, i) = curlBy; - dB(b,2, k, j, i) = curlBz; - - }); - } - - pmb->par_reduce( - "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - const auto &coords = cons.GetCoords(b); - - Real curlBx,curlBy,curlBz; - - curlBx = dB(b,0, k, j, i); - curlBy = dB(b,1, k, j, i); - curlBz = dB(b,2, k, j, i); - - lsum += (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); - }, - b2_sum); + + // Idea: separate into two loops, one par_for and one par_reduce + + std::cout << "Setting up perturbed magnetic field." << std::endl; + + for (int b = 0; b < md->NumBlocks(); b++) { + + std::cout << "Treating block number " << b << " out of " << md->NumBlocks() + << std::endl; + + auto pmb = md->GetBlockData(b)->GetBlockPointer(); + auto hydro_pkg = pmb->packages.Get("Hydro"); + auto units = hydro_pkg->Param("units"); + + IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); + IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); + IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); + + // Computation of the P_rho_profile require entire domain of the block (boundary + // conditions for curl computation) + IndexRange ib_entire = pmb->cellbounds.GetBoundsI(IndexDomain::entire); + IndexRange jb_entire = pmb->cellbounds.GetBoundsJ(IndexDomain::entire); + IndexRange kb_entire = pmb->cellbounds.GetBoundsK(IndexDomain::entire); + + // Initialize the conserved variables + auto &u = pmb->meshblock_data.Get()->Get("cons").data; + auto &coords = pmb->coords; + + const auto &he_sphere = hydro_pkg->Param< + HydrostaticEquilibriumSphere>( + "hydrostatic_equilibirum_sphere"); + + const auto P_rho_profile = + he_sphere.generate_P_rho_profile(ib_entire, jb_entire, kb_entire, coords); + + // initialize conserved variables + parthenon::par_for( + DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::MagneticPerturbations", + parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int &k, const int &j, const int &i) { + const Real x = coords.Xc<1>(i); + const Real xp = coords.Xc<1>(i + 1); + const Real xm = coords.Xc<1>(i - 1); + const Real y = coords.Xc<2>(j); + const Real yp = coords.Xc<2>(j + 1); + const Real ym = coords.Xc<2>(j - 1); + const Real z = coords.Xc<3>(k); + const Real zp = coords.Xc<3>(k + 1); + const Real zm = coords.Xc<3>(k - 1); + + const Real r = sqrt(SQR(x) + SQR(y) + SQR(z)); + const Real r_ip = sqrt(SQR(xp) + SQR(y) + SQR(z)); + const Real r_im = sqrt(SQR(xm) + SQR(y) + SQR(z)); + const Real r_jp = sqrt(SQR(x) + SQR(yp) + SQR(z)); + const Real r_jm = sqrt(SQR(x) + SQR(ym) + SQR(z)); + const Real r_kp = sqrt(SQR(x) + SQR(y) + SQR(zp)); + const Real r_km = sqrt(SQR(x) + SQR(y) + SQR(zm)); + + const auto rho = P_rho_profile.rho_from_r(r); + const auto rho_ip = P_rho_profile.rho_from_r(r_ip); + const auto rho_im = P_rho_profile.rho_from_r(r_im); + const auto rho_jp = P_rho_profile.rho_from_r(r_jp); + const auto rho_jm = P_rho_profile.rho_from_r(r_jm); + const auto rho_kp = P_rho_profile.rho_from_r(r_kp); + const auto rho_km = P_rho_profile.rho_from_r(r_km); + + // const Real rho_r = P_rho_profile.rho_from_r(r); + + // Normalization condition here, which we want to lift. To do so, we'll need + // to copy the values of the magnetic field into a new array, which we will + // use to store the perturbed magnetic field and then rescale it, until + // values are added to u = cons(b) + + // PARTHENON_REQUIRE( + // u(IB1, k, j, i) == 0.0 && u(IB2, k, j, i) == 0.0 && u(IB3, k, j, i) + // == 0.0, "Found existing non-zero B when setting magnetic field + // perturbations."); + + // First, needs to rescale the perturb_pack, ie. the magnetic field + // potential + Real perturb2_k_jp_i, perturb2_k_jm_i, perturb1_kp_j_i, perturb1_km_j_i; + Real perturb0_kp_j_i, perturb0_km_j_i, perturb2_k_j_ip, perturb2_k_j_im; + Real perturb1_k_j_ip, perturb1_k_j_im, perturb0_k_jp_i, perturb0_k_jm_i; + + // Rescaling the magnetic potential + + perturb2_k_jp_i = perturb_pack(b, 2, k, j + 1, i) * std::pow(r_jp, alpha_b); + perturb2_k_jm_i = perturb_pack(b, 2, k, j - 1, i) * std::pow(r_jm, alpha_b); + perturb1_kp_j_i = perturb_pack(b, 1, k + 1, j, i) * std::pow(r_kp, alpha_b); + perturb1_km_j_i = perturb_pack(b, 1, k - 1, j, i) * std::pow(r_km, alpha_b); + perturb0_kp_j_i = perturb_pack(b, 0, k + 1, j, i) * std::pow(r_kp, alpha_b); + perturb0_km_j_i = perturb_pack(b, 0, k - 1, j, i) * std::pow(r_km, alpha_b); + perturb2_k_j_ip = perturb_pack(b, 2, k, j, i + 1) * std::pow(r_ip, alpha_b); + perturb2_k_j_im = perturb_pack(b, 2, k, j, i - 1) * std::pow(r_im, alpha_b); + perturb1_k_j_ip = perturb_pack(b, 1, k, j, i + 1) * std::pow(r_ip, alpha_b); + perturb1_k_j_im = perturb_pack(b, 1, k, j, i - 1) * std::pow(r_im, alpha_b); + perturb0_k_jp_i = perturb_pack(b, 0, k, j + 1, i) * std::pow(r_jp, alpha_b); + perturb0_k_jm_i = perturb_pack(b, 0, k, j - 1, i) * std::pow(r_jm, alpha_b); + + // Then, compute the curl of the magnetic field + + Real curlBx, curlBy, curlBz; + + curlBx = (perturb2_k_jp_i - perturb2_k_jm_i) / coords.Dxc<2>(j) / 2.0 - + (perturb1_kp_j_i - perturb1_km_j_i) / coords.Dxc<3>(k) / 2.0; + curlBy = (perturb0_kp_j_i - perturb0_km_j_i) / coords.Dxc<3>(k) / 2.0 - + (perturb2_k_j_ip - perturb2_k_j_im) / coords.Dxc<1>(i) / 2.0; + curlBz = (perturb1_k_j_ip - perturb1_k_j_im) / coords.Dxc<1>(i) / 2.0 - + (perturb0_k_jp_i - perturb0_k_jm_i) / coords.Dxc<2>(j) / 2.0; + + dB(b, 0, k, j, i) = curlBx; + dB(b, 1, k, j, i) = curlBy; + dB(b, 2, k, j, i) = curlBz; + }); + } + + pmb->par_reduce( + "Init sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { + const auto &coords = cons.GetCoords(b); + + Real curlBx, curlBy, curlBz; + + curlBx = dB(b, 0, k, j, i); + curlBy = dB(b, 1, k, j, i); + curlBz = dB(b, 2, k, j, i); + + lsum += + (SQR(curlBx) + SQR(curlBy) + SQR(curlBz)) * coords.CellVolume(k, j, i); + }, + b2_sum); } - + #ifdef MPI_PARALLEL PARTHENON_MPI_CHECK(MPI_Allreduce(MPI_IN_PLACE, &b2_sum, 1, MPI_PARTHENON_REAL, MPI_SUM, MPI_COMM_WORLD)); @@ -1253,45 +1277,44 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const auto Ly = pmesh->mesh_size.x2max - pmesh->mesh_size.x2min; const auto Lz = pmesh->mesh_size.x3max - pmesh->mesh_size.x3min; auto b_norm = std::sqrt(b2_sum / (Lx * Ly * Lz) / (SQR(sigma_b))); - - if (standard_B){ - + + if (standard_B) { + pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); - u(IB1, k, j, i) /= b_norm; - u(IB2, k, j, i) /= b_norm; - u(IB3, k, j, i) /= b_norm; + u(IB1, k, j, i) /= b_norm; + u(IB2, k, j, i) /= b_norm; + u(IB3, k, j, i) /= b_norm; + + u(IEN, k, j, i) += 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + + SQR(u(IB3, k, j, i))); + }); - u(IEN, k, j, i) += - 0.5 * (SQR(u(IB1, k, j, i)) + SQR(u(IB2, k, j, i)) + SQR(u(IB3, k, j, i))); - }); - } else { - - pmb->par_for( - "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, - KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { - const auto &u = cons(b); - - dB(b, 0, k, j, i) /= b_norm; - dB(b, 1, k, j, i) /= b_norm; - dB(b, 2, k, j, i) /= b_norm; - - // Computing energy - dB(b, 3, k, j, i) += - 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + SQR(dB(b, 2, k, j, i))); - - // Updating the MHD vector - - u(IB1, k, j, i) += dB(b, 0, k, j, i); - u(IB2, k, j, i) += dB(b, 1, k, j, i); - u(IB3, k, j, i) += dB(b, 2, k, j, i); - u(IEN, k, j, i) += dB(b, 3, k, j, i); - - }); + + pmb->par_for( + "Norm sigma_b", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(const int b, const int k, const int j, const int i) { + const auto &u = cons(b); + + dB(b, 0, k, j, i) /= b_norm; + dB(b, 1, k, j, i) /= b_norm; + dB(b, 2, k, j, i) /= b_norm; + + // Computing energy + dB(b, 3, k, j, i) += 0.5 * (SQR(dB(b, 0, k, j, i)) + SQR(dB(b, 1, k, j, i)) + + SQR(dB(b, 2, k, j, i))); + + // Updating the MHD vector + + u(IB1, k, j, i) += dB(b, 0, k, j, i); + u(IB2, k, j, i) += dB(b, 1, k, j, i); + u(IB3, k, j, i) += dB(b, 2, k, j, i); + u(IEN, k, j, i) += dB(b, 3, k, j, i); + }); } } } @@ -1352,15 +1375,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) { diff --git a/src/pgen/old_cluster/cluster_working.cpp b/src/pgen/old_cluster/cluster_working.cpp index cbdb6dd3..3a2d1618 100644 --- a/src/pgen/old_cluster/cluster_working.cpp +++ b/src/pgen/old_cluster/cluster_working.cpp @@ -103,12 +103,13 @@ void ApplyClusterClips(MeshData *md, const parthenon::SimTime &tm, if (r2 < clip_r2) { // Cell falls within clipping radius - + const int gks = 0; const int gjs = 0; const int gis = 0; - - eos.ConsToPrim(cons, prim, nhydro, nscalars, k, j, i, gks, gjs, gis); // Three last parameters are just passive here + + eos.ConsToPrim(cons, prim, nhydro, nscalars, k, j, i, gks, gjs, + gis); // Three last parameters are just passive here if (dfloor > 0) { const Real rho = prim(IDN, k, j, i); @@ -260,7 +261,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd const Real uniform_b_field_bx = pin->GetReal("problem/cluster/uniform_b_field", "bx"); const Real uniform_b_field_by = pin->GetReal("problem/cluster/uniform_b_field", "by"); const Real uniform_b_field_bz = pin->GetReal("problem/cluster/uniform_b_field", "bz"); - + hydro_pkg->AddParam<>("uniform_b_field_bx", uniform_b_field_bx); hydro_pkg->AddParam<>("uniform_b_field_by", uniform_b_field_by); hydro_pkg->AddParam<>("uniform_b_field_bz", uniform_b_field_bz); @@ -283,7 +284,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddParam<>("dipole_b_field_my", dipole_b_field_my); hydro_pkg->AddParam<>("dipole_b_field_mz", dipole_b_field_mz); } - + /************************************************************ * Read Cluster Gravity Parameters ************************************************************/ @@ -310,9 +311,8 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd HydrostaticEquilibriumSphere hse_sphere(pin, hydro_pkg, cluster_gravity, entropy_profile); - - - /************************************************************ + + /************************************************************ * Read Precessing Jet Coordinate system ************************************************************/ @@ -327,7 +327,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd /************************************************************ * Read AGN Triggering ************************************************************/ - + AGNTriggering agn_triggering(pin, hydro_pkg); /************************************************************ @@ -336,7 +336,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // Build Magnetic Tower MagneticTower magnetic_tower(pin, hydro_pkg); - // Determine if magnetic_tower_power_scaling is needed // Is AGN Power and Magnetic fraction non-zero? @@ -401,7 +400,7 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("mach_sonic", m); // temperature hydro_pkg->AddField("temperature", m); - + if (hydro_pkg->Param("enable_cooling") == Cooling::tabular) { // cooling time hydro_pkg->AddField("cooling_time", m); @@ -414,25 +413,19 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd // plasma beta hydro_pkg->AddField("plasma_beta", m); } - - - - - - - + /************************************************************ * Read Density perturbation ************************************************************/ - - //const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - //hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + // const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", + // "init_perturb_rho", false); hydro_pkg->AddParam<>("init_perturb_rho", + // init_perturb_rho); + /************************************************************ * Read Velocity perturbation ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); if (sigma_v != 0.0) { // peak of init vel perturb @@ -490,7 +483,6 @@ void ProblemInitPackageData(ParameterInput *pin, parthenon::StateDescriptor *hyd hydro_pkg->AddField("tmp_perturb", m); } } - } //======================================================================================== @@ -532,12 +524,12 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { const Real uy = hydro_pkg->Param("uniform_gas_uy"); const Real uz = hydro_pkg->Param("uniform_gas_uz"); const Real pres = hydro_pkg->Param("uniform_gas_pres"); - + const Real Mx = rho * ux; const Real My = rho * uy; const Real Mz = rho * uz; const Real E = rho * (0.5 * (ux * ux + uy * uy + uz * uz) + pres / (gm1 * rho)); - + parthenon::par_for( DEFAULT_LOOP_PATTERN, "Cluster::ProblemGenerator::UniformGas", parthenon::DevExecSpace(), kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, @@ -548,7 +540,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IM3, k, j, i) = Mz; u(IEN, k, j, i) = E; }); - + // end if(init_uniform_gas) } else { /************************************************************ @@ -558,9 +550,9 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { hydro_pkg ->Param>( "hydrostatic_equilibirum_sphere"); - + const auto P_rho_profile = he_sphere.generate_P_rho_profile(ib, jb, kb, coords); - + // initialize conserved variables parthenon::par_for( DEFAULT_LOOP_PATTERN, "cluster::ProblemGenerator::UniformGas", @@ -583,7 +575,7 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { u(IEN, k, j, i) = P_r / gm1; }); } - + if (hydro_pkg->Param("fluid") == Fluid::glmmhd) { /************************************************************ * Initialize the initial magnetic field state via a vector potential @@ -690,197 +682,207 @@ void ProblemGenerator(Mesh *pmesh, ParameterInput *pin, MeshData *md) { } // END if(hydro_pkg->Param("fluid") == Fluid::glmmhd) } - /************************************************************ + /************************************************************ * Initial parameters - ************************************************************/ - + ************************************************************/ + auto pmb = md->GetBlockData(0)->GetBlockPointer(); IndexRange ib = pmb->cellbounds.GetBoundsI(IndexDomain::interior); IndexRange jb = pmb->cellbounds.GetBoundsJ(IndexDomain::interior); IndexRange kb = pmb->cellbounds.GetBoundsK(IndexDomain::interior); - + auto hydro_pkg = pmb->packages.Get("Hydro"); const auto fluid = hydro_pkg->Param("fluid"); auto const &cons = md->PackVariables(std::vector{"cons"}); - const auto num_blocks = md->NumBlocks(); - - /************************************************************ + const auto num_blocks = md->NumBlocks(); + + /************************************************************ * Set initial density perturbations ************************************************************/ - - const bool init_perturb_rho = pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); - const bool full_box = pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); - const Real thickness_ism = pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); - const bool overpressure_ring = pin->GetOrAddBoolean("problem/cluster/init_perturb", "overpressure_ring", false); - const bool spherical_collapse = pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); - + + const bool init_perturb_rho = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "init_perturb_rho", false); + const bool full_box = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "full_box", true); + const Real thickness_ism = + pin->GetOrAddReal("problem/cluster/init_perturb", "thickness_ism", 0.0); + const bool overpressure_ring = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "overpressure_ring", false); + const bool spherical_collapse = + pin->GetOrAddBoolean("problem/cluster/init_perturb", "spherical_collapse", false); + hydro_pkg->AddParam<>("init_perturb_rho", init_perturb_rho); - + Real passive_scalar = 0.0; // Not useful here - + // Spherical collapse test with an initial overdensity - + if (spherical_collapse == true) { - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1 * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2 * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3 * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + const Real x = coords.Xc<1>(i); const Real y = coords.Xc<2>(j); const Real z = coords.Xc<3>(k); const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - const Real background_density = pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); - const Real foreground_density = pin->GetOrAddReal("problem/cluster/init_perturb", "foreground_density", 150); - - // Setting an initial + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + const Real background_density = + pin->GetOrAddReal("problem/cluster/init_perturb", "background_density", 3); + const Real foreground_density = pin->GetOrAddReal( + "problem/cluster/init_perturb", "foreground_density", 150); + + // Setting an initial u(IDN, k, j, i) = background_density; - - // For any cell at a radius less then overdensity radius, set the density to foreground_density - if (r < overdensity_radius){ - u(IDN, k, j, i) = foreground_density; + + // For any cell at a radius less then overdensity radius, set the density to + // foreground_density + if (r < overdensity_radius) { + u(IDN, k, j, i) = foreground_density; } - - //u(IDN, k, j, i) += foreground_density * std::exp(- 2 * SQR(r) / SQR(overdensity_radius) ) ; - - + + // u(IDN, k, j, i) += foreground_density * std::exp(- 2 * SQR(r) / + // SQR(overdensity_radius) ) ; }, passive_scalar); - } - + /* -------------- Setting up a clumpy atmosphere -------------- - + 1) Extract the values of the density from an input hdf5 file using H5Easy 2) Initiate the associated density field 3) Optionnaly, add some overpressure ring to check behavior (overpressure_ring bool) 4) Optionnaly, add a central overdensity - + */ - + if (init_perturb_rho == true) { - - auto init_perturb_rho_file = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_file"); - auto init_perturb_rho_keys = pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); - + + auto init_perturb_rho_file = + pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_file"); + auto init_perturb_rho_keys = + pin->GetString("problem/cluster/init_perturb", "init_perturb_rho_keys"); + hydro_pkg->AddParam<>("cluster/init_perturb_rho_file", init_perturb_rho_file); - hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); - + hydro_pkg->AddParam<>("cluster/init_perturb_rho_keys", init_perturb_rho_keys); + std::cout << "Setting density perturbation"; - + // Read HDF5 file containing the density std::string filename_rho = "/work/bbd0833/test/rho.h5"; std::string keys_rho = "data"; H5Easy::File file(filename_rho, HighFive::File::ReadOnly); - auto rho_init = H5Easy::load, 256>, 256>>(file, keys_rho); - + auto rho_init = + H5Easy::load, 256>, 256>>(file, + keys_rho); + Real passive_scalar = 0.0; // Useless - + std::cout << "entering initialisation of rho field"; - + pmb->par_reduce( "Init density field", 0, num_blocks - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int b, const int k, const int j, const int i, Real &lsum) { - - auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b - + auto pmbb = md->GetBlockData(b)->GetBlockPointer(); // Meshblock b + const auto gis = pmbb->loc.lx1 * pmb->block_size.nx1; const auto gjs = pmbb->loc.lx2 * pmb->block_size.nx2; const auto gks = pmbb->loc.lx3 * pmb->block_size.nx3; - + const auto &coords = cons.GetCoords(b); const auto &u = cons(b); - + // Adding the value of the density field - if (full_box){ - + if (full_box) { + u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2]; - + } - + else { - - const Real z = coords.Xc<3>(k); - + + const Real z = coords.Xc<3>(k); + // if (z > -thickness_ism / 2 && z < thickness_ism / 2){ - - u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * std::exp(- SQR(z) / SQR(thickness_ism)) ; - - + + u(IDN, k, j, i) += rho_init[gks + k - 2][gjs + j - 2][gis + i - 2] * + std::exp(-SQR(z) / SQR(thickness_ism)); } - + // Ring of overpressure // compute radius - if (overpressure_ring){ - - const Real x = coords.Xc<1>(i); - const Real y = coords.Xc<2>(j); - const Real z = coords.Xc<3>(k); - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real width = 0.002; - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - - if (r > 0 && r < overdensity_radius){ - - //u(IEN, k, j, i) *= 100; - - // Pushing a ring of gas outward (kinetic boost) - const Real u_x = x / r; - const Real u_y = y / r; - const Real u_z = z / r; - - const Real velocity_blast = pin->GetOrAddReal("problem/cluster/init_perturb", "velocity_blast", 0.0); - - //u(IEN, k, j, i) *= 100; - - u(IM1, k, j, i) = u_x * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho - u(IM2, k, j, i) = u_y * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho - u(IM3, k, j, i) = u_z * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho - u(IEN, k, j, i) += 0.5 * u(IDN, k, j, i) * (pow(velocity_blast,2)); - } + if (overpressure_ring) { + + const Real x = coords.Xc<1>(i); + const Real y = coords.Xc<2>(j); + const Real z = coords.Xc<3>(k); + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius + const Real width = 0.002; + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + + if (r > 0 && r < overdensity_radius) { + + // u(IEN, k, j, i) *= 100; + + // Pushing a ring of gas outward (kinetic boost) + const Real u_x = x / r; + const Real u_y = y / r; + const Real u_z = z / r; + + const Real velocity_blast = pin->GetOrAddReal( + "problem/cluster/init_perturb", "velocity_blast", 0.0); + + // u(IEN, k, j, i) *= 100; + + u(IM1, k, j, i) = + u_x * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho + u(IM2, k, j, i) = + u_y * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho + u(IM3, k, j, i) = + u_z * velocity_blast * u(IDN, k, j, i); // p = (1 Mpc / Gyr) * rho + u(IEN, k, j, i) += 0.5 * u(IDN, k, j, i) * (pow(velocity_blast, 2)); + } } - - if (spherical_collapse){ - - const Real x = coords.Xc<1>(i); - const Real y = coords.Xc<2>(j); - const Real z = coords.Xc<3>(k); - const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius - const Real overdensity_radius = pin->GetOrAddReal("problem/cluster/init_perturb", "overdensity_radius", 0.01); - - u(IDN, k, j, i) = 3; - u(IDN, k, j, i) *= 50 * std::exp(- 2 * SQR(r) / SQR(overdensity_radius)); - + + if (spherical_collapse) { + + const Real x = coords.Xc<1>(i); + const Real y = coords.Xc<2>(j); + const Real z = coords.Xc<3>(k); + const Real r = std::sqrt(SQR(x) + SQR(y) + SQR(z)); // Computing radius + const Real overdensity_radius = pin->GetOrAddReal( + "problem/cluster/init_perturb", "overdensity_radius", 0.01); + + u(IDN, k, j, i) = 3; + u(IDN, k, j, i) *= 50 * std::exp(-2 * SQR(r) / SQR(overdensity_radius)); } - }, passive_scalar); - } - + /************************************************************ * Set initial velocity perturbations (requires no other velocities for now) ************************************************************/ - + const auto sigma_v = pin->GetOrAddReal("problem/cluster/init_perturb", "sigma_v", 0.0); - + if (sigma_v != 0.0) { auto few_modes_ft = hydro_pkg->Param("cluster/few_modes_ft_v"); // Init phases on all blocks for (int b = 0; b < md->NumBlocks(); b++) { auto pmb = md->GetBlockData(b)->GetBlockPointer(); few_modes_ft.SetPhases(pmb.get(), pin); - } // As for t_corr in few_modes_ft, the choice for dt is // in principle arbitrary because the inital v_hat is 0 and the v_hat_new will contain @@ -1073,15 +1075,15 @@ void UserWorkBeforeOutput(MeshBlock *pmb, ParameterInput *pin) { // compute temperature temperature(k, j, i) = mbar_over_kb * P / rho; }); - + if (pkg->Param("enable_cooling") == Cooling::tabular) { auto &cooling_time = data->Get("cooling_time").data; - + // get cooling function const cooling::TabularCooling &tabular_cooling = pkg->Param("tabular_cooling"); const auto cooling_table_obj = tabular_cooling.GetCoolingTableObj(); - + pmb->par_for( "Cluster::UserWorkBeforeOutput::CoolingTime", kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, KOKKOS_LAMBDA(const int k, const int j, const int i) {