feat(newton): first newton solver implementation

This commit is contained in:
2026-09-08 06:36:39 -04:00
parent 76818f2f82
commit b3c04d507a
98 changed files with 20397 additions and 11040 deletions

View File

@@ -6,130 +6,124 @@ module;
#include <type_traits>
#include <utility>
#include <mpi.h>
export module mean_field:equilibrium.stellar_discretization;
export import :fem;
export import :mapping.domain_mapper;
export import :normalization.physical_riesz;
namespace mean_field::equilibrium::detail {
struct StellarEquilibriumProblemFactory;
}
export namespace mean_field::equilibrium {
/*
* An explicit, non-owning view of the numerical discretization used by a
* stellar equilibrium problem. The referenced FEM and mapper must outlive
* every problem and structure that uses this view.
*
* Ownership cannot move here yet because FEM currently also contains
* mutable field workspaces. Separating those workspaces is a prerequisite
* for shared discretization ownership by solved Structure objects.
* The complete numerical discretization used by a stellar equilibrium
* problem. Moving the FEM into stable heap storage lets the problem and a
* completed Structure transfer unique ownership without invalidating the
* references retained by prepared operators. The mapper is part of that
* owned FEM and therefore has the same lifetime.
*/
template <normalization::NormalizationPrescription Normalization>
class StellarDiscretizationFor final {
template <normalization::NormalizationPrescription Normalization> class StellarDiscretizationFor final {
public:
using NormalizationPrescriptionType = std::remove_cvref_t<Normalization>;
explicit StellarDiscretizationFor(fem::FEM &finiteElementModel)
requires std::same_as<NormalizationPrescriptionType, normalization::Unnormalized>
explicit StellarDiscretizationFor(fem::FEM &&finiteElementModel)
requires std::same_as<
NormalizationPrescriptionType,
normalization::Unnormalized>
: StellarDiscretizationFor(
finiteElementModel,
RequireDomainMapper(finiteElementModel),
std::move(finiteElementModel),
normalization::Unnormalized{}
) {
}
StellarDiscretizationFor(
fem::FEM &finiteElementModel,
const mapping::DomainMapper &domainMapper
)
requires std::same_as<NormalizationPrescriptionType, normalization::Unnormalized>
: StellarDiscretizationFor(
finiteElementModel,
domainMapper,
normalization::Unnormalized{}
) {
}
explicit StellarDiscretizationFor(fem::FEM &)
requires std::same_as<
NormalizationPrescriptionType,
normalization::Unnormalized>
= delete;
StellarDiscretizationFor(
fem::FEM &,
mapping::DomainMapper &&
) requires std::same_as<NormalizationPrescriptionType, normalization::Unnormalized> = delete;
StellarDiscretizationFor(
fem::FEM &,
const mapping::DomainMapper &&
) requires std::same_as<NormalizationPrescriptionType, normalization::Unnormalized> = delete;
StellarDiscretizationFor(
fem::FEM &finiteElementModel,
fem::FEM &&finiteElementModel,
NormalizationPrescriptionType normalizationPrescription
)
: StellarDiscretizationFor(
finiteElementModel,
RequireDomainMapper(finiteElementModel),
std::move(normalizationPrescription)
) {
}
StellarDiscretizationFor(
fem::FEM &finiteElementModel,
const mapping::DomainMapper &domainMapper,
NormalizationPrescriptionType normalizationPrescription
)
: m_finiteElementModel(std::addressof(finiteElementModel)),
m_domainMapper(std::addressof(domainMapper)),
: m_finiteElementModel(TakeOwnership(std::move(finiteElementModel))),
m_normalizationPrescription(std::move(normalizationPrescription)) {
if (!finiteElementModel.okay()) {
throw std::invalid_argument("A stellar discretization requires a complete finite-element model.");
}
}
StellarDiscretizationFor(
fem::FEM &,
mapping::DomainMapper &&,
NormalizationPrescriptionType
) = delete;
) = delete;
StellarDiscretizationFor(
fem::FEM &,
const mapping::DomainMapper &&,
NormalizationPrescriptionType
) = delete;
StellarDiscretizationFor(const StellarDiscretizationFor &) = delete;
StellarDiscretizationFor &operator=(const StellarDiscretizationFor &) = delete;
StellarDiscretizationFor(StellarDiscretizationFor &&) = default;
StellarDiscretizationFor &operator=(StellarDiscretizationFor &&) = delete;
[[nodiscard]] fem::FEM &finiteElementModel() const noexcept {
return *m_finiteElementModel;
}
[[nodiscard]] const mapping::DomainMapper &domainMapper() const noexcept {
return *m_domainMapper;
}
[[nodiscard]] const NormalizationPrescriptionType &normalizationPrescription() const noexcept {
return m_normalizationPrescription;
}
[[nodiscard]] bool isCurrent() const noexcept {
return m_finiteElementModel != nullptr && m_domainMapper != nullptr && m_finiteElementModel->okay();
}
private:
[[nodiscard]] static const mapping::DomainMapper &RequireDomainMapper(const fem::FEM &finiteElementModel) {
[[nodiscard]] const mapping::DomainMapper &domainMapper() const & {
const auto &finiteElementModel = RequireFiniteElementModel();
if (finiteElementModel.domainMapperStateless == nullptr) {
throw std::invalid_argument("A stellar discretization requires a domain mapper.");
throw std::logic_error("The stellar discretization has no domain mapper.");
}
return *finiteElementModel.domainMapperStateless;
}
fem::FEM *m_finiteElementModel;
const mapping::DomainMapper *m_domainMapper;
[[nodiscard]] const mapping::DomainMapper &domainMapper() const && = delete;
[[nodiscard]] MPI_Comm communicator() const & {
const auto &finiteElementModel = RequireFiniteElementModel();
if (finiteElementModel.mesh == nullptr) {
throw std::logic_error("The stellar discretization has no parallel mesh.");
}
return finiteElementModel.mesh->GetComm();
}
[[nodiscard]] MPI_Comm communicator() const && = delete;
[[nodiscard]] const NormalizationPrescriptionType &normalizationPrescription() const & noexcept {
return m_normalizationPrescription;
}
[[nodiscard]] const NormalizationPrescriptionType &normalizationPrescription() const && = delete;
[[nodiscard]] bool isCurrent() const noexcept {
return m_finiteElementModel != nullptr && m_finiteElementModel->okay();
}
private:
friend struct detail::StellarEquilibriumProblemFactory;
[[nodiscard]] fem::FEM &MutableFiniteElementModelForAssembly() & {
return const_cast<fem::FEM &>(RequireFiniteElementModel());
}
[[nodiscard]] const fem::FEM &RequireFiniteElementModel() const {
if (m_finiteElementModel == nullptr) {
throw std::logic_error("A moved-from stellar discretization has no finite-element model.");
}
return *m_finiteElementModel;
}
[[nodiscard]] static std::unique_ptr<fem::FEM> TakeOwnership(fem::FEM &&finiteElementModel) {
if (!finiteElementModel.okay()) {
throw std::invalid_argument("A stellar discretization requires a complete finite-element model.");
}
return std::make_unique<fem::FEM>(std::move(finiteElementModel));
}
std::unique_ptr<fem::FEM> m_finiteElementModel;
NormalizationPrescriptionType m_normalizationPrescription;
};
template <normalization::NormalizationPrescription Normalization>
StellarDiscretizationFor(fem::FEM &, Normalization)
-> StellarDiscretizationFor<std::remove_cvref_t<Normalization>>;
template <normalization::NormalizationPrescription Normalization>
StellarDiscretizationFor(fem::FEM &, const mapping::DomainMapper &, Normalization)
-> StellarDiscretizationFor<std::remove_cvref_t<Normalization>>;
StellarDiscretizationFor(
fem::FEM &&,
Normalization
) -> StellarDiscretizationFor<std::remove_cvref_t<Normalization>>;
using StellarDiscretization = StellarDiscretizationFor<normalization::Unnormalized>;
@@ -143,41 +137,17 @@ export namespace mean_field::equilibrium {
template <normalization::NormalizationPrescription Normalization>
[[nodiscard]] auto makeStellarDiscretization(
fem::FEM &finiteElementModel,
fem::FEM &&finiteElementModel,
Normalization normalizationPrescription
) {
return StellarDiscretizationFor<std::remove_cvref_t<Normalization>>{
finiteElementModel,
std::move(normalizationPrescription)
std::move(finiteElementModel), std::move(normalizationPrescription)
};
}
template <normalization::NormalizationPrescription Normalization>
[[nodiscard]] auto makeStellarDiscretization(
fem::FEM &finiteElementModel,
const mapping::DomainMapper &domainMapper,
Normalization normalizationPrescription
) {
return StellarDiscretizationFor<std::remove_cvref_t<Normalization>>{
finiteElementModel,
domainMapper,
std::move(normalizationPrescription)
};
}
template <normalization::NormalizationPrescription Normalization>
StellarDiscretizationFor<std::remove_cvref_t<Normalization>>
makeStellarDiscretization(
StellarDiscretizationFor<std::remove_cvref_t<Normalization>> makeStellarDiscretization(
fem::FEM &,
mapping::DomainMapper &&,
Normalization
) = delete;
template <normalization::NormalizationPrescription Normalization>
StellarDiscretizationFor<std::remove_cvref_t<Normalization>>
makeStellarDiscretization(
fem::FEM &,
const mapping::DomainMapper &&,
Normalization
) = delete;
} // namespace mean_field::equilibrium