AMReX-Astro / AMReX-Astro/Microphysics

templating integrator functions on NumSpec, actual_rhs

Open
#1,657 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement integrator
Dominant language
C++
Stars
43
Forks
46
Avg merge
2d 18h
Merged PRs (30d)
15

Description

There is somewhat of a design "impedance mismatch" between Quokka and Microphysics.

I think this can be solved with two straightforward API changes:

  • making actual_rhs a functor object, and
  • templating the integrator functions on:
    • the number of species/equations NumSpec
    • the type of the actual_rhs functor object

Then it should be possible to call any integrator (either BackwardEuler or VODE) with something like:
integrate<NumSpec, F>(F actual_rhs, ...) from the application code, or from the existing burner. Note that since the type of F is known at compile time, the compiler can inline the function call to actual_rhs() and there is no performance loss (it is not equivalent to a function pointer).

The functor could look like this:

struct QuokkaActualRhsFunctor {
        constexpr int num_groups = 1;
        amrex::Real my_runtime_parameter = 1.5;
	AMREX_GPU_DEVICE void operator()(amrex::GpuArray<num_groups> &rhs) const
	{
		// compute rhs here
		rhs(0) = M_PI * my_runtime_parameter;
	}
};

Calling the integrator could look like this:

QuokkaActualRhsFunctor my_actual_rhs;
my_actual_rhs.my_runtime_parameter = 42.0;
integrate<NumGroups>(my_actual_rhs, dt);

where the template parameter F is deduced by the compiler from the type of my_actual_rhs.

For existing Microphysics networks, I think this could be accomplished with code changes only trivial syntactic changes to the generic burner code (although potentially changing a significant number of lines of code). But it would be good to hear from other Microphysics developers on this point.

Background information

  • "Function Objects in the C++ Standard Library"
    • "A function object, or functor, is any type that implements operator(). This operator is referred to as the call operator or sometimes the application operator. The C++ Standard Library uses function objects primarily as sorting criteria for containers and in algorithms."
    • "Function objects provide two main advantages over a straight function call. The first is that a function object can contain state. The second is that a function object is a type and therefore can be used as a template parameter."
  • "What is a functor?"
    • "So what is the purpose of using a functor? It helps us implement a common software engineering design pattern used in coding -- the strategy pattern. The strategy pattern is the idea of passing a function into a function -- i.e. a pluggable algorithm."

cc @chongchonghe @markkrumholz @psharda @zingale

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the BackwardEuler and VODE integrator entry points, actual_rhs, and the generic burner code. Compare how NumSpec and actual_rhs are currently passed, then determine the changes needed for functor-based, templated calls and verify that existing Microphysics networks still build and run their tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend-api-design
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.