feat(abaqus-subset-completion): step 3 — material-section-and-shear-defaults
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
#include <fesa/io/abaqus/semantic_mapper.hpp>
|
||||
|
||||
#include <fesa/io/abaqus/active_input.hpp>
|
||||
#include <fesa/io/abaqus/set_resolver.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
@@ -28,6 +33,24 @@ const std::string* parameter(
|
||||
return found == record.parameters.end() ? nullptr : &found->second;
|
||||
}
|
||||
|
||||
SourceLocation data_source(
|
||||
const DeckRecord& record,
|
||||
const std::size_t row) {
|
||||
return row < record.data_sources.size()
|
||||
? record.data_sources[row]
|
||||
: record.source;
|
||||
}
|
||||
|
||||
bool parse_number(const std::string_view text, double& value) {
|
||||
const auto parsed = std::from_chars(
|
||||
text.data(),
|
||||
text.data() + text.size(),
|
||||
value,
|
||||
std::chars_format::general);
|
||||
return parsed.ec == std::errc{} &&
|
||||
parsed.ptr == text.data() + text.size() && std::isfinite(value);
|
||||
}
|
||||
|
||||
class DeckMapper final {
|
||||
public:
|
||||
explicit DeckMapper(const ParsedDeck& deck) : deck_{deck} {}
|
||||
@@ -39,15 +62,20 @@ public:
|
||||
return failure();
|
||||
}
|
||||
active_records_ = selected.input->part_records;
|
||||
assembly_records_ = selected.input->assembly_records;
|
||||
flat_ = selected.input->flat;
|
||||
part_name_ = std::move(selected.input->part_name);
|
||||
instance_name_ = std::move(selected.input->instance_name);
|
||||
|
||||
collect_materials();
|
||||
collect_nodes();
|
||||
collect_raw_sets(active_records_, false);
|
||||
if (!assembly_records_.empty()) {
|
||||
collect_raw_sets(assembly_records_, true);
|
||||
SetResolutionResult resolved_sets = resolve_sets(deck_);
|
||||
if (!resolved_sets.diagnostics.empty()) {
|
||||
diagnostics_.insert(
|
||||
diagnostics_.end(),
|
||||
std::make_move_iterator(resolved_sets.diagnostics.begin()),
|
||||
std::make_move_iterator(resolved_sets.diagnostics.end()));
|
||||
} else {
|
||||
collect_resolved_sets(resolved_sets.sets);
|
||||
}
|
||||
collect_sections();
|
||||
collect_elements();
|
||||
@@ -66,6 +94,19 @@ private:
|
||||
SectionId section;
|
||||
};
|
||||
|
||||
struct MaterialProperties final {
|
||||
MaterialId id;
|
||||
double young;
|
||||
double poisson;
|
||||
};
|
||||
|
||||
struct MaterialDefinition final {
|
||||
std::string name;
|
||||
SourceLocation source;
|
||||
const DeckRecord* elastic = nullptr;
|
||||
bool duplicate = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] DomainBuildResult failure() {
|
||||
return {std::nullopt, std::move(diagnostics_)};
|
||||
}
|
||||
@@ -158,47 +199,105 @@ private:
|
||||
}
|
||||
|
||||
void collect_materials() {
|
||||
const std::string* current_name = nullptr;
|
||||
std::vector<MaterialDefinition> definitions;
|
||||
std::map<std::string, std::size_t, std::less<>> first_definition;
|
||||
std::optional<std::size_t> current_definition;
|
||||
|
||||
for (const DeckRecord& record : deck_.global_records) {
|
||||
if (record.keyword == "MATERIAL") {
|
||||
current_name = require_parameter(record, "NAME");
|
||||
const std::string* name = require_parameter(record, "NAME");
|
||||
if (name == nullptr) {
|
||||
current_definition.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool duplicate = first_definition.contains(*name);
|
||||
if (duplicate) {
|
||||
add_error(
|
||||
"abaqus.semantic.duplicate_material",
|
||||
"Material '" + *name +
|
||||
"' is defined more than once.",
|
||||
record.source);
|
||||
}
|
||||
definitions.push_back({
|
||||
*name,
|
||||
record.source,
|
||||
nullptr,
|
||||
duplicate,
|
||||
});
|
||||
current_definition = definitions.size() - 1U;
|
||||
first_definition.try_emplace(*name, *current_definition);
|
||||
continue;
|
||||
}
|
||||
if (record.keyword != "ELASTIC") {
|
||||
continue;
|
||||
}
|
||||
if (current_name == nullptr) {
|
||||
if (!current_definition.has_value()) {
|
||||
add_error(
|
||||
"abaqus.semantic.elastic_without_material",
|
||||
"*ELASTIC requires a preceding *MATERIAL.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
if (record.data.empty() || record.data[0].size() < 2U) {
|
||||
|
||||
MaterialDefinition& definition =
|
||||
definitions[*current_definition];
|
||||
if (definition.elastic != nullptr) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_elastic_data",
|
||||
"*ELASTIC requires Young's modulus and Poisson ratio.",
|
||||
"A material accepts exactly one *ELASTIC record.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
definition.elastic = &record;
|
||||
}
|
||||
|
||||
const auto young =
|
||||
parse_real(record.data[0][0], record, "Young's modulus");
|
||||
const auto poisson =
|
||||
parse_real(record.data[0][1], record, "Poisson ratio");
|
||||
if (!young.has_value() || !poisson.has_value()) {
|
||||
for (const MaterialDefinition& definition : definitions) {
|
||||
if (definition.duplicate) {
|
||||
continue;
|
||||
}
|
||||
if (definition.elastic == nullptr) {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_elastic",
|
||||
"Material '" + definition.name +
|
||||
"' requires one *ELASTIC record.",
|
||||
definition.source);
|
||||
continue;
|
||||
}
|
||||
|
||||
const DeckRecord& elastic = *definition.elastic;
|
||||
const SourceLocation source =
|
||||
elastic.data.empty() ? elastic.source
|
||||
: data_source(elastic, 0U);
|
||||
if (elastic.data.size() != 1U ||
|
||||
elastic.data[0].size() != 2U ||
|
||||
elastic.data[0][0].empty() ||
|
||||
elastic.data[0][1].empty()) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_elastic_data",
|
||||
"*ELASTIC requires exactly one E, nu data row.",
|
||||
source);
|
||||
continue;
|
||||
}
|
||||
|
||||
double young = 0.0;
|
||||
double poisson = 0.0;
|
||||
if (!parse_number(elastic.data[0][0], young) ||
|
||||
!parse_number(elastic.data[0][1], poisson) ||
|
||||
young <= 0.0 || poisson <= -1.0 || poisson >= 0.5) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_elastic_data",
|
||||
"*ELASTIC requires finite E > 0 and -1 < nu < 0.5.",
|
||||
source);
|
||||
continue;
|
||||
}
|
||||
|
||||
const MaterialId id{next_material_id_++};
|
||||
if (!material_ids_.emplace(*current_name, id).second) {
|
||||
add_error(
|
||||
"abaqus.semantic.duplicate_material",
|
||||
"Material '" + *current_name + "' is defined more than once.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
builder_.add_material({id, *current_name, *young, *poisson});
|
||||
materials_.emplace(
|
||||
definition.name,
|
||||
MaterialProperties{id, young, poisson});
|
||||
builder_.add_material(
|
||||
{id, definition.name, young, poisson});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,125 +335,267 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void collect_raw_sets(
|
||||
const std::span<const DeckRecord> records,
|
||||
const bool assembly_scope) {
|
||||
for (const DeckRecord& record : records) {
|
||||
const bool is_node_set = record.keyword == "NSET";
|
||||
const bool is_element_set = record.keyword == "ELSET";
|
||||
if (!is_node_set && !is_element_set) {
|
||||
void collect_resolved_sets(const std::vector<ResolvedSet>& sets) {
|
||||
for (const ResolvedSet& set : sets) {
|
||||
const bool mesh_scope =
|
||||
(flat_ && set.scope == ResolvedSetScope::global) ||
|
||||
(!flat_ && set.scope == ResolvedSetScope::part &&
|
||||
set.scope_name == part_name_);
|
||||
const bool assembly_scope =
|
||||
!flat_ && set.scope == ResolvedSetScope::assembly &&
|
||||
deck_.assembly.has_value() &&
|
||||
set.scope_name == deck_.assembly->name;
|
||||
if (!mesh_scope && !assembly_scope) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string* name =
|
||||
require_parameter(record, is_node_set ? "NSET" : "ELSET");
|
||||
if (name == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (assembly_scope) {
|
||||
const std::string* instance = parameter(record, "INSTANCE");
|
||||
if (instance == nullptr || *instance != instance_name_) {
|
||||
add_error(
|
||||
"abaqus.semantic.wrong_instance",
|
||||
"Assembly set '" + *name +
|
||||
"' must reference the active Instance.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RawSetMap& target = set.kind == ResolvedSetKind::node
|
||||
? raw_node_sets_
|
||||
: raw_element_sets_;
|
||||
std::vector<std::int64_t>& labels = target[set.set_name];
|
||||
labels.insert(
|
||||
labels.end(),
|
||||
set.sorted_unique_labels.begin(),
|
||||
set.sorted_unique_labels.end());
|
||||
std::ranges::sort(labels);
|
||||
labels.erase(std::ranges::unique(labels).begin(), labels.end());
|
||||
|
||||
std::vector<std::int64_t> labels;
|
||||
for (const auto& row : record.data) {
|
||||
for (const std::string& field : row) {
|
||||
if (field.empty()) {
|
||||
continue;
|
||||
}
|
||||
const auto label =
|
||||
parse_label(field, record, "set member");
|
||||
if (label.has_value()) {
|
||||
labels.push_back(*label);
|
||||
}
|
||||
}
|
||||
if (mesh_scope && set.kind == ResolvedSetKind::element) {
|
||||
active_element_sets_[set.set_name] =
|
||||
set.sorted_unique_labels;
|
||||
}
|
||||
RawSetMap& sets = is_node_set ? raw_node_sets_ : raw_element_sets_;
|
||||
sets[*name] = std::move(labels);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_sections() {
|
||||
for (const DeckRecord& record : active_records_) {
|
||||
for (std::size_t index = 0; index < active_records_.size(); ++index) {
|
||||
const DeckRecord& record = active_records_[index];
|
||||
if (record.keyword == "TRANSVERSE SHEAR STIFFNESS") {
|
||||
add_error(
|
||||
"abaqus.semantic.orphan_transverse_shear",
|
||||
"*TRANSVERSE SHEAR STIFFNESS must immediately follow "
|
||||
"*BEAM GENERAL SECTION.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
if (record.keyword != "BEAM GENERAL SECTION") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const DeckRecord* shear = nullptr;
|
||||
if (index + 1U < active_records_.size() &&
|
||||
active_records_[index + 1U].keyword ==
|
||||
"TRANSVERSE SHEAR STIFFNESS") {
|
||||
shear = &active_records_[index + 1U];
|
||||
++index;
|
||||
}
|
||||
|
||||
bool valid = true;
|
||||
const std::string* section_type =
|
||||
require_parameter(record, "SECTION");
|
||||
const std::string* element_set =
|
||||
require_parameter(record, "ELSET");
|
||||
const std::string* material_name =
|
||||
require_parameter(record, "MATERIAL");
|
||||
if (element_set == nullptr || material_name == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const auto material = material_ids_.find(*material_name);
|
||||
if (material == material_ids_.end()) {
|
||||
if (section_type == nullptr || element_set == nullptr ||
|
||||
material_name == nullptr) {
|
||||
valid = false;
|
||||
} else if (*section_type != "GENERAL") {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_material",
|
||||
"Beam section references missing Material '" +
|
||||
*material_name + "'.",
|
||||
"abaqus.semantic.unsupported_section",
|
||||
"Phase 1 supports only SECTION=GENERAL.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
if (record.data.size() < 2U ||
|
||||
record.data[0].size() < 5U ||
|
||||
record.data[1].size() < 3U) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_section_data",
|
||||
"*BEAM GENERAL SECTION requires general properties and "
|
||||
"an orientation vector.",
|
||||
record.source);
|
||||
continue;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
const auto area = parse_real(record.data[0][0], record, "area");
|
||||
const auto iy = parse_real(record.data[0][1], record, "Iy");
|
||||
const auto iz = parse_real(record.data[0][3], record, "Iz");
|
||||
const auto torsion =
|
||||
parse_real(record.data[0][4], record, "torsion J");
|
||||
const auto ox =
|
||||
parse_real(record.data[1][0], record, "orientation");
|
||||
const auto oy =
|
||||
parse_real(record.data[1][1], record, "orientation");
|
||||
const auto oz =
|
||||
parse_real(record.data[1][2], record, "orientation");
|
||||
if (!area.has_value() || !iy.has_value() || !iz.has_value() ||
|
||||
!torsion.has_value() || !ox.has_value() || !oy.has_value() ||
|
||||
!oz.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const SectionId section_id{next_section_id_++};
|
||||
if (!section_assignments_
|
||||
.emplace(
|
||||
*element_set,
|
||||
SectionAssignment{material->second, section_id})
|
||||
.second) {
|
||||
if (element_set != nullptr &&
|
||||
!assigned_element_set_names_.insert(*element_set).second) {
|
||||
add_error(
|
||||
"abaqus.semantic.duplicate_section_assignment",
|
||||
"Element set '" + *element_set +
|
||||
"' has more than one section assignment.",
|
||||
record.source);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
auto material = materials_.end();
|
||||
if (material_name != nullptr) {
|
||||
material = materials_.find(*material_name);
|
||||
if (material == materials_.end()) {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_material",
|
||||
"Beam section references missing Material '" +
|
||||
*material_name + "'.",
|
||||
record.source);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
auto resolved_set = active_element_sets_.end();
|
||||
if (element_set != nullptr) {
|
||||
resolved_set = active_element_sets_.find(*element_set);
|
||||
if (resolved_set == active_element_sets_.end()) {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_element_set",
|
||||
"Beam section references missing element set '" +
|
||||
*element_set + "'.",
|
||||
record.source);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<double, 5> properties{};
|
||||
std::array<double, 3> orientation{};
|
||||
if (record.data.size() != 2U ||
|
||||
record.data[0].size() != properties.size() ||
|
||||
record.data[1].size() != orientation.size()) {
|
||||
SourceLocation section_data_source = record.source;
|
||||
if (!record.data.empty()) {
|
||||
if (record.data[0].size() != properties.size()) {
|
||||
section_data_source = data_source(record, 0U);
|
||||
} else if (record.data.size() > 2U) {
|
||||
section_data_source = data_source(record, 2U);
|
||||
} else if (record.data.size() == 2U) {
|
||||
section_data_source = data_source(record, 1U);
|
||||
}
|
||||
}
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_section_data",
|
||||
"*BEAM GENERAL SECTION requires exactly A, Iy, Iyz, Iz, "
|
||||
"J and one three-component orientation row.",
|
||||
section_data_source);
|
||||
valid = false;
|
||||
} else {
|
||||
bool valid_properties = true;
|
||||
for (std::size_t field = 0; field < properties.size(); ++field) {
|
||||
valid_properties = parse_number(
|
||||
record.data[0][field],
|
||||
properties[field]) &&
|
||||
valid_properties;
|
||||
}
|
||||
valid_properties =
|
||||
valid_properties && properties[0] > 0.0 &&
|
||||
properties[1] > 0.0 && properties[2] == 0.0 &&
|
||||
properties[3] > 0.0 && properties[4] > 0.0;
|
||||
if (!valid_properties) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_section_data",
|
||||
"General Beam properties require finite positive A, "
|
||||
"Iy, Iz, J and Iyz=0.",
|
||||
data_source(record, 0U));
|
||||
}
|
||||
|
||||
bool valid_orientation = true;
|
||||
for (std::size_t field = 0; field < orientation.size(); ++field) {
|
||||
valid_orientation = parse_number(
|
||||
record.data[1][field],
|
||||
orientation[field]) &&
|
||||
valid_orientation;
|
||||
}
|
||||
if (!valid_orientation) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_section_data",
|
||||
"Beam section orientation components must be finite.",
|
||||
data_source(record, 1U));
|
||||
}
|
||||
valid = valid && valid_properties && valid_orientation;
|
||||
}
|
||||
|
||||
double shear_area_y = 0.0;
|
||||
double shear_area_z = 0.0;
|
||||
ShearPropertySource shear_source =
|
||||
ShearPropertySource::phase1_default;
|
||||
if (shear == nullptr) {
|
||||
shear_area_y = 5.0 * properties[0] / 6.0;
|
||||
shear_area_z = shear_area_y;
|
||||
} else {
|
||||
const SourceLocation shear_source_location =
|
||||
shear->data.empty() ? shear->source
|
||||
: data_source(*shear, 0U);
|
||||
std::array<double, 3> values{};
|
||||
bool valid_shear =
|
||||
shear->data.size() == 1U &&
|
||||
shear->data[0].size() == values.size();
|
||||
if (valid_shear) {
|
||||
for (std::size_t field = 0; field < values.size(); ++field) {
|
||||
valid_shear = parse_number(
|
||||
shear->data[0][field], values[field]) &&
|
||||
valid_shear;
|
||||
}
|
||||
}
|
||||
if (!valid_shear || values[0] <= 0.0 || values[1] <= 0.0) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_transverse_shear_data",
|
||||
"*TRANSVERSE SHEAR STIFFNESS requires finite positive "
|
||||
"K23, K13 and numeric SCF=0.",
|
||||
shear_source_location);
|
||||
valid = false;
|
||||
} else if (values[2] != 0.0) {
|
||||
add_error(
|
||||
"abaqus.semantic.nonzero_scf",
|
||||
"Phase 1 supports only SCF=0.",
|
||||
shear_source_location);
|
||||
valid = false;
|
||||
} else if (material != materials_.end()) {
|
||||
const double shear_modulus =
|
||||
material->second.young /
|
||||
(2.0 * (1.0 + material->second.poisson));
|
||||
shear_area_y = values[0] / shear_modulus;
|
||||
shear_area_z = values[1] / shear_modulus;
|
||||
if (!std::isfinite(shear_area_y) ||
|
||||
!std::isfinite(shear_area_z) ||
|
||||
shear_area_y <= 0.0 || shear_area_z <= 0.0) {
|
||||
add_error(
|
||||
"abaqus.semantic.invalid_transverse_shear_data",
|
||||
"Transverse stiffness produces an invalid effective "
|
||||
"shear area.",
|
||||
shear_source_location);
|
||||
valid = false;
|
||||
}
|
||||
shear_source = ShearPropertySource::input;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid || element_set == nullptr ||
|
||||
material == materials_.end() ||
|
||||
resolved_set == active_element_sets_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const SectionId section_id{next_section_id_++};
|
||||
const SectionAssignment assignment{
|
||||
material->second.id,
|
||||
section_id,
|
||||
};
|
||||
bool duplicate_member = false;
|
||||
for (const std::int64_t label : resolved_set->second) {
|
||||
if (element_assignments_.contains(label)) {
|
||||
duplicate_member = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (duplicate_member) {
|
||||
add_error(
|
||||
"abaqus.semantic.duplicate_section_assignment",
|
||||
"An element has more than one section assignment.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
for (const std::int64_t label : resolved_set->second) {
|
||||
element_assignments_.emplace(label, assignment);
|
||||
}
|
||||
|
||||
builder_.add_section({
|
||||
section_id,
|
||||
*element_set,
|
||||
*area,
|
||||
*iy,
|
||||
*iz,
|
||||
*torsion,
|
||||
5.0 * *area / 6.0,
|
||||
5.0 * *area / 6.0,
|
||||
ShearPropertySource::phase1_default,
|
||||
Vec3{*ox, *oy, *oz},
|
||||
properties[0],
|
||||
properties[1],
|
||||
properties[3],
|
||||
properties[4],
|
||||
shear_area_y,
|
||||
shear_area_z,
|
||||
shear_source,
|
||||
Vec3{orientation[0], orientation[1], orientation[2]},
|
||||
{},
|
||||
});
|
||||
}
|
||||
@@ -367,9 +608,7 @@ private:
|
||||
}
|
||||
|
||||
const std::string* type = require_parameter(record, "TYPE");
|
||||
const std::string* element_set =
|
||||
require_parameter(record, "ELSET");
|
||||
if (type == nullptr || element_set == nullptr) {
|
||||
if (type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (*type != "B31") {
|
||||
@@ -379,15 +618,6 @@ private:
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
const auto assignment = section_assignments_.find(*element_set);
|
||||
if (assignment == section_assignments_.end()) {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_section",
|
||||
"Element set '" + *element_set +
|
||||
"' has no Beam section assignment.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& row : record.data) {
|
||||
if (row.size() < 3U) {
|
||||
@@ -407,6 +637,16 @@ private:
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto assignment = element_assignments_.find(*label);
|
||||
if (assignment == element_assignments_.end()) {
|
||||
add_error(
|
||||
"abaqus.semantic.missing_section",
|
||||
"B31 element " + std::to_string(*label) +
|
||||
" has no Beam section assignment.",
|
||||
record.source);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto first = node_ids_.find(*first_label);
|
||||
const auto second = node_ids_.find(*second_label);
|
||||
if (first == node_ids_.end() || second == node_ids_.end()) {
|
||||
@@ -601,14 +841,16 @@ private:
|
||||
DomainBuilder builder_;
|
||||
std::vector<Diagnostic> diagnostics_;
|
||||
std::span<const DeckRecord> active_records_;
|
||||
std::span<const DeckRecord> assembly_records_;
|
||||
bool flat_ = true;
|
||||
std::string part_name_;
|
||||
std::string instance_name_;
|
||||
LabelMap node_ids_;
|
||||
ElementLabelMap element_ids_;
|
||||
std::map<std::string, MaterialId, std::less<>> material_ids_;
|
||||
std::map<std::string, SectionAssignment, std::less<>>
|
||||
section_assignments_;
|
||||
std::map<std::string, MaterialProperties, std::less<>> materials_;
|
||||
std::map<std::string, std::vector<std::int64_t>, std::less<>>
|
||||
active_element_sets_;
|
||||
std::map<std::int64_t, SectionAssignment> element_assignments_;
|
||||
std::set<std::string, std::less<>> assigned_element_set_names_;
|
||||
RawSetMap raw_node_sets_;
|
||||
RawSetMap raw_element_sets_;
|
||||
std::map<std::string, std::vector<NodeId>, std::less<>> node_sets_;
|
||||
|
||||
Reference in New Issue
Block a user