Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dust coagulation #25

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Open

Dust coagulation #25

wants to merge 11 commits into from

Conversation

shengtai
Copy link
Collaborator

@shengtai shengtai commented Dec 4, 2024

Background

I merged develop branch with my dust module (feedback + coagulation)

Description of Changes

change in the dust.cpp, dust.hpp, artemis.hpp artemis.cpp, artemis_driver.cpp,
added new files for coagulation,
added new input files for dust testing

Checklist

  • New features are documented
  • Tests added for bug fixes and new features
  • (@lanl.gov employees) Update copyright on changed files

@adamdempsey90
Copy link
Collaborator

you need to remove all of your dust drag code from this branch

@brryan
Copy link
Collaborator

brryan commented Dec 5, 2024

This PR also needs a CI-enrolled test associated with the dust_coagulation.in input; see e.g. https://github.com/lanl/artemis/blob/develop/tst/scripts/drag/drag.py for an example test script. Let us know on teams if you want help with working the test into the CI so it runs automatically and checks against a known answer

src/artemis.hpp Outdated
@@ -67,11 +67,13 @@ namespace prim {
ARTEMIS_VARIABLE(dust.prim, density);
ARTEMIS_VARIABLE(dust.prim, velocity);
} // namespace prim
ARTEMIS_VARIABLE(dust, stopping_time);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was removed in the new updated code

Comment on lines 115 to 120
// Execute operator split physics
for (auto &fn : OperatorSplitTasks) {
status = fn(pmesh, tm, integrator->dt).Execute();
if (status != TaskListStatus::complete) return status;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that instead of all this OperatorSplitTasks boilerplate throughout the code, we just add the CoagulationTasks directly into the artemis driver. That will be much cleaner and clearer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like @adamdempsey90 had same thought as my above comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed as you suggested in the new updated code

Comment on lines 193 to 195
// update dust stopping time and dust diffusivity
TaskID dust_stopping_time =
tl.AddTask(none, Dust::UpdateDustStoppingTime<GEOM>, u0.get());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This task can be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I strongly suggest keeping this task and move all dust stopping time calculation to this routine because this is used in many different places. We can reduce the storage to save only the stopping time only for the first dust species, as other dust species only differ by a factor of dust size.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stopping time already has a function that calculates it and is used by the drag package, so at the very least any other package that uses stopping time should call that same function. I don't see the benefit of storing this, since calculating it is so cheap. But this is again one of those areas where we first implement something in a potentially non-performant way, evaluate the performance, and then potentially adjust the implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided previously to calculate stopping times on the fly, templating on the dust stopping model if necessary, rather than store the extra data. Because the (current) stopping models are simple, it is likely to be more performant to recalculate where necessary rather than retrieve the stored values from memory. Assuming dust stopping is proportional to dust size and hardcoding that into the code is the sort of significant complexity that we would only want to do if we measured later that dust stopping really was a bottleneck.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still reading through the PR... it sounds like I should expect to see these computed on the fly whenever they are needed... I agree this is what we want.

Regardless, just a warning that by not placing these definitions in FillDerived (which we don't want, probably), there is some ambiguity on what these derived fields hold upon AMR remeshing (e.g., an output of this field may not contain what you expect if the output follows a remeshing event).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remove this and calculate the stopping time on fly the new code

Comment on lines 32 to 41
const int nm = pin->GetOrAddInteger("dust", "nspecies", 1);
cpars.nm = nm;
cpars.vfrag = pin->GetOrAddReal("dust", "vfrag", 1.e3); // cm/s
cpars.nlim = 1e10;
cpars.integrator = pin->GetOrAddInteger("dust", "coag_int", 3);
cpars.use_adaptive = pin->GetOrAddBoolean("dust", "coag_use_adaptiveStep", true);
cpars.mom_coag = pin->GetOrAddBoolean("dust", "coag_mom_preserve", true);
cpars.nCall_mx = pin->GetOrAddInteger("dust", "coag_nsteps_mx", 1000);
// dust particle internal density g/cc
const Real rho_p = pin->GetOrAddReal("dust", "grain_density", 1.25);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful about adding new default values to parameters that have already been read by the dust package. nspecies, grain_density are two examples.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will modify them to use the same value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in the new updated code

Comment on lines 75 to 96
const Real s_min = pin->GetReal("dust", "min_size");
const Real s_max = pin->GetReal("dust", "max_size");
const Real mmin = 4.0 * M_PI / 3.0 * rho_p * std::pow(s_min, 3);
const Real mmax = 4.0 * M_PI / 3.0 * rho_p * std::pow(s_max, 3);
const Real cond = 1.0 / (1.0 - nm) * std::log(mmin / mmax);
const Real conc = std::log(mmin);
if (std::exp(cond) > std::sqrt(2.0)) {
std::stringstream msg;
msg << "### FATAL ERROR in dust with coagulation: using nspecies >"
<< std::log(mmax / mmin) / (std::log(std::sqrt(2.0))) + 1. << " instead of " << nm
<< std::endl;
PARTHENON_FAIL(msg);
}

ParArray1D<Real> dust_size("dustSize", nm);
auto dust_size_host = dust_size.GetHostMirror();

for (int n = 0; n < nm; ++n) {
Real mgrid = std::exp(conc + cond * n);
dust_size_host(n) = std::pow(3.0 * mgrid / (4.0 * M_PI * cpars.rho_p), 1. / 3.);
}
dust_size.DeepCopy(dust_size_host);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dust package has already read an initialized the dust size array, so this can be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also related to your question why coagulation must uses the "logspace" in dust size input. I will remove this and only retain the check validation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in the new updated code

Comment on lines 149 to 153
if (parthenon::Globals::my_rank == 0) {
for (int n = 0; n < nspecies; n++) {
std::cout << "dust_size(" << n << ")=" << h_sizes(n) << std::endl;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to print this out

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed it in the new updated code

Comment on lines 194 to 221
if (enable_dust_coagulation) {
if (cgsunit == NULL) {
cgsunit = new CGSUnit;
}
if (!cgsunit->isSet()) {
cgsunit->SetCGSUnit(pin);
}
params.Add("cgs_unit", cgsunit);

Real rho_p = rho_p_orig;
// density in physical unit correspinding to code unit 1.
// const Real rho_g0 = pin->GetOrAddReal("dust", "rho_g0", 1.0);
const Real rho_g0 = cgsunit->mass0 / cgsunit->vol0;
// re-scale rho_p to account for rho_g0 for stopping_time calculation
rho_p /= rho_g0;

// re-scale rho_p by prefactor coefficient
if (cgsunit->isurface_den) {
rho_p *= 0.5 * M_PI;
} else {
rho_p *= std::sqrt(M_PI / 8.);
rho_p /= cgsunit->length0;
}

if (parthenon::Globals::my_rank == 0) {
std::cout << "rho_p, rho_g0=" << rho_p << " " << rho_g0 << std::endl;
}
params.Add("rho_p", rho_p);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See earlier comment about not doing unit conversions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in the new committed code

Comment on lines 260 to 264
// dust stopping-time
m = Metadata({Metadata::Cell, Metadata::Derived, Metadata::Intensive, Metadata::OneCopy,
Metadata::Sparse});
m.SetSparseThresholds(0.0, 0.0, 0.0);
dust->AddSparsePool<dust::stopping_time>(m, control_field, dustids);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my comment above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in the new updated code and calculate the stopping time on fly

Comment on lines 292 to 293
TaskStatus UpdateDustStoppingTime(MeshData<Real> *md) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole function can be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in the new code

Comment on lines 375 to 378
auto userDt = params.template Get<Real>("user_dt");
auto nspecies = params.template Get<int>("nspecies");

const auto cfl_number = params.template Get<Real>("cfl");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no reason to modify this function anymore

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in the new code

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 6, 2024 via email

@brryan brryan changed the title Sli/dust merge request Dust coagulation Dec 9, 2024
@@ -0,0 +1,135 @@
# ========================================================================================
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the two dust coagulation input files show be a part of this PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this input file is deleted in the new code

// Licensed under the 3-clause BSD License (the "LICENSE")
//========================================================================================

// NOTE(@pdmullen): The following is taken directly from the open-source
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// NOTE(@pdmullen): The following is taken directly from the open-source
// NOTE(@Shengtai): The following is taken directly from the open-source

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in the new code

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 9, 2024 via email

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 9, 2024 via email

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 9, 2024 via email

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 9, 2024 via email

Copy link
Collaborator

@pdmullen pdmullen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice start @shengtai. I think it needs a bit more work to adopt some artemis-isms, particularly as it relates to sparse compatibility and style.

dust.prim.velocity

file_type = hdf5 # HDF5 data dump
dt = 2.0 # time increment between outputs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

align comments here and elsewhere.

x2max = 0.02
level = 1


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extraneous whitespace here and elsewhere.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this input is removed in the new code

src/artemis.cpp Outdated
@@ -138,6 +146,25 @@ Packages_t ProcessPackages(std::unique_ptr<ParameterInput> &pin) {
parthenon::MetadataFlag MetadataOperatorSplit =
parthenon::Metadata::AddUserFlag("OperatorSplit");

if (do_coagulation) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that coagulation need not use the "anonymous" operator split framework. Even coupling with jaybenne has moved away from this design. I'd mimic the handling of IMC for dust coagulation... e.g.,

if (do_coagulation) status = Dust::OperatorSplitDust<GEOM>(pmesh, tm.time, tm.dt);
if (status != TaskListStatus::complete) return status;

maybe we should completely remove the OperatorSplitTasks machinery?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done as you suggested.

src/artemis.hpp Outdated
} // namespace dust
#undef ARTEMIS_VARIABLE

// TaskCollection function pointer for operator split tasks
using TaskCollectionFnPtr = TaskCollection (*)(Mesh *pm, const Real time, const Real dt);
using TaskCollectionFnPtr = TaskCollection (*)(Mesh *pm, parthenon::SimTime &tm,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break coupling to jaybenne, but I am happy to make the change. If we are passing the whole SimTime object, however, should we still pass dt? Maybe we would want to pass a different dt than tm.dt for something like sub-cycling...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need SimTime object. It would be better to keep both.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdmullen Can subcycling not always be done inside the enrolled task collection? It seems to me to make sense to always provide the SimTime argument here, but maybe I'm missing something.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that anything that returns a TaskCollection lives inside the driver class. You then have access to everything in the driver class like SimTime.

Comment on lines 115 to 120
// Execute operator split physics
for (auto &fn : OperatorSplitTasks) {
status = fn(pmesh, tm, integrator->dt).Execute();
if (status != TaskListStatus::complete) return status;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like @adamdempsey90 had same thought as my above comment.

src/dust/dust.cpp Outdated Show resolved Hide resolved
src/dust/dust.cpp Outdated Show resolved Hide resolved
src/dust/dust.cpp Show resolved Hide resolved
src/dust/dust.cpp Outdated Show resolved Hide resolved
const int nspecies = coag.nm;
std::vector<std::string> dust_var_names;
for (int n = 0; n < nspecies; n++) {
dust_var_names.push_back(dust::prim::density::name() + '_' + std::to_string(n));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really have to do this? I'd like to look at how to clean this up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have simple way to do it, please let me know

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need the names like this? I can't think of a reason why.


// for density (g/cc), Stokes number = sqrt(Pi/8)*rho_p*s_p*Omega_k/rho_g/Cs
const Real pres = vmesh(b, gas::prim::pressure(0), k, j, i);
const Real cs = std::sqrt(gamma * pres / dens_g);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever you need cs, you should get it from the eos via the bulk modulus, e.g., BulkModulusFromDensityInternalEnergy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done as you suggested

const Real omega1 = Omega_k / time0;
const int nm = nspecies;

ScratchPad1D<Real> rhod(mbr.team_scratch(scr_level), nspecies);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should think a bit more about how to store this information. I could see this being okay for when you have > 100 dust species, but maybe not being very performant for < 20 species. Maybe in those smaller cases, you'd want a 2D scratchpad that is (nspecies,nx1) large.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For coagulation run, nspecies is usually larger than 100.

CoagParams cpars;
const int nm = pin->GetOrAddInteger("dust", "nspecies", 1);
cpars.nm = nm;
cpars.vfrag = pin->GetOrAddReal("dust", "vfrag", 1.e3); // cm/s
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that #24 is merged, "unit"-ed quantities like here should be updated to (1) have a specified unit system for input parameters, e.g. cm./s as here (2) converted to code units at the first opportunity, so for example this line should be

cpars.vfrag = pin->GetOrAddReal("dust", "vfrag", 1.e3) * units.GetSpeedPhysicalToCode; // cm/s

where for Initialize functions like this units and constants must be added to the function argument (e.g. if (do_gas) packages.Add(Gas::Initialize(pin.get(), units, constants));), whereas for tasks you can pull the units object out of the artemis package's params.

Comment on lines +45 to +47
const Real GRAV_CONST = 6.674299999999999e-8; // gravitational const in cm^3 g^-1 s^-2
const Real mstar = pin->GetOrAddReal("problem", "mstar", 1.0) * M_SUN;
cpars.gm = std::sqrt(GRAV_CONST * mstar);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const Real GRAV_CONST = 6.674299999999999e-8; // gravitational const in cm^3 g^-1 s^-2
const Real mstar = pin->GetOrAddReal("problem", "mstar", 1.0) * M_SUN;
cpars.gm = std::sqrt(GRAV_CONST * mstar);
const Real mstar = pin->GetOrAddReal("problem", "mstar", 1.0) * constants.GetMsolarCode();
cpars.gm = std::sqrt(constants.GetGCode() * mstar);

hardcoded constants need to be replaced with centralized constants from the Constants class introduced in #24

//! \fn StateDescriptor Coagulalation::Initialize
//! \brief Adds intialization function for coagulation package
std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin, Params &dustPars) {
auto coag = std::make_shared<StateDescriptor>("coagulation");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me that this just belongs in the dust package. Thoughts @pdmullen @adamdempsey90?

src/dust/dust.cpp Show resolved Hide resolved
@@ -0,0 +1,91 @@
# ========================================================================================
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pure drag input problem and so is out of scope for this PR unless I'm misunderstanding, so this input file and pgen/dust_collision.hpp should be removed.

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 23, 2024 via email

@shengtai
Copy link
Collaborator Author

shengtai commented Dec 23, 2024 via email

Comment on lines +659 to +669
TaskListStatus OperatorSplitDust(Mesh *pm, parthenon::SimTime &tm) {
auto &dust_pkg = pm->packages.Get("dust");
typedef Coordinates C;
const C coords = dust_pkg->template Param<Coordinates>("coords");

if (coords == C::cartesian) {
return OperatorSplitDustSelect<C::cartesian>(pm, tm).Execute();
} else if (coords == C::spherical1D) {
return OperatorSplitDustSelect<C::spherical1D>(pm, tm).Execute();
} else if (coords == C::spherical2D) {
return OperatorSplitDustSelect<C::spherical2D>(pm, tm).Execute();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OperatorSplitDust is the function that I'm suggesting be put into the driver class. You then have access to SimTime and other things. You can also template it on the coords, so you don't need OperatorSplitDustSelect at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants