feat(equations): displacement_force

added equation that sums pressure, gravity, and rotation together to get the displacement force. Note that some of the dependencies of this have not been commited yet as they lack documentation
This commit is contained in:
2026-10-08 11:59:57 -04:00
parent 0eef623130
commit 4336a93364

View File

@@ -0,0 +1,88 @@
#pragma once
/**
* @file displacement_force.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the DisplacementForce class, which represents the mechanical balance equation in SERiF.
*
*/
#include <string_view>
#include <utility>
#include "serif/equations/arithmetic.hpp"
#include "serif/equations/gravity_force.hpp"
#include "serif/equations/pressure_force.hpp"
#include "serif/equations/rotational_force.hpp"
namespace serif::equations {
/**
* @class DisplacementForce
* @tparam EOST The equation of state type, this must satisfy the PressureForceEOS concept. The requires section below lays out
* what the PressureForceEOS concept requires.
*
* @requires The equation of state type must publish a valid Relation catalog
* @requires The equation of state type must implement all relations required by the catalog it publishes
* @requires The equation of state type must support the relation pressure from specific enthalpy
* @requires The equation of state type must support the partial derivative pressure from specific enthalpy with respect to specific enthalpy
*
* This class represents the mechanical balance equation in SERiF. It is a sum of the pressure force, gravity force, and rotational force equations.
*
* As I have said in a number of other locations this is an important file / class to understand. You might note that this file
* is where we actually build the momentum equation (though in the case of a polytrope it looks a lot more like a
* mechanical balance equation). You may note though how little code there actually is here. That is because we have
* split up the separated physics into the gravity_force, the pressure_force, and the rotational_force equations. Then
* we use the arithmetic equation routines sum their contributions together. Further, this is where we actually define
* the rotational axis of the star (note how we set it along the z-axis) and the center of rotation.
*
* Generally this equation should be used as a model for how to implement other multi-term equations.
* We want to avoid monolithic equations. There are a few reasons for this, one would be maintainability. This software is,
* by requirement, exceedingly complex, the more we can break things up into semantically meaningful pieces
* the easier it will be for a developer to hold parts of the code in their head. However, more than just maintainability there
* is a performance reason for this (though one that we admittedly do not exploit at the moment). The backend of
* SERiF makes heavy use of a computational graph with aggressive inter-node caching. If we split equations up
* into smaller pieces and then represent their sums as operations on this graph the backend can more aggressively
* avoid recomputing certain parts which may, provably, have not changes from one evaluation to the next. Currently,
* we do not do this; however, this is future optimization will not require modifying this code at all only the
* equation sum backend.
*
* @note The DisplacementForce equation owns all three contributing equations
*/
template <eos::models::PressureForceEOS EOST>
class DisplacementForce final {
public:
using Test = discretization::blocks::displacement::vector; ///< The test type is the model displacement vector, which is the quantity being constrained by the mechanical balance equation. Effectively here we say that all these forces control what the geometry of the surface is (and then other equations connect that geometry to the mass distribution)
static constexpr std::string_view name = "displacement force"; ///< Compile time name for the mechanical balance equation, used for debugging and logging.
/// Pressure carries its EOS; rotation prescribes an axis and reads angular speed from the state.
/**
* @brief Construct a mechanical balance equation.
*
* @param pressure The pressure force equation, which must be constructed with the same EOS type as the DisplacementForce (note generally this can be inferred).
* @param axis The axis of rotation for the rotational force equation. Defaults to the z-axis.
* @param center The center of rotation for the rotational force equation. Defaults to the origin.
*/
explicit DisplacementForce(
PressureForce<EOST> pressure,
RigidRotation::Vector axis = {0.0, 0.0, 1.0},
RigidRotation::Vector center = {}
) :
m_equation(std::move(pressure), GravityForce{}, RotationalForce{axis, center}) {}
/**
* @brief Return the contributions of the mechanical balance equation.
*
* @return A tuple containing the contributions of the mechanical balance equation.
*/
[[nodiscard]] const auto& contributions() const noexcept {
return m_equation.contributions();
}
private:
EquationSum<PressureForce<EOST>, GravityForce, RotationalForce> m_equation; ///< The mechanical balance residual is a sum of residuals from the pressure force, gravity force, and rotational force equations.
};
} // namespace serif::equations