Integrate Refactor solver sources and dual MSVC CMake builds
This commit is contained in:
@@ -283,3 +283,14 @@ TEST(Mitc4Geometry, ExposesTheCompleteRequiredValidationPointInventory) {
|
||||
EXPECT_EQ(points[13].natural_coordinates, (Vector3{-gauss, -gauss, 0.0}));
|
||||
EXPECT_EQ(points[16].natural_coordinates, (Vector3{-gauss, gauss, 0.0}));
|
||||
}
|
||||
|
||||
TEST(Mitc4Geometry, RetainsReciprocalDeterminantOverflowGateAtTinyScale) {
|
||||
const std::vector<fesa::Node> nodes{
|
||||
Node(0U, {0.0, 0.0, 0.0}), Node(1U, {2e-104, 0.0, 0.0}),
|
||||
Node(2U, {2e-104, 2e-104, 0.0}), Node(3U, {0.0, 2e-104, 0.0})};
|
||||
EXPECT_TRUE(fesa::PreprocessShellGeometry(
|
||||
nodes, {Element(10U, {0U, 1U, 2U, 3U})}, Sections(2e-99)).HasValue());
|
||||
ExpectFailureCode(fesa::PreprocessShellGeometry(
|
||||
nodes, {Element(10U, {0U, 1U, 2U, 3U})}, Sections(2e-102)),
|
||||
"invalid-shell-jacobian");
|
||||
}
|
||||
|
||||
@@ -133,3 +133,41 @@ TEST(SourceTargetResolver,
|
||||
EXPECT_EQ(result.GetStatus().Diagnostics()[1U].message,
|
||||
"Duplicate resolved source target 10.");
|
||||
}
|
||||
|
||||
TEST(SourceTargetResolver, OwnsNodeCandidateIndexBeforeDomainCommit) {
|
||||
using fesa::SourceEntityKind;
|
||||
const auto index = [] {
|
||||
const std::vector<fesa::Node> nodes{{{"Part-1", 20, "0020"}, {}, {}},
|
||||
{{"Part-1", 10, "0010"}, {}, {}},
|
||||
{{"Part-2", 10, "0010"}, {}, {}}};
|
||||
const std::vector<fesa::NodeSet> sets{
|
||||
{"Ends", "Part-1", {1U, 0U}, {}},
|
||||
{"Ends", "Part-2", {2U}, {}},
|
||||
{"Repeated", "Part-1", {0U, 1U, 0U, 1U}, {}}};
|
||||
return fesa::SourceTargetIndex::FromNodeDefinitions(nodes, sets);
|
||||
}();
|
||||
const fesa::SourceTargetResolver resolver{index};
|
||||
const auto ends =
|
||||
resolver.Resolve({SourceEntityKind::kNode, "part-1", "ENDS"});
|
||||
ASSERT_TRUE(ends.HasValue());
|
||||
EXPECT_EQ(Indices(ends.Value()), (std::vector<fesa::EntityIndex>{1U, 0U}));
|
||||
EXPECT_EQ(ends.Value()[0U].source_id.source_label_text, "0010");
|
||||
EXPECT_EQ(ends.Value()[1U].source_id.source_label_text, "0020");
|
||||
const auto direct =
|
||||
resolver.Resolve({SourceEntityKind::kNode, "Part-2", "10"});
|
||||
ASSERT_TRUE(direct.HasValue());
|
||||
EXPECT_EQ(Indices(direct.Value()), (std::vector<fesa::EntityIndex>{2U}));
|
||||
ExpectFailure(index, {SourceEntityKind::kNode, "", "Ends"},
|
||||
"ambiguous-source-target");
|
||||
const auto repeated =
|
||||
resolver.Resolve({SourceEntityKind::kNode, "Part-1", "Repeated"});
|
||||
ASSERT_FALSE(repeated.HasValue());
|
||||
ASSERT_EQ(repeated.GetStatus().Diagnostics().size(), 2U);
|
||||
EXPECT_EQ(repeated.GetStatus().Diagnostics()[0U].message,
|
||||
"Duplicate resolved source target 0020.");
|
||||
EXPECT_EQ(repeated.GetStatus().Diagnostics()[1U].message,
|
||||
"Duplicate resolved source target 0010.");
|
||||
const auto empty = fesa::SourceTargetIndex::FromNodeDefinitions({}, {});
|
||||
ExpectFailure(empty, {SourceEntityKind::kNode, "", "1"},
|
||||
"unresolved-source-target");
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "fesa/elements/thermal_shell.h"
|
||||
#include "fesa/model/domain.h"
|
||||
#include "elements/thermal_shell_geometry.h"
|
||||
|
||||
namespace {
|
||||
using fesa::Vector3;
|
||||
@@ -210,3 +211,68 @@ TEST(ThermalShellGeometry,
|
||||
{1, 1, 0}},
|
||||
{{{0, 1, 4, 3}}, {{1, 2, 5, 4}}, {{3, 4, 7, 6}}, {{4, 5, 8, 7}}})));
|
||||
}
|
||||
|
||||
namespace {
|
||||
TEST(ThermalGeometryAction, EnclosesIndependentDyadicTangentialConstraints) {
|
||||
using namespace fesa::thermal_internal;
|
||||
// The rounded Gram matrix loses rank for delta=2^-40, while the physical
|
||||
// tangents and their exterior determinant remain certified and nonsingular.
|
||||
for (const int exponent : {-40,-27,-4,0}) {
|
||||
const double delta = std::ldexp(1.,exponent);
|
||||
Geometry geometry;
|
||||
geometry.b = {1,1,0};
|
||||
geometry.c = {1,1+delta,0};
|
||||
for (std::size_t j=0; j<3; ++j) {
|
||||
geometry.bi[j] = Interval{geometry.b[j]};
|
||||
geometry.ci[j] = Interval{geometry.c[j]};
|
||||
}
|
||||
const auto evaluated = EvaluateSurface(geometry, 0, 0, Interval{0},
|
||||
Interval{0}, {}, {});
|
||||
ASSERT_TRUE(evaluated.HasValue()) << exponent;
|
||||
const double dx[4]{-.25,.25,.25,-.25};
|
||||
const double dy[4]{-.25,-.25,.25,.25};
|
||||
for (std::size_t i=0; i<4; ++i) {
|
||||
const double gy = (dy[i]-dx[i])/delta;
|
||||
const double gx = dx[i]-gy;
|
||||
const double oracle[3]{gx,gy,0};
|
||||
for (std::size_t j=0; j<3; ++j) {
|
||||
EXPECT_DOUBLE_EQ(evaluated.Value().gradient[i][j],oracle[j]);
|
||||
const auto interval = evaluated.Value().gradient_interval[i][j];
|
||||
EXPECT_LE(interval.lower,oracle[j]);
|
||||
EXPECT_GE(interval.upper,oracle[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TEST(ThermalGeometryAction, PreservesWholePatchAndScaledFiniteRejections) {
|
||||
using namespace fesa::thermal_internal;
|
||||
for (const Patch patch : {
|
||||
kSquare,
|
||||
Patch{{{3,-9,-3},{1,3,-3},{-1,3,3},{-3,3,3}}},
|
||||
Patch{{{-1,4,-4},{-1,-2,2},{3,2,4},{-1,-4,-2}}}}) {
|
||||
const auto geometry = BuildGeometry(patch, {}, {});
|
||||
ASSERT_TRUE(geometry.HasValue());
|
||||
for (const double xi : {-std::sqrt(.6),0.,std::sqrt(.6)})
|
||||
for (const double eta : {-std::sqrt(.6),0.,std::sqrt(.6)})
|
||||
EXPECT_TRUE(EvaluateSurface(geometry.Value(),xi,eta,
|
||||
Interval{Down(xi),Up(xi)},Interval{Down(eta),Up(eta)},{},{}).HasValue());
|
||||
}
|
||||
const Patch folded{{{0,0,0},{1,1,0},{1,0,0},{0,1,0}}};
|
||||
const auto rejected = BuildGeometry(folded,{"part",27,"0027"},{"mesh.inp",17});
|
||||
ASSERT_FALSE(rejected.HasValue());
|
||||
EXPECT_EQ(rejected.GetStatus().Diagnostics()[0].code,
|
||||
"uncertain-thermal-shell-geometry");
|
||||
EXPECT_EQ(rejected.GetStatus().Diagnostics()[0].entity_identity,"part:0027");
|
||||
Geometry geometry;
|
||||
geometry.b = {1,0,0}; geometry.c = {0,1,0};
|
||||
geometry.bi[0] = Interval{1}; geometry.ci[1] = Interval{1};
|
||||
geometry.length_exponent = -600;
|
||||
const auto scaled = EvaluateSurface(geometry,0,0,Interval{0},Interval{0},
|
||||
{"part",27,"0027"},{"mesh.inp",17});
|
||||
ASSERT_FALSE(scaled.HasValue());
|
||||
EXPECT_EQ(scaled.GetStatus().Diagnostics()[0].code,
|
||||
"uncertain-thermal-shell-metric");
|
||||
EXPECT_EQ(scaled.GetStatus().Diagnostics()[0].message,
|
||||
"Metric inverse enclosure is not finite or excludes no zero divisor.");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user