feat(mean_field): added dimensions, discritization, and start of eos

The full rewrite of mean_field into something maintainable is progressing. dimensions is mostly done, discritization (domain, blocks, and fields) is done, and eos is progressing quickly
This commit is contained in:
2026-09-15 10:42:00 -04:00
parent 7c99debf2f
commit d1f59d6d70
88 changed files with 324020 additions and 268 deletions

View File

@@ -0,0 +1,101 @@
#pragma once
#include <optional>
#include "serif/discretization/domain/concepts.hpp"
#include "serif/discretization/domain/mesh/topology.hpp"
#include "serif/discretization/domain/relation/relations.hpp"
#include "serif/discretization/domain/relation/validation/runtime.hpp"
#include "serif/discretization/domain/schema/concepts.hpp"
#include "serif/discretization/domain/schema/validation/validator.hpp"
// Inscribed<InnerT, OuterT>: every face where the inner domain stops must have
// the outer domain on the far side.
namespace serif::discretization::domain::schema::validation {
using relation::Inscribed;
using relation::validation::RelationValidationResult;
using relation::validation::RelationValidationFailure;
template <IsDomainOrSet InnerT, IsDomainOrSet OuterT>
struct RelationValidator<Inscribed<InnerT, OuterT>> {
template <IsSchema SchemaT>
[[nodiscard]] static RelationValidationResult validate(const mesh::MeshTopology &topology) {
static_assert(
SchemaT::template contains_domain<InnerT>(), "The inner domain of an Inscribed relation is not present in the supplied schema. Inscribed cannot be enforced"
);
static_assert(
SchemaT::template contains_domain<OuterT>(), "The outer domain of an Inscribed relation is not present in the supplied schema. Inscribed cannot be enforced"
);
bool foundInnerElement = false;
bool foundOuterElement = false;
bool foundInnerBoundary = false;
for (int elementID = 0; elementID < topology.element_count(); ++elementID) {
const int domainID = topology.element_domain_id(elementID);
foundInnerElement = foundInnerElement || SchemaT::template domain_id_belongs_to<InnerT>(domainID);
foundOuterElement = foundOuterElement || SchemaT::template domain_id_belongs_to<OuterT>(domainID);
}
if (!foundInnerElement) {
return {.failure = RelationValidationFailure::InnerDomainAbsent};
}
if (!foundOuterElement) {
return {.failure = RelationValidationFailure::OuterDomainAbsent};
}
for (int faceID = 0; faceID < topology.face_count(); ++faceID) {
const mesh::FaceElements faceElements = topology.face_elements(faceID);
const int firstElementID = faceElements.firstElementID;
const int secondElementID = faceElements.secondElementID;
const bool firstIsInner = firstElementID >= 0 &&
SchemaT::template domain_id_belongs_to<InnerT>(topology.element_domain_id(firstElementID));
const bool secondIsInner = secondElementID >= 0 &&
SchemaT::template domain_id_belongs_to<InnerT>(topology.element_domain_id(secondElementID));
if (firstIsInner == secondIsInner) {
continue;
}
foundInnerBoundary = true;
const int innerElementID = firstIsInner ? firstElementID : secondElementID;
const int adjacentElementID = firstIsInner ? secondElementID : firstElementID;
if (adjacentElementID < 0) {
return {
.failure = RelationValidationFailure::InnerDomainTouchesMeshBoundary,
.inscribedDiagnostics = std::make_optional<RelationValidationResult::InscribedDiagnostics>({
.faceID = faceID,
.innerElementID = innerElementID,
})};
}
const int adjacentDomainID = topology.element_domain_id(adjacentElementID);
if (!SchemaT::template domain_id_belongs_to<OuterT>(adjacentDomainID)) {
return {
.failure = RelationValidationFailure::InnerDomainTouchesUnexpectedDomain,
.inscribedDiagnostics = std::make_optional<RelationValidationResult::InscribedDiagnostics>({
.faceID = faceID,
.innerElementID = innerElementID,
.adjacentElementID = adjacentElementID,
.adjacentDomainID = adjacentDomainID
})};
}
}
if (!foundInnerBoundary) {
return {.failure = RelationValidationFailure::InnerDomainHasNoBoundary};
}
return {};
}
};
}