module; #include #include #include #include #include #include export module mean_field:operators.prepared_gravity_source; export import :fem; export import :field.mfem; export import :mapping.domain_mapper; export namespace mean_field::operators { enum class GravitySourcePreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic }; struct GravitySourcePreparationRejection final { GravitySourcePreparationRejectionReason reason{GravitySourcePreparationRejectionReason::invalid_mapping}; mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid}; }; using GravitySourcePreparationResult = std::expected; [[noreturn]] inline void throwGravitySourcePreparationRejection(const GravitySourcePreparationRejection &rejection) { if (rejection.reason == GravitySourcePreparationRejectionReason::non_finite_arithmetic) { throw std::domain_error("Prepared gravity-source data contained non-finite arithmetic."); } throw std::domain_error("Prepared gravity-source data could not map the candidate geometry."); } class PreparedMappedGravitySourceOperator final : public mfem::Operator { public: PreparedMappedGravitySourceOperator( const fem::FEM &f, const mapping::DomainMapper &domain_mapper ); void Prepare(const mfem::Vector &displacement); void PreparePrimal(const mfem::Vector &displacement); [[nodiscard]] GravitySourcePreparationResult TryPrepare(const mfem::Vector &displacement); [[nodiscard]] GravitySourcePreparationResult TryPreparePrimal(const mfem::Vector &displacement); void Mult( const mfem::Vector &density, mfem::Vector &action ) const override; void MultDisplacementVariationTrue( const mfem::Vector &densityTrue, const mfem::Vector &displacementVariationTrue, mfem::Vector &actionVariationTrue ) const; [[nodiscard]] bool IsPrepared() const noexcept; [[nodiscard]] bool HasVariationData() const noexcept; [[nodiscard]] std::uint64_t GetPreparationCount() const noexcept; [[nodiscard]] const field::FieldDofMap &GetDensityMap() const noexcept; [[nodiscard]] const field::FieldDofMap &GetPotentialMap() const noexcept; [[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept; void MultTranspose( const mfem::Vector &potential, mfem::Vector &action ) const override; private: enum class PreparationMode : std::uint8_t { primal, linearization }; struct ElementPAData { int element_id{-1}; mfem::Array density_dofs; mfem::Array potential_dofs; mfem::Array displacement_dofs; mfem::DofTransformation *density_dof_transformation{nullptr}; mfem::DofTransformation *potential_dof_transformation{nullptr}; mfem::DofTransformation *displacement_dof_transformation{nullptr}; const mfem::IntegrationRule *integration_rule{nullptr}; // Rows are quadrature points; columns are element DOFs. mfem::DenseMatrix density_basis; mfem::DenseMatrix potential_basis; mfem::DenseMatrix inverse_element_jacobians; // Contains quadrature weight, mesh Jacobian, mapped Jacobian, // and 4*pi*G. mfem::Vector quadrature_data; }; [[nodiscard]] GravitySourcePreparationResult TryPrepareImpl( const mfem::Vector &displacement, PreparationMode mode ); const fem::FEM &m_fem; const mapping::DomainMapper &m_domain_mapper; field::FieldDofMap m_density_map; field::FieldDofMap m_potential_map; field::FieldDofMap m_displacement_map; mfem::Array m_stellar_marker; std::vector m_elements; mutable mfem::Vector m_density_true; mutable mfem::Vector m_potential_true; mutable mfem::Vector m_action_true; mutable mfem::Vector m_potential_local; mutable mfem::Vector m_local_action; mutable mfem::Vector m_element_input; mutable mfem::Vector m_quadrature_action; mutable mfem::Vector m_element_action; mutable mfem::Vector m_density_local; mutable mfem::Vector m_displacement_variation_local; mutable mfem::Vector m_local_variation_action; mutable mfem::Vector m_element_density; mutable mfem::Vector m_element_displacement_variation; mutable mfem::Vector m_quadrature_variation_action; mutable mfem::Vector m_element_variation_action; mutable mfem::DenseMatrix m_reference_displacement_dshape; mutable mfem::DenseMatrix m_reference_displacement_jacobian; mfem::Vector m_displacement_true; std::uint64_t m_preparation_count{0}; bool m_is_prepared{false}; bool m_has_variation_data{false}; }; } // namespace mean_field::operators