fix(input): enforce strict Abaqus subset contract
This commit is contained in:
Vendored
+16
@@ -26,6 +26,7 @@ heading_noop_valid valid valid/noop_directives.inp - - 0 2 1 1 1 6 1 phase1_defa
|
||||
preprint_noop_valid valid valid/noop_directives.inp - - 0 2 1 1 1 6 1 phase1_default 0.8333333333333334 0.8333333333333334 Fixed:1 Beam:1
|
||||
restart_noop_valid valid valid/noop_directives.inp - - 0 2 1 1 1 6 1 phase1_default 0.8333333333333334 0.8333333333333334 Fixed:1 Beam:1
|
||||
output_noop_valid valid valid/noop_directives.inp - - 0 2 1 1 1 6 1 phase1_default 0.8333333333333334 0.8333333333333334 Fixed:1 Beam:1
|
||||
enum_case_insensitive_valid valid valid/case_insensitive_enums.inp - - 0 2 1 1 1 6 1 phase1_default 0.8333333333333334 0.8333333333333334 Fixed:1 Beam:1
|
||||
node_duplicate_invalid invalid invalid/node_duplicate.inp semantic abaqus.semantic.duplicate_node_label 3 - - - - - - - - - - -
|
||||
element_type_invalid invalid invalid/element_wrong_type.inp semantic abaqus.semantic.unsupported_element 4 - - - - - - - - - - -
|
||||
part_unclosed_invalid invalid invalid/part_unclosed.inp syntax abaqus.syntax.unclosed_part 1 - - - - - - - - - - -
|
||||
@@ -52,3 +53,18 @@ preprint_parameter_invalid invalid invalid/preprint_invalid_parameter.inp syntax
|
||||
restart_scope_invalid invalid invalid/restart_outside_step.inp syntax abaqus.syntax.invalid_restart_scope 1 - - - - - - - - - - -
|
||||
output_parameter_invalid invalid invalid/output_invalid_parameter.inp syntax abaqus.syntax.unsupported_parameter 3 - - - - - - - - - - -
|
||||
unknown_keyword_invalid invalid invalid/unknown_include.inp syntax abaqus.unsupported_keyword 1 - - - - - - - - - - -
|
||||
node_parameter_invalid invalid invalid/node_unsupported_parameter.inp syntax abaqus.syntax.unsupported_parameter 1 - - - - - - - - - - -
|
||||
node_scope_invalid invalid invalid/node_wrong_scope.inp syntax abaqus.syntax.invalid_node_scope 2 - - - - - - - - - - -
|
||||
material_scope_invalid invalid invalid/material_wrong_scope.inp syntax abaqus.syntax.invalid_material_scope 2 - - - - - - - - - - -
|
||||
generate_form_invalid invalid invalid/generate_valued.inp syntax abaqus.syntax.unsupported_parameter 1 - - - - - - - - - - -
|
||||
flat_set_instance_invalid invalid invalid/flat_set_instance.inp syntax abaqus.syntax.unsupported_parameter 1 - - - - - - - - - - -
|
||||
global_set_hierarchy_invalid invalid invalid/global_set_hierarchical.inp semantic abaqus.semantic.mixed_mesh_organization 1 - - - - - - - - - - -
|
||||
duplicate_part_invalid invalid invalid/duplicate_part.inp semantic abaqus.semantic.duplicate_part 3 - - - - - - - - - - -
|
||||
node_surplus_field_invalid invalid invalid/node_surplus_field.inp semantic abaqus.semantic.invalid_node_data 2 - - - - - - - - - - -
|
||||
node_empty_invalid invalid invalid/node_empty.inp semantic abaqus.semantic.invalid_node_data 1 - - - - - - - - - - -
|
||||
element_surplus_field_invalid invalid invalid/element_surplus_field.inp semantic abaqus.semantic.invalid_element_data 2 - - - - - - - - - - -
|
||||
element_empty_invalid invalid invalid/element_empty.inp semantic abaqus.semantic.invalid_element_data 1 - - - - - - - - - - -
|
||||
hierarchical_part_target_invalid invalid invalid/hierarchical_part_set_target.inp semantic abaqus.semantic.missing_node_target 25 - - - - - - - - - - -
|
||||
material_data_invalid invalid invalid/material_data.inp syntax abaqus.syntax.data_without_keyword 2 - - - - - - - - - - -
|
||||
node_coordinate_invalid invalid invalid/node_invalid_coordinate.inp semantic abaqus.semantic.invalid_number 2 - - - - - - - - - - -
|
||||
element_missing_node_invalid invalid invalid/element_missing_node.inp semantic abaqus.semantic.missing_node 4 - - - - - - - - - - -
|
||||
|
||||
|
@@ -0,0 +1,8 @@
|
||||
*PART, NAME=BeamPart
|
||||
*END PART
|
||||
*PART, NAME=BeamPart
|
||||
*END PART
|
||||
*ASSEMBLY, NAME=RootAssembly
|
||||
*INSTANCE, NAME=Beam-1, PART=BeamPart
|
||||
*END INSTANCE
|
||||
*END ASSEMBLY
|
||||
@@ -0,0 +1,4 @@
|
||||
*ELEMENT, TYPE=B31
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,13 @@
|
||||
*NODE
|
||||
1, 0.0, 0.0, 0.0
|
||||
*ELEMENT, TYPE=B31, ELSET=Beam
|
||||
1, 1, 2
|
||||
*MATERIAL, NAME=Steel
|
||||
*ELASTIC
|
||||
210000.0, 0.3
|
||||
*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=Beam, MATERIAL=Steel
|
||||
1.0, 1.0, 0.0, 1.0, 1.0
|
||||
0.0, 1.0, 0.0
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,5 @@
|
||||
*ELEMENT, TYPE=B31
|
||||
1, 1, 2, 3
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,2 @@
|
||||
*NSET, NSET=Fixed, INSTANCE=Beam-1
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
*NSET, NSET=Generated, GENERATE=YES
|
||||
1, 2, 1
|
||||
@@ -0,0 +1,7 @@
|
||||
*NSET, NSET=Ignored
|
||||
*PART, NAME=BeamPart
|
||||
*END PART
|
||||
*ASSEMBLY, NAME=RootAssembly
|
||||
*INSTANCE, NAME=Beam-1, PART=BeamPart
|
||||
*END INSTANCE
|
||||
*END ASSEMBLY
|
||||
@@ -0,0 +1,26 @@
|
||||
*PART, NAME=BeamPart
|
||||
*NODE
|
||||
1, 0.0, 0.0, 0.0
|
||||
2, 1.0, 0.0, 0.0
|
||||
*ELEMENT, TYPE=B31, ELSET=Beam
|
||||
1, 1, 2
|
||||
*NSET, NSET=Fixed
|
||||
1
|
||||
*ELSET, ELSET=Beam
|
||||
1
|
||||
*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=Beam, MATERIAL=Steel
|
||||
1.0, 1.0, 0.0, 1.0, 1.0
|
||||
0.0, 1.0, 0.0
|
||||
*END PART
|
||||
*ASSEMBLY, NAME=RootAssembly
|
||||
*INSTANCE, NAME=Beam-1, PART=BeamPart
|
||||
*END INSTANCE
|
||||
*END ASSEMBLY
|
||||
*MATERIAL, NAME=Steel
|
||||
*ELASTIC
|
||||
200.0, 0.25
|
||||
*STEP
|
||||
*STATIC
|
||||
*BOUNDARY
|
||||
Fixed, 1, 6
|
||||
*END STEP
|
||||
@@ -0,0 +1,2 @@
|
||||
*MATERIAL, NAME=Steel
|
||||
unexpected data
|
||||
@@ -0,0 +1,3 @@
|
||||
*PART, NAME=BeamPart
|
||||
*MATERIAL, NAME=Steel
|
||||
*END PART
|
||||
@@ -0,0 +1,4 @@
|
||||
*NODE
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,5 @@
|
||||
*NODE
|
||||
1, invalid, 0.0, 0.0
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,5 @@
|
||||
*NODE
|
||||
1, 0.0, 0.0, 0.0, 9.0
|
||||
*STEP
|
||||
*STATIC
|
||||
*END STEP
|
||||
@@ -0,0 +1,2 @@
|
||||
*NODE, EXTRA=1
|
||||
1, 0.0, 0.0, 0.0
|
||||
@@ -0,0 +1,4 @@
|
||||
*ASSEMBLY, NAME=RootAssembly
|
||||
*NODE
|
||||
1, 0.0, 0.0, 0.0
|
||||
*END ASSEMBLY
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
1, 0.0, 0.0, 0.0
|
||||
** Comments and blank lines do not terminate the current data record.
|
||||
|
||||
2, 1.0, 0.0, 0.0,
|
||||
2, 1.0, 0.0, 0.0
|
||||
*eLeMeNt, TYPE=B31, elset=Beam
|
||||
1, 1, 2
|
||||
*NSET, NSET=Fixed
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
*NODE
|
||||
1, 0.0, 0.0, 0.0
|
||||
2, 1.0, 0.0, 0.0
|
||||
*ELEMENT, TYPE=b31, ELSET=Beam
|
||||
1, 1, 2
|
||||
*NSET, NSET=Fixed
|
||||
1
|
||||
*ELSET, ELSET=Beam
|
||||
1
|
||||
*MATERIAL, NAME=Steel
|
||||
*ELASTIC
|
||||
200.0, 0.25
|
||||
*BEAM GENERAL SECTION, SECTION=general, ELSET=Beam, MATERIAL=Steel
|
||||
1.0, 1.0, 0.0, 1.0, 1.0
|
||||
0.0, 1.0, 0.0
|
||||
*BOUNDARY
|
||||
Fixed, 1, 6
|
||||
*STEP, NAME=Load
|
||||
*STATIC
|
||||
*CLOAD
|
||||
2, 2, -1.0
|
||||
*END STEP
|
||||
@@ -173,6 +173,128 @@ TEST(DeckToDomain, NormalizesFlatAndSingleInstanceDecksEquivalently) {
|
||||
fesa::ShearPropertySource::phase1_default);
|
||||
}
|
||||
|
||||
TEST(DeckToDomain, RequiresExactNodeAndB31DataWidthsAndNonemptyRecords) {
|
||||
struct Case final {
|
||||
std::string_view name;
|
||||
std::string_view mesh;
|
||||
std::string_view code;
|
||||
};
|
||||
const Case cases[]{
|
||||
{
|
||||
"node-surplus-field",
|
||||
"*NODE\n1, 0.0, 0.0, 0.0, 9.0\n"
|
||||
"2, 1.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n1, 1, 2\n",
|
||||
"abaqus.semantic.invalid_node_data",
|
||||
},
|
||||
{
|
||||
"node-empty",
|
||||
"*NODE\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n1, 1, 2\n",
|
||||
"abaqus.semantic.invalid_node_data",
|
||||
},
|
||||
{
|
||||
"element-surplus-field",
|
||||
"*NODE\n1, 0.0, 0.0, 0.0\n2, 1.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n1, 1, 2, 3\n",
|
||||
"abaqus.semantic.invalid_element_data",
|
||||
},
|
||||
{
|
||||
"element-empty",
|
||||
"*NODE\n1, 0.0, 0.0, 0.0\n2, 1.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n",
|
||||
"abaqus.semantic.invalid_element_data",
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& test_case : cases) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-exact-mesh-data-" + std::string{test_case.name} + ".inp",
|
||||
std::string{test_case.mesh} +
|
||||
"*ELSET, ELSET=Beam\n1\n"
|
||||
"*MATERIAL, NAME=Steel\n"
|
||||
"*ELASTIC\n210000.0, 0.3\n"
|
||||
"*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=Beam, "
|
||||
"MATERIAL=Steel\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n0.0, 1.0, 0.0\n"
|
||||
"*STEP\n*STATIC\n*END STEP\n",
|
||||
};
|
||||
|
||||
const auto result = parse_and_map(input.path());
|
||||
|
||||
SCOPED_TRACE(test_case.name);
|
||||
EXPECT_FALSE(result.domain.has_value());
|
||||
EXPECT_TRUE(has_diagnostic(result, test_case.code));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DeckToDomain, ReportsMeshDataErrorsAtTheOffendingRows) {
|
||||
const TemporaryDeck invalid_coordinate{
|
||||
"fesa-node-coordinate-source.inp",
|
||||
"*NODE\n"
|
||||
"1, invalid, 0.0, 0.0\n"
|
||||
"*STEP\n"
|
||||
"*STATIC\n"
|
||||
"*END STEP\n"};
|
||||
const TemporaryDeck missing_node{
|
||||
"fesa-element-node-source.inp",
|
||||
"*NODE\n"
|
||||
"1, 0.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n"
|
||||
"1, 1, 2\n"
|
||||
"*MATERIAL, NAME=Steel\n"
|
||||
"*ELASTIC\n"
|
||||
"210000.0, 0.3\n"
|
||||
"*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=Beam, MATERIAL=Steel\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n"
|
||||
"0.0, 1.0, 0.0\n"
|
||||
"*STEP\n"
|
||||
"*STATIC\n"
|
||||
"*END STEP\n"};
|
||||
|
||||
const auto coordinate_result = parse_and_map(invalid_coordinate.path());
|
||||
const auto missing_node_result = parse_and_map(missing_node.path());
|
||||
|
||||
const fesa::Diagnostic* coordinate =
|
||||
find_diagnostic(coordinate_result, "abaqus.semantic.invalid_number");
|
||||
ASSERT_NE(coordinate, nullptr);
|
||||
ASSERT_TRUE(coordinate->source.has_value());
|
||||
EXPECT_EQ(coordinate->source->line, 2U);
|
||||
|
||||
const fesa::Diagnostic* node =
|
||||
find_diagnostic(missing_node_result, "abaqus.semantic.missing_node");
|
||||
ASSERT_NE(node, nullptr);
|
||||
ASSERT_TRUE(node->source.has_value());
|
||||
EXPECT_EQ(node->source->line, 4U);
|
||||
}
|
||||
|
||||
TEST(DeckToDomain, AcceptsCaseInsensitiveElementAndSectionValues) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-case-insensitive-enums.inp",
|
||||
"*NODE\n"
|
||||
"1, 0.0, 0.0, 0.0\n"
|
||||
"2, 1.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=b31, ELSET=Beam\n"
|
||||
"1, 1, 2\n"
|
||||
"*ELSET, ELSET=Beam\n"
|
||||
"1\n"
|
||||
"*MATERIAL, NAME=Steel\n"
|
||||
"*ELASTIC\n"
|
||||
"210000.0, 0.3\n"
|
||||
"*BEAM GENERAL SECTION, SECTION=general, ELSET=Beam, MATERIAL=Steel\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n"
|
||||
"0.0, 1.0, 0.0\n"
|
||||
"*STEP\n"
|
||||
"*STATIC\n"
|
||||
"*END STEP\n"};
|
||||
|
||||
const auto result = parse_and_map(input.path());
|
||||
|
||||
ASSERT_TRUE(result.domain.has_value());
|
||||
EXPECT_TRUE(result.diagnostics.empty());
|
||||
EXPECT_EQ(result.domain->beam_elements().size(), 1U);
|
||||
}
|
||||
|
||||
TEST(ActiveInstance, ExcludesPartsNotReferencedByTheInstance) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-active-instance.inp",
|
||||
@@ -406,6 +528,42 @@ TEST(Boundary, CanonicalizesIdenticalGlobalAndStepPrescriptions) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Boundary, HierarchicalTargetsRequireAssemblySets) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-hierarchical-part-set-target.inp",
|
||||
"*PART, NAME=BeamPart\n"
|
||||
"*NODE\n"
|
||||
"1, 0.0, 0.0, 0.0\n"
|
||||
"2, 1.0, 0.0, 0.0\n"
|
||||
"*ELEMENT, TYPE=B31, ELSET=Beam\n"
|
||||
"1, 1, 2\n"
|
||||
"*NSET, NSET=Fixed\n"
|
||||
"1\n"
|
||||
"*ELSET, ELSET=Beam\n"
|
||||
"1\n"
|
||||
"*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=Beam, MATERIAL=Steel\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n"
|
||||
"0.0, 1.0, 0.0\n"
|
||||
"*END PART\n"
|
||||
"*ASSEMBLY, NAME=RootAssembly\n"
|
||||
"*INSTANCE, NAME=Beam-1, PART=BeamPart\n"
|
||||
"*END INSTANCE\n"
|
||||
"*END ASSEMBLY\n"
|
||||
"*MATERIAL, NAME=Steel\n"
|
||||
"*ELASTIC\n"
|
||||
"210000.0, 0.3\n"
|
||||
"*STEP\n"
|
||||
"*STATIC\n"
|
||||
"*BOUNDARY\n"
|
||||
"Fixed, 1, 6\n"
|
||||
"*END STEP\n"};
|
||||
|
||||
const auto result = parse_and_map(input.path());
|
||||
|
||||
EXPECT_FALSE(result.domain.has_value());
|
||||
EXPECT_TRUE(has_diagnostic(result, "abaqus.semantic.missing_node_target"));
|
||||
}
|
||||
|
||||
TEST(Boundary, ReportsConflictAtTheConflictingDataRow) {
|
||||
const auto result =
|
||||
parse_and_map(fixture_path("invalid/boundary_conflict.inp"));
|
||||
|
||||
@@ -130,6 +130,37 @@ TEST(ActiveInput, RejectsMixedFlatAndHierarchicalMeshAtTheFlatRecord) {
|
||||
EXPECT_EQ(diagnostic.source->file, fixture_path("invalid/mixed_mesh.inp"));
|
||||
}
|
||||
|
||||
TEST(ActiveInput, RejectsGlobalSetsInHierarchicalInput) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-global-set-with-hierarchy.inp",
|
||||
"*NSET, NSET=Ignored\n"
|
||||
"*PART, NAME=BeamPart\n"
|
||||
"*END PART\n"
|
||||
"*ASSEMBLY, NAME=RootAssembly\n"
|
||||
"*INSTANCE, NAME=Beam-1, PART=BeamPart\n"
|
||||
"*END INSTANCE\n"
|
||||
"*END ASSEMBLY\n"};
|
||||
|
||||
expect_failure(
|
||||
parse(input.path()), "abaqus.semantic.mixed_mesh_organization", 1U);
|
||||
}
|
||||
|
||||
TEST(ActiveInput, RejectsDuplicatePartNamesAtTheSecondDefinition) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-duplicate-parts.inp",
|
||||
"*PART, NAME=BeamPart\n"
|
||||
"*END PART\n"
|
||||
"*PART, NAME=BeamPart\n"
|
||||
"*END PART\n"
|
||||
"*ASSEMBLY, NAME=RootAssembly\n"
|
||||
"*INSTANCE, NAME=Beam-1, PART=BeamPart\n"
|
||||
"*END INSTANCE\n"
|
||||
"*END ASSEMBLY\n"};
|
||||
|
||||
expect_failure(
|
||||
parse(input.path()), "abaqus.semantic.duplicate_part", 3U);
|
||||
}
|
||||
|
||||
TEST(ActiveInput, RejectsHierarchicalInputWithoutAnAssembly) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-missing-assembly.inp",
|
||||
|
||||
@@ -74,7 +74,7 @@ TEST(AbaqusParser, ParsesCaseInsensitiveKeywordsCommentsAndCommaFields) {
|
||||
EXPECT_EQ(nodes.data[0], (std::vector<std::string>{
|
||||
"1", "0.0", "0.0", "0.0"}));
|
||||
EXPECT_EQ(nodes.data[1], (std::vector<std::string>{
|
||||
"2", "1.0", "0.0", "0.0", ""}));
|
||||
"2", "1.0", "0.0", "0.0"}));
|
||||
EXPECT_EQ(nodes.source.file, path);
|
||||
EXPECT_EQ(nodes.source.line, 3U);
|
||||
EXPECT_EQ(nodes.source.column, 1U);
|
||||
@@ -121,6 +121,214 @@ TEST(AbaqusParser, RejectsUnsupportedKeywordsInsteadOfIgnoringThem) {
|
||||
EXPECT_EQ(result.diagnostics[0].source->line, 2U);
|
||||
}
|
||||
|
||||
TEST(AbaqusParser, RejectsUnsupportedParametersOnSupportedKeywords) {
|
||||
struct Case final {
|
||||
std::string_view name;
|
||||
std::string_view contents;
|
||||
std::size_t line;
|
||||
};
|
||||
const Case cases[]{
|
||||
{"node", "*NODE, EXTRA=1\n1, 0.0, 0.0, 0.0\n", 1U},
|
||||
{"element", "*ELEMENT, TYPE=B31, EXTRA=1\n1, 1, 2\n", 1U},
|
||||
{"part", "*PART, NAME=P, EXTRA=1\n*END PART\n", 1U},
|
||||
{"end-part", "*PART, NAME=P\n*END PART, EXTRA=1\n", 2U},
|
||||
{
|
||||
"assembly",
|
||||
"*ASSEMBLY, NAME=A, EXTRA=1\n*END ASSEMBLY\n",
|
||||
1U,
|
||||
},
|
||||
{
|
||||
"end-assembly",
|
||||
"*ASSEMBLY, NAME=A\n*END ASSEMBLY, EXTRA=1\n",
|
||||
2U,
|
||||
},
|
||||
{
|
||||
"instance",
|
||||
"*ASSEMBLY, NAME=A\n"
|
||||
"*INSTANCE, NAME=I, PART=P, EXTRA=1\n"
|
||||
"*END INSTANCE\n"
|
||||
"*END ASSEMBLY\n",
|
||||
2U,
|
||||
},
|
||||
{
|
||||
"end-instance",
|
||||
"*ASSEMBLY, NAME=A\n"
|
||||
"*INSTANCE, NAME=I, PART=P\n"
|
||||
"*END INSTANCE, EXTRA=1\n"
|
||||
"*END ASSEMBLY\n",
|
||||
3U,
|
||||
},
|
||||
{"nset", "*NSET, NSET=S, EXTRA=1\n1\n", 1U},
|
||||
{"elset", "*ELSET, ELSET=S, EXTRA=1\n1\n", 1U},
|
||||
{"material", "*MATERIAL, NAME=M, EXTRA=1\n", 1U},
|
||||
{
|
||||
"elastic",
|
||||
"*MATERIAL, NAME=M\n*ELASTIC, EXTRA=1\n1.0, 0.3\n",
|
||||
2U,
|
||||
},
|
||||
{
|
||||
"beam-general-section",
|
||||
"*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=S, "
|
||||
"MATERIAL=M, EXTRA=1\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n"
|
||||
"0.0, 1.0, 0.0\n",
|
||||
1U,
|
||||
},
|
||||
{
|
||||
"transverse-shear-stiffness",
|
||||
"*TRANSVERSE SHEAR STIFFNESS, EXTRA=1\n1.0, 1.0, 0.0\n",
|
||||
1U,
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& test_case : cases) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-parser-unsupported-parameter-" +
|
||||
std::string{test_case.name} + ".inp",
|
||||
test_case.contents,
|
||||
};
|
||||
|
||||
const auto result = fesa::parse_deck(input.path());
|
||||
|
||||
SCOPED_TRACE(test_case.name);
|
||||
EXPECT_FALSE(result.deck.has_value());
|
||||
ASSERT_EQ(result.diagnostics.size(), 1U);
|
||||
EXPECT_EQ(
|
||||
result.diagnostics[0].code,
|
||||
"abaqus.syntax.unsupported_parameter");
|
||||
ASSERT_TRUE(result.diagnostics[0].source.has_value());
|
||||
EXPECT_EQ(result.diagnostics[0].source->line, test_case.line);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AbaqusParser, RejectsInvalidParameterFormsAndSetScopeOptions) {
|
||||
struct Case final {
|
||||
std::string_view name;
|
||||
std::string_view contents;
|
||||
std::string_view code;
|
||||
};
|
||||
const Case cases[]{
|
||||
{
|
||||
"generate-valued",
|
||||
"*NSET, NSET=S, GENERATE=YES\n1, 2, 1\n",
|
||||
"abaqus.syntax.unsupported_parameter",
|
||||
},
|
||||
{
|
||||
"generate-empty-valued",
|
||||
"*NSET, NSET=S, GENERATE=\n1, 2, 1\n",
|
||||
"abaqus.syntax.unsupported_parameter",
|
||||
},
|
||||
{
|
||||
"empty-element-set",
|
||||
"*ELEMENT, TYPE=B31, ELSET=\n1, 1, 2\n",
|
||||
"abaqus.syntax.invalid_parameter",
|
||||
},
|
||||
{
|
||||
"instance-on-flat-set",
|
||||
"*NSET, NSET=S, INSTANCE=I\n1\n",
|
||||
"abaqus.syntax.unsupported_parameter",
|
||||
},
|
||||
{
|
||||
"instance-on-part-set",
|
||||
"*PART, NAME=P\n"
|
||||
"*NSET, NSET=S, INSTANCE=I\n"
|
||||
"1\n"
|
||||
"*END PART\n",
|
||||
"abaqus.syntax.unsupported_parameter",
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& test_case : cases) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-parser-parameter-form-" + std::string{test_case.name} +
|
||||
".inp",
|
||||
test_case.contents,
|
||||
};
|
||||
|
||||
const auto result = fesa::parse_deck(input.path());
|
||||
|
||||
SCOPED_TRACE(test_case.name);
|
||||
EXPECT_FALSE(result.deck.has_value());
|
||||
ASSERT_EQ(result.diagnostics.size(), 1U);
|
||||
EXPECT_EQ(result.diagnostics[0].code, test_case.code);
|
||||
ASSERT_TRUE(result.diagnostics[0].source.has_value());
|
||||
EXPECT_EQ(result.diagnostics[0].source->line, 1U +
|
||||
(test_case.name == "instance-on-part-set" ? 1U : 0U));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AbaqusParser, RejectsModelKeywordsOutsideTheirDocumentedScopes) {
|
||||
struct Case final {
|
||||
std::string_view name;
|
||||
std::string_view contents;
|
||||
std::string_view code;
|
||||
std::size_t line;
|
||||
};
|
||||
const Case cases[]{
|
||||
{
|
||||
"node-in-assembly",
|
||||
"*ASSEMBLY, NAME=A\n"
|
||||
"*NODE\n"
|
||||
"1, 0.0, 0.0, 0.0\n"
|
||||
"*END ASSEMBLY\n",
|
||||
"abaqus.syntax.invalid_node_scope",
|
||||
2U,
|
||||
},
|
||||
{
|
||||
"material-in-part",
|
||||
"*PART, NAME=P\n"
|
||||
"*MATERIAL, NAME=M\n"
|
||||
"*END PART\n",
|
||||
"abaqus.syntax.invalid_material_scope",
|
||||
2U,
|
||||
},
|
||||
{
|
||||
"section-in-assembly",
|
||||
"*ASSEMBLY, NAME=A\n"
|
||||
"*BEAM GENERAL SECTION, SECTION=GENERAL, ELSET=S, MATERIAL=M\n"
|
||||
"1.0, 1.0, 0.0, 1.0, 1.0\n"
|
||||
"0.0, 1.0, 0.0\n"
|
||||
"*END ASSEMBLY\n",
|
||||
"abaqus.syntax.invalid_section_scope",
|
||||
2U,
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& test_case : cases) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-parser-invalid-scope-" + std::string{test_case.name} +
|
||||
".inp",
|
||||
test_case.contents,
|
||||
};
|
||||
|
||||
const auto result = fesa::parse_deck(input.path());
|
||||
|
||||
SCOPED_TRACE(test_case.name);
|
||||
EXPECT_FALSE(result.deck.has_value());
|
||||
ASSERT_EQ(result.diagnostics.size(), 1U);
|
||||
EXPECT_EQ(result.diagnostics[0].code, test_case.code);
|
||||
ASSERT_TRUE(result.diagnostics[0].source.has_value());
|
||||
EXPECT_EQ(result.diagnostics[0].source->line, test_case.line);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AbaqusParser, RejectsDataRowsOnMaterial) {
|
||||
const TemporaryDeck input{
|
||||
"fesa-parser-material-data.inp",
|
||||
"*MATERIAL, NAME=Steel\n"
|
||||
"unexpected data\n"};
|
||||
|
||||
const auto result = fesa::parse_deck(input.path());
|
||||
|
||||
EXPECT_FALSE(result.deck.has_value());
|
||||
ASSERT_EQ(result.diagnostics.size(), 1U);
|
||||
EXPECT_EQ(
|
||||
result.diagnostics[0].code,
|
||||
"abaqus.syntax.data_without_keyword");
|
||||
ASSERT_TRUE(result.diagnostics[0].source.has_value());
|
||||
EXPECT_EQ(result.diagnostics[0].source->line, 2U);
|
||||
}
|
||||
|
||||
TEST(ScopedDeck, PreservesPartAssemblyAndInstanceScopes) {
|
||||
const auto path =
|
||||
fixture_path("minimal_part_instance_cantilever.inp");
|
||||
|
||||
Reference in New Issue
Block a user