Skip to content

[newchem-cpp] Improve API-Test Harness (2/2): grtest::FieldContainer#500

Open
mabruzzo wants to merge 31 commits intograckle-project:newchem-cppfrom
mabruzzo:ncc/add-FieldContainer
Open

[newchem-cpp] Improve API-Test Harness (2/2): grtest::FieldContainer#500
mabruzzo wants to merge 31 commits intograckle-project:newchem-cppfrom
mabruzzo:ncc/add-FieldContainer

Conversation

@mabruzzo
Copy link
Collaborator

@mabruzzo mabruzzo commented Feb 5, 2026

To be reviewed after #499 is merged


This PR introduces the grtest::FieldContainer type and basic machinery for initializing the values.

Description: grtest::FieldContainer

This is basically a glorified wrapper around grackle_field_data and the underlying field allocations. The main goals were to:

  • provide a C++ class that properly manages resource management of this data
  • provide an interface that can be used to iterate over the various field values, provide random access to the field values, and clone the container (i.e. make a deepcopy)

There are obvious parallels to gracklepy's FluidContainer class

A fair amount of design decisions were influenced by my desire to write benchmarks (in a subsequent PR).

  • Essentially, I tried to design the code in a way where it would be easy to adapt it to work with older Grackle versions (i.e. as a consequence, I tried to stick to only using public API functions)
  • As a consequence, the constructor for FieldContainer is probably a little slow. This won't be a problem for benchmarks since the FieldContainer::copy_to is designed to be a fast memcpy. The very end of this PR includes a snippet of what a benchmark might look like

Description: grtest::fill_field_values

This is the basic function that is intended to initialize the values of a FluidContainer. The basic idea is that an initial-condition "tile" is specified and this function fills a FluidContainer by repeating this tile.

At the moment, machinery is in place to construct highly simplistic initial-conditions. Over time, we'll probably add alternative choices to test Grackle in various regimes (and to eventually build benchmarks of physically meaningful scenarios).

  • Construction of initial condition "tiles" would ideally support a variety of Grackle Configurations
  • If we are inclined, it would be straight-forward to make a "tile" that reads data from an external file (maybe json, toml or hdf5), which could be quite useful for debugging

Summary

All of these changes make it possible to write tests of the Grackle API a lot more concisely. Things are still fairly clunky, but I think it's worth wait to refactor until I have written some tests using this API (I have a handful of half-finished PRs).

This PR talks quite a bit about benchmarking. At this point, it will be quite straight-forward to construct a few basic benchmarks. For some context, if we used a tool like Google Benchmark, then a benchmark of local_solve_chemistry might look something like the snippet in the collapsible section

Sample Benchmarking Snippet

In practice, the benchmarking code would probably be a little more sophisticated.

  • For example, Google Benchmark makes it possible to parameterize the benchmark. This could be useful for parameterizing the number of cells in the calculation or possibly controlling some aspect of the chemical configuration (.
  • We might factor out some of the setup logic. This would make it easier (if only to make it possible for the benchmarking library to run the benchmarks )
#include <benchmark/benchmark.h>
#include "grackle.h"
#include "grtestutils/GrackleCtxPack.hpp"
#include "grtestutils/field_container.hpp"
#include "grtestutils/fill_field_vals.hpp"

static void BM_SimpleSolveChem(benchmark::State& state) {
  // set up Grackle config
  grtest::GrackleCtxPack ctx_pack = /* ... */;
  // set up the primary fluid container, involves FieldContainer::create()
  grtest::FieldContainer fc = /* ... */;
  
  // set the code units used during the calculation...
  code_units my_units = /* ... */;
  
  // modify fc so it holds appropriate initial field values
  grtest::Status s = grtest::fill_field_vals(fc, /* ... */);
  // abort if s.is_err() is true
  
  // make a pristine immutable clone of the initial field values
  const fc_initial = fc.clone();
  
  // the size of the timestep
  double dt = /* ... */;

  // the following loop is actually benchmarked
  for (auto _ : state) {
    // reset the values in fc to the desired initial field values
    // (this is an extremely quick operation)
    fc_initial.copy_into(fc, /*bypass_check=*/ true);
    
    // the actual function that is profiled
    local_solve_chemistry(ctx_pack.my_chemistry(), ctx_pack.my_rates(),
                          &my_units, fc.get_ptr(), dt);
  }
}

// Register the function as a benchmark
BENCHMARK(BM_SimpleSolveChem);

BENCHMARK_MAIN();

@mabruzzo mabruzzo force-pushed the ncc/add-FieldContainer branch from d34d389 to 2fbe523 Compare February 5, 2026 04:30
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.

1 participant