141 lines
5.6 KiB
C++
141 lines
5.6 KiB
C++
module;
|
|
|
|
#include <optional>
|
|
#include <span>
|
|
#include <vector>
|
|
|
|
#include <mfem/linalg/densemat.hpp>
|
|
|
|
export module mean_field:deformation.spherical_harmonic_surface;
|
|
|
|
export import :deformation.nodal_radial_surface;
|
|
|
|
export namespace mean_field::deformation {
|
|
struct SphericalHarmonicSurfaceOptions final {
|
|
int maximumDegree{4};
|
|
// A cutoff retains both real sine/cosine partners. Zero restricts the
|
|
// shape to axisymmetry; an omitted cutoff retains every order.
|
|
std::optional<int> maximumAzimuthalOrder{};
|
|
|
|
void validate() const;
|
|
};
|
|
|
|
struct SphericalHarmonicMode final {
|
|
int degree;
|
|
int order;
|
|
|
|
constexpr bool operator==(const SphericalHarmonicMode &) const = default;
|
|
};
|
|
|
|
class PreparedSphericalHarmonicSurface;
|
|
|
|
class SphericalHarmonicSurface final {
|
|
public:
|
|
using PreparedType = PreparedSphericalHarmonicSurface;
|
|
|
|
explicit SphericalHarmonicSurface(SphericalHarmonicSurfaceOptions options = {});
|
|
explicit SphericalHarmonicSurface(
|
|
mfem::Vector referenceCenter,
|
|
SphericalHarmonicSurfaceOptions options = {}
|
|
);
|
|
|
|
[[nodiscard]] const mfem::Vector &referenceCenter() const noexcept;
|
|
[[nodiscard]] const SphericalHarmonicSurfaceOptions &options() const noexcept;
|
|
[[nodiscard]] int modeCount() const noexcept;
|
|
[[nodiscard]] SurfaceDeformationDescriptor descriptor() const noexcept;
|
|
void validate() const;
|
|
|
|
private:
|
|
mfem::Vector m_referenceCenter;
|
|
SphericalHarmonicSurfaceOptions m_options;
|
|
};
|
|
|
|
// Coefficients have units of radial length. The fixed reference functions
|
|
// satisfy integral(Y_lm^2 dOmega)=1, with Condon--Shortley phase, negative
|
|
// orders denoting sine and positive orders cosine. FE interpolation of
|
|
// their nodal samples need not retain continuous spherical orthogonality.
|
|
class PreparedSphericalHarmonicSurface final {
|
|
public:
|
|
static constexpr bool hasNodalRadialParameters = false;
|
|
// Trace entries follow dimension * canonical boundary-node index + component.
|
|
static constexpr bool hasCanonicalNodalVectorTrace = true;
|
|
|
|
[[nodiscard]] SurfaceDeformationDescriptor descriptor() const noexcept;
|
|
[[nodiscard]] int parameterCount() const noexcept;
|
|
[[nodiscard]] long long globalParameterCount() const noexcept;
|
|
[[nodiscard]] long long globalParameterOffset() const noexcept;
|
|
[[nodiscard]] int spatialDimension() const noexcept;
|
|
[[nodiscard]] int surfaceNodeCount() const noexcept;
|
|
[[nodiscard]] int surfaceDisplacementSize() const noexcept;
|
|
[[nodiscard]] long long globalSurfaceDisplacementSize() const noexcept;
|
|
[[nodiscard]] long long globalSurfaceDisplacementOffset() const noexcept;
|
|
[[nodiscard]] int surfaceDisplacementDof(
|
|
int surfaceNode,
|
|
int component
|
|
) const;
|
|
[[nodiscard]] double radialDirection(
|
|
int surfaceNode,
|
|
int component
|
|
) const;
|
|
[[nodiscard]] double referenceRadius(int surfaceNode) const;
|
|
[[nodiscard]] const mfem::Vector &referenceCenter() const noexcept;
|
|
[[nodiscard]] const field::ScalarBoundaryDofMap &surfaceDofMap() const noexcept;
|
|
[[nodiscard]] std::span<const SphericalHarmonicMode> modes() const noexcept;
|
|
[[nodiscard]] const mfem::DenseMatrix &nodalBasis() const noexcept;
|
|
|
|
void buildSurfaceDisplacement(
|
|
const mfem::Vector ¶meters,
|
|
mfem::Vector &surfaceDisplacement
|
|
) const;
|
|
void applyJacobian(
|
|
const mfem::Vector ¶meters,
|
|
const mfem::Vector ¶meterDirection,
|
|
mfem::Vector &surfaceDisplacementDirection
|
|
) const;
|
|
void applyJacobianTranspose(
|
|
const mfem::Vector ¶meters,
|
|
const mfem::Vector &surfaceDisplacementDual,
|
|
mfem::Vector ¶meterDual
|
|
) const;
|
|
void applyPullbackDerivative(
|
|
const mfem::Vector ¶meters,
|
|
const mfem::Vector ¶meterDirection,
|
|
const mfem::Vector &surfaceDisplacementDual,
|
|
mfem::Vector ¶meterDualAction
|
|
) const;
|
|
|
|
private:
|
|
friend PreparedSphericalHarmonicSurface compileSurfaceDeformationPrescription(
|
|
const SphericalHarmonicSurface &,
|
|
const SurfaceDeformationCompilationContext &
|
|
);
|
|
|
|
PreparedSphericalHarmonicSurface(
|
|
PreparedNodalRadialSurface radialSurface,
|
|
std::vector<SphericalHarmonicMode> modes,
|
|
mfem::DenseMatrix nodalBasis
|
|
);
|
|
void requireParameters(const mfem::Vector ¶meters) const;
|
|
void requireSurfaceSize(const mfem::Vector &surfaceDisplacement) const;
|
|
void applyEmbedding(
|
|
const mfem::Vector ¶meters,
|
|
mfem::Vector &surfaceDisplacement
|
|
) const;
|
|
|
|
PreparedNodalRadialSurface m_radialSurface;
|
|
std::vector<SphericalHarmonicMode> m_modes;
|
|
mfem::DenseMatrix m_nodalBasis;
|
|
};
|
|
|
|
[[nodiscard]] PreparedSphericalHarmonicSurface compileSurfaceDeformationPrescription(
|
|
const SphericalHarmonicSurface &prescription,
|
|
const SurfaceDeformationCompilationContext &context
|
|
);
|
|
|
|
static_assert(SurfaceDeformationPrescription<SphericalHarmonicSurface>);
|
|
static_assert(PreparedSurfaceDeformationPrescription<PreparedSphericalHarmonicSurface>);
|
|
static_assert(SurfaceDeformationCompilable<
|
|
SphericalHarmonicSurface,
|
|
SurfaceDeformationCompilationContext>);
|
|
} // namespace mean_field::deformation
|