module; #include #include #include #include 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 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 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 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 m_modes; mfem::DenseMatrix m_nodalBasis; }; [[nodiscard]] PreparedSphericalHarmonicSurface compileSurfaceDeformationPrescription( const SphericalHarmonicSurface &prescription, const SurfaceDeformationCompilationContext &context ); static_assert(SurfaceDeformationPrescription); static_assert(PreparedSurfaceDeformationPrescription); static_assert(SurfaceDeformationCompilable< SphericalHarmonicSurface, SurfaceDeformationCompilationContext>); } // namespace mean_field::deformation