feat(nonlinear-static-newton-raphson): step 1 - nonlinear-static-domain-contract
This commit is contained in:
@@ -174,6 +174,12 @@ TipSecond, 6, 1.
|
||||
)inp";
|
||||
}
|
||||
|
||||
std::string NonlinearShellDeck() {
|
||||
return ReplaceOnce(
|
||||
ReplaceOnce(ShellDeck(), "nlgeom=NO", "nlgeom=YES"),
|
||||
"0.1, 1., 0.01, 1.", "0.1, 1., 0.001, 0.1");
|
||||
}
|
||||
|
||||
std::string SupportedInventoryDeck(bool include_no_ops) {
|
||||
const std::string preprint =
|
||||
include_no_ops ? "*Preprint, echo=NO, model=NO, history=NO, contact=NO\n"
|
||||
@@ -570,6 +576,142 @@ TEST(InpDomainMapping, NoOpAllowlistWarnsWithoutSemanticEffect) {
|
||||
plain.Value().Steps()[0].Loads().size());
|
||||
}
|
||||
|
||||
// NSNR-IO-001, NSNR-IO-005, NSNR-IO-007
|
||||
TEST(InpDomainMapping, MapsNonlinearStaticShellProcedureAndRawControls) {
|
||||
auto result = MapText("nonlinear-static-shell", NonlinearShellDeck());
|
||||
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
const fesa::Domain& domain = result.Value();
|
||||
ASSERT_EQ(domain.Steps().Size(), 1U);
|
||||
const auto& step = domain.Steps()[0U];
|
||||
EXPECT_EQ(step.ProcedureKind(),
|
||||
fesa::StaticProcedureKind::kNonlinearFullNewton);
|
||||
EXPECT_TRUE(step.IsNonlinearStatic());
|
||||
EXPECT_DOUBLE_EQ(step.InitialIncrement(), 0.1);
|
||||
EXPECT_DOUBLE_EQ(step.TimePeriod(), 1.0);
|
||||
EXPECT_DOUBLE_EQ(step.MinimumIncrement(), 0.001);
|
||||
EXPECT_DOUBLE_EQ(step.MaximumIncrement(), 0.1);
|
||||
EXPECT_TRUE(domain.BeamElements().Empty());
|
||||
ASSERT_EQ(domain.ShellElements().Size(), 4U);
|
||||
EXPECT_EQ(domain.ShellElements()[0U].source_type,
|
||||
fesa::ShellSourceElementType::kS4);
|
||||
EXPECT_EQ(domain.ShellElements()[1U].source_type,
|
||||
fesa::ShellSourceElementType::kS4r);
|
||||
}
|
||||
|
||||
// NSNR-IO-002, NSNR-IO-003
|
||||
TEST(InpDomainMapping, KeepsExplicitAndImplicitLinearStaticProcedures) {
|
||||
const std::vector<std::string> decks{
|
||||
ShellDeck(), ReplaceOnce(ShellDeck(), ", nlgeom=NO", "")};
|
||||
|
||||
for (std::size_t index = 0U; index < decks.size(); ++index) {
|
||||
SCOPED_TRACE(index);
|
||||
auto result = MapText("linear-static-procedure-" + std::to_string(index),
|
||||
decks[index]);
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
ASSERT_EQ(result.Value().Steps().Size(), 1U);
|
||||
EXPECT_EQ(result.Value().Steps()[0U].ProcedureKind(),
|
||||
fesa::StaticProcedureKind::kLinearSmallDisplacement);
|
||||
EXPECT_FALSE(result.Value().Steps()[0U].IsNonlinearStatic());
|
||||
}
|
||||
}
|
||||
|
||||
// NSNR-IO-004
|
||||
TEST(InpDomainMapping, RejectsInvalidNonlinearStaticControlValues) {
|
||||
struct InvalidCase {
|
||||
std::string name;
|
||||
std::string controls;
|
||||
};
|
||||
const std::vector<InvalidCase> cases{
|
||||
{"zero", "0., 1., 0.001, 0.1"},
|
||||
{"nonfinite", "nan, 1., 0.001, 0.1"},
|
||||
{"nonunit-period", "0.1, 0.5, 0.001, 0.1"},
|
||||
{"reversed-bounds", "0.1, 1., 0.2, 0.1"}};
|
||||
|
||||
for (const auto& test_case : cases) {
|
||||
SCOPED_TRACE(test_case.name);
|
||||
auto result = MapText(
|
||||
"invalid-nonlinear-static-" + test_case.name,
|
||||
ReplaceOnce(NonlinearShellDeck(), "0.1, 1., 0.001, 0.1",
|
||||
test_case.controls));
|
||||
ASSERT_FALSE(result.HasValue());
|
||||
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
|
||||
ASSERT_NE(FindDiagnostic(result.GetStatus(), "invalid-nonlinear-static-data"),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// NSNR-IO-006, NSNR-IO-008
|
||||
TEST(InpDomainMapping, RejectsUnsupportedNonlinearProceduresAndMixedModels) {
|
||||
const std::string nonlinear = NonlinearShellDeck();
|
||||
const std::vector<std::pair<std::string, std::string>> procedure_cases{
|
||||
{"dynamic",
|
||||
ReplaceOnce(nonlinear, "*Static\n0.1, 1., 0.001, 0.1",
|
||||
"*Dynamic\n0.1, 1., 0.001, 0.1")},
|
||||
{"mixed-steps",
|
||||
nonlinear + "*Step, name=Linear, nlgeom=NO\n*Static\n0.1, 1., 0.01, "
|
||||
"1.\n*End Step\n"},
|
||||
{"beam-nlgeom",
|
||||
ReplaceOnce(MinimalDeck(), "nlgeom=NO", "nlgeom=YES")}};
|
||||
|
||||
for (const auto& test_case : procedure_cases) {
|
||||
SCOPED_TRACE(test_case.first);
|
||||
auto result = MapText("unsupported-nonlinear-" + test_case.first,
|
||||
test_case.second);
|
||||
ASSERT_FALSE(result.HasValue());
|
||||
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
|
||||
ASSERT_NE(FindDiagnostic(result.GetStatus(), "unsupported-analysis-procedure"),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
const std::string mixed_model = ReplaceOnce(
|
||||
nonlinear, "0020, 2, 5, 6, 3\n*Elset",
|
||||
"0020, 2, 5, 6, 3\n*Element, type=B33\n30, 1, 2\n*Elset");
|
||||
auto mixed_result = MapText("mixed-nonlinear-model", mixed_model);
|
||||
ASSERT_FALSE(mixed_result.HasValue());
|
||||
EXPECT_EQ(mixed_result.GetStatus().Category(), fesa::FailureCategory::kInput);
|
||||
ASSERT_NE(FindDiagnostic(mixed_result.GetStatus(),
|
||||
"unsupported-mixed-element-model"),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
// NSNR-IO-009, NSNR-IO-010, NSNR-IO-011
|
||||
TEST(InpDomainMapping, AcceptsOnlyNonlinearPreselectOutputNoOps) {
|
||||
auto plain = MapText("nonlinear-output-plain", NonlinearShellDeck());
|
||||
ASSERT_TRUE(plain.HasValue());
|
||||
|
||||
for (const std::string_view request : {"field", "history"}) {
|
||||
const std::string deck = ReplaceOnce(
|
||||
NonlinearShellDeck(), "*End Step\n",
|
||||
"*Output, " + std::string{request} + ", variable=PRESELECT\n*End Step\n");
|
||||
auto result = MapText("nonlinear-output-" + std::string{request}, deck);
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
EXPECT_EQ(result.Value().Nodes().size(), plain.Value().Nodes().size());
|
||||
EXPECT_EQ(result.Value().Steps().Size(), plain.Value().Steps().Size());
|
||||
EXPECT_EQ(result.Value().Steps()[0U].BoundaryConditions().size(),
|
||||
plain.Value().Steps()[0U].BoundaryConditions().size());
|
||||
EXPECT_EQ(result.Value().Steps()[0U].Loads().size(),
|
||||
plain.Value().Steps()[0U].Loads().size());
|
||||
ASSERT_EQ(result.Value().Warnings().size(), 1U);
|
||||
EXPECT_EQ(result.Value().Warnings()[0U].keyword, "OUTPUT");
|
||||
}
|
||||
|
||||
const std::vector<std::string> malformed_requests{
|
||||
"*Output, field\n", "*Output, field, history, variable=PRESELECT\n",
|
||||
"*Output, field, variable=ALL\n"};
|
||||
for (std::size_t index = 0U; index < malformed_requests.size(); ++index) {
|
||||
SCOPED_TRACE(index);
|
||||
auto result = MapText(
|
||||
"malformed-nonlinear-output-" + std::to_string(index),
|
||||
ReplaceOnce(NonlinearShellDeck(), "*End Step\n",
|
||||
malformed_requests[index] + "*End Step\n"));
|
||||
ASSERT_FALSE(result.HasValue());
|
||||
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kInput);
|
||||
ASSERT_NE(FindDiagnostic(result.GetStatus(), "invalid-keyword-parameter"),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// MITC4-MAP-001
|
||||
// C-MODEL-002
|
||||
TEST(InpDomainMapping, MapsS4AndS4rThroughOneMitc4Identity) {
|
||||
@@ -738,8 +880,6 @@ TEST(InpDomainMapping,
|
||||
const std::vector<InvalidCase> cases{
|
||||
{"second-step", base + "*Step\n*Static\n1., 1., 1., 1.\n*End Step\n",
|
||||
"unsupported-multiple-step"},
|
||||
{"nonlinear-step", ReplaceOnce(base, "nlgeom=NO", "nlgeom=YES"),
|
||||
"unsupported-nonlinear-geometry"},
|
||||
{"other-procedure",
|
||||
ReplaceOnce(base, "*Static\n0.1, 1., 0.01, 1.",
|
||||
"*Dynamic\n0.1, 1., 0.01, 1."),
|
||||
@@ -898,7 +1038,7 @@ TEST(InpDomainMapping, RejectsUnsupportedAndInvalidPortfolio) {
|
||||
{"malformed-node-arity", ReplaceOnce(base, "1, 0., 0., 0.", "1, 0., 0."),
|
||||
"invalid-data-arity", fesa::FailureCategory::kInput},
|
||||
{"nlgeom", ReplaceOnce(base, "nlgeom=NO", "nlgeom=YES"),
|
||||
"unsupported-nonlinear-geometry", fesa::FailureCategory::kModel},
|
||||
"unsupported-analysis-procedure", fesa::FailureCategory::kInput},
|
||||
{"unknown-keyword",
|
||||
ReplaceOnce(base, "*Assembly, name=Assembly",
|
||||
"*Density\n1.\n*Assembly, name=Assembly"),
|
||||
|
||||
@@ -150,6 +150,9 @@ TEST(DomainMappingComponents,
|
||||
EXPECT_EQ(domain.Materials().Size(), 1U);
|
||||
EXPECT_EQ(domain.Properties().Size(), 1U);
|
||||
ASSERT_EQ(domain.Steps().Size(), 1U);
|
||||
EXPECT_EQ(domain.Steps()[0].ProcedureKind(),
|
||||
StaticProcedureKind::kLinearSmallDisplacement);
|
||||
EXPECT_FALSE(domain.Steps()[0].IsNonlinearStatic());
|
||||
EXPECT_EQ(domain.Steps()[0].BoundaryConditions().size(), 7U);
|
||||
EXPECT_EQ(domain.Steps()[0].Loads().size(), 1U);
|
||||
ASSERT_EQ(domain.Warnings().size(), 3U);
|
||||
|
||||
Reference in New Issue
Block a user