Skip to content

new Setup class base for better encapsulation - #420

Open
glesur wants to merge 14 commits into
developfrom
newSetupClass
Open

glesur wants to merge 14 commits into
developfrom
newSetupClass

Conversation

@glesur

@glesur glesur commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

This PR introduces a new Setup Class system to encapsulate user-defined functions (boundary conditions, source terms, etc.) in a clean, object-oriented way. It replaces raw function pointers with std::function and lambdas for better flexibility and maintainability.

Core Changes: Setup Class System

  1. Motivation
  • Replace global functions and raw function pointers with a user-defined Setup class.
  • Improve encapsulation and eliminate global state.
  • Support both member functions (for OOP-style setups) and free functions (for backward compatibility).
  1. Implementation
    a. Function Type Definitions
  • Updated function signatures to use std::function (e.g., in src/fluid/boundary/boundary.hpp):
// OLD:
template<typename Phys>
using UserDefBoundaryFunc = void (*) (Fluid<Phys> *, int, BoundarySide, const real);

// NEW:
template<typename Phys>
using UserDefBoundaryFunc = std::function<void(Fluid<Phys> *, int, BoundarySide, const real)>;

b. Setup Base Class and Factory

  • Introduced SetupBase (src/setup.hpp) as the base class for user-defined setups:
class SetupBase {
public:
    SetupBase(Input &input, Grid &grid, DataBlock &data, Output &output)
        : myInput(input), myGrid(grid), myData(data), myOutput(output) {}

    virtual ~SetupBase() = default;
    virtual void InitFlow(DataBlock &data) = 0;

protected:
    Input &myInput;
    Grid &myGrid;
    DataBlock &myData;
    Output &myOutput;
};
  • Add a SetupRegistry (src/setup_registry.hpp) for dynamic setup registration which replaces weak attributes:
class SetupRegistry {
public:
    using SetupFactory = std::function<std::unique_ptr<SetupBase>(Input&, Grid&, DataBlock&, Output&)>;
    static void Register(SetupFactory factory);  // Register user's setup
    static std::unique_ptr<SetupBase> Create(Input&, Grid&, DataBlock&, Output&);  // Create setup
};
  • Added a REGISTER_SETUP macro for one-line setup registration in user-defined setup source code.

c. Updated main.cpp

  • Replaced the old CreateSetup call with SetupRegistry::Create:
auto mysetup = SetupRegistry::Create(input, grid, data, output);

d. User-Defined Setup Example
Users now define their setup class and register it using REGISTER_SETUP (e.g., test/HD/MachReflection_newsetup/setup.cpp):

#include "setup.hpp"
#include "setup_registry.hpp"

class MachReflectionSetup : public SetupBase {
public:
    using SetupBase::SetupBase;  // Inherit constructor

    // Member function for boundary conditions
    void UserdefBoundary(Fluid<DefaultPhysics>* hydro, int dir, BoundarySide side, const real t) {
        // ... implementation (moved from global function)
    }

    // Constructor - enroll member functions using lambdas
    MachReflectionSetup(Input &input, Grid &grid, DataBlock &data, Output &output)
        : SetupBase(input, grid, data, output) {

        // Enroll boundary function
        data.hydro->EnrollUserDefBoundary(
            [this](Fluid<DefaultPhysics>* hydro, int dir, BoundarySide side, const real t) {
                this->UserdefBoundary(hydro, dir, side, t);
            }
        );
    }

    // InitFlow as member function
    void InitFlow(DataBlock &data) override {
        DataBlockHost d(data);
        real alpha = 1.0/3.0*M_PI;
        // ... implementation (moved from global InitFlow)
        d.SyncToDevice();
    }
};

// Register the setup
REGISTER_SETUP(MachReflectionSetup);

Consequential Refactoring: EOS and Drag

The new setup system required device-compatible refactoring of the Equation of State (EOS) and Drag Class to ensure compatibility with GPU execution.

  1. Equation of State (EOS) Refactoring
  • Split EOS classes into host-only and device-compatible versions:
  • Introduced EquationOfStateDevice for device-compatible operations.
  • Derived EquationOfState from EquationOfStateDevice for host-only operations (e.g., ShowConfig).
  • Updated Riemann solvers and fluid modules to use EquationOfStateDevice:
// OLD:
EquationOfState eos = *(hydro->eos.get());

// NEW:
EquationOfStateDevice eos = *(hydro->eos.get());
  1. Drag Class Refactoring
  • Moved user-defined drag enrollment from GammaDrag to the Drag class.
  • Updated Drag to use std::function for user-defined drag functions.
  • Ensured device compatibility by using EquationOfStateDevice in GammaDrag.

Pros
✅ Clean OOP design with proper encapsulation.
✅ Flexible - supports both member functions and free functions (backward compatible).
✅ No more global variables/state.
✅ Improved maintainability - user-defined functions are logically grouped in a single class.
✅ Device compatibility - EOS and Drag refactoring ensures compatibility with GPU execution.
✅ Simplified setup registration - REGISTER_SETUP macro makes it easy to define and register user setups.
Cons
❌ Enrollment becomes more verbose due to lambda usage.
❌ Requires modifications to all tests to adapt to the new implementation.
❌ Slight overhead due to runtime polymorphism (negligible in most cases).
❌ Learning curve for users transitioning from the old approach.
❌ EOS and Drag refactoring introduces complexity for developers maintaining the codebase.

@glesur glesur added enhancement New feature or request experiment labels Oct 28, 2026
@glesur
glesur requested a review from svalat October 28, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request experiment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant