feat(cpp-object-oriented-modular-refactoring): step 4 - model-element-google-style
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "fesa/results/result_recovery.hpp"
|
||||
|
||||
#include "fesa/elements/euler_beam_3d.hpp"
|
||||
#include "fesa/elements/mitc4_shell.hpp"
|
||||
#include "fesa/elements/euler_beam_3d.h"
|
||||
#include "fesa/elements/mitc4_shell.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -131,15 +131,15 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
const SparseMatrix& fullStiffness,
|
||||
const AnalysisState& state) {
|
||||
const Domain& domain = model.domain();
|
||||
if (domain.nodes().size() >
|
||||
if (domain.Nodes().size() >
|
||||
(std::numeric_limits<std::size_t>::max)() / kDofsPerNode) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-dimensions",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"The semantic node count cannot be represented in full-DOF space.");
|
||||
}
|
||||
const std::size_t fullCount = domain.nodes().size() * kDofsPerNode;
|
||||
const std::size_t fullCount = domain.Nodes().size() * kDofsPerNode;
|
||||
if (dofs.fullDofCount() != fullCount ||
|
||||
fullStiffness.Rows() != fullCount ||
|
||||
fullStiffness.Columns() != fullCount ||
|
||||
@@ -150,8 +150,8 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
state.reaction().Size() != fullCount) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-dimensions",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"Model, DOF, stiffness, and AnalysisState full-space dimensions must agree.");
|
||||
}
|
||||
const Status matrixStatus = fullStiffness.Validate();
|
||||
@@ -161,8 +161,8 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
if (!finite(state.displacement()) || !finite(state.externalForce())) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"Displacement and external-force inputs must be finite.");
|
||||
}
|
||||
|
||||
@@ -176,8 +176,8 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
!strictlyIncreasing(constrainedDofs)) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"Free and constrained DOFs must form stable increasing full-space orders.");
|
||||
}
|
||||
std::vector<unsigned char> ownership(fullCount, 0U);
|
||||
@@ -188,7 +188,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
dofs.freeEquation(fullDof) != equation) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(fullDof),
|
||||
"Free equations must match stable full-DOF order.");
|
||||
}
|
||||
@@ -202,7 +202,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
dofs.freeEquation(fullDof).has_value()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(fullDof),
|
||||
"Constrained DOFs must be unique and absent from free equations.");
|
||||
}
|
||||
@@ -211,7 +211,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
dofs.prescribedValues()[constrained]) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-state",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(fullDof),
|
||||
"Constrained displacement must equal its prescribed value before recovery.");
|
||||
}
|
||||
@@ -220,40 +220,40 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
} catch (const std::out_of_range&) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-dimensions",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"DofManager equation storage must cover every full DOF.");
|
||||
}
|
||||
if (std::find(ownership.begin(), ownership.end(), 0U) != ownership.end()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"Free and constrained DOFs must partition the full range.");
|
||||
}
|
||||
|
||||
EntityIndex previousElement = 0U;
|
||||
bool firstElement = true;
|
||||
for (const EntityIndex element : model.activeElements()) {
|
||||
if (element >= domain.elements().size() ||
|
||||
if (element >= domain.Elements().size() ||
|
||||
(!firstElement && element <= previousElement)) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(element),
|
||||
"Active elements must be unique in stable internal-index order.");
|
||||
}
|
||||
firstElement = false;
|
||||
previousElement = element;
|
||||
const auto& definition = domain.elements()[element];
|
||||
if (definition.nodeIndices[0U] >= domain.nodes().size() ||
|
||||
definition.nodeIndices[1U] >= domain.nodes().size() ||
|
||||
definition.materialIndex >= domain.materials().size() ||
|
||||
definition.sectionIndex >= domain.sections().size()) {
|
||||
const auto& definition = domain.Elements()[element];
|
||||
if (definition.node_indices[0U] >= domain.Nodes().size() ||
|
||||
definition.node_indices[1U] >= domain.Nodes().size() ||
|
||||
definition.material_index >= domain.Materials().size() ||
|
||||
definition.section_index >= domain.Sections().size()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Active beam references must resolve before recovery.");
|
||||
}
|
||||
try {
|
||||
@@ -263,7 +263,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
component < kDofsPerNode;
|
||||
++component) {
|
||||
const std::size_t expected =
|
||||
static_cast<std::size_t>(definition.nodeIndices[endpoint]) *
|
||||
static_cast<std::size_t>(definition.node_indices[endpoint]) *
|
||||
kDofsPerNode +
|
||||
component;
|
||||
if (scatter[endpoint * kDofsPerNode + component] != expected ||
|
||||
@@ -271,7 +271,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Element scatter must preserve endpoint/component full-DOF order.");
|
||||
}
|
||||
}
|
||||
@@ -280,51 +280,51 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Every active element requires one twelve-DOF scatter map.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!model.activeElements().empty() && !domain.shellElements().empty()) {
|
||||
if (!model.activeElements().empty() && !domain.ShellElements().empty()) {
|
||||
return recoveryFailure(
|
||||
"unsupported-mixed-element-model",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
"B33:FESA-MITC4",
|
||||
"Result recovery does not support mixed beam and shell models.");
|
||||
}
|
||||
if (domain.shellElements().size() >
|
||||
if (domain.ShellElements().size() >
|
||||
static_cast<std::size_t>(
|
||||
(std::numeric_limits<EntityIndex>::max)())) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-dimensions",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"The shell element count cannot be represented by stable element identities.");
|
||||
}
|
||||
for (std::size_t elementOrder = 0U;
|
||||
elementOrder < domain.shellElements().size();
|
||||
elementOrder < domain.ShellElements().size();
|
||||
++elementOrder) {
|
||||
const auto& definition = domain.shellElements()[elementOrder];
|
||||
if (definition.materialIndex >= domain.materials().size() ||
|
||||
definition.sectionIndex >= domain.shellSections().size()) {
|
||||
const auto& definition = domain.ShellElements()[elementOrder];
|
||||
if (definition.material_index >= domain.Materials().size() ||
|
||||
definition.section_index >= domain.ShellSections().size()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Active shell material and section references must resolve before recovery.");
|
||||
}
|
||||
try {
|
||||
const auto& scatter = dofs.shellElementScatter(
|
||||
static_cast<EntityIndex>(elementOrder));
|
||||
for (std::size_t nodePosition = 0U;
|
||||
nodePosition < definition.nodeIndices.size();
|
||||
nodePosition < definition.node_indices.size();
|
||||
++nodePosition) {
|
||||
const EntityIndex node = definition.nodeIndices[nodePosition];
|
||||
if (node >= domain.nodes().size()) {
|
||||
const EntityIndex node = definition.node_indices[nodePosition];
|
||||
if (node >= domain.Nodes().size()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Active shell node references must resolve before recovery.");
|
||||
}
|
||||
for (std::size_t component = 0U;
|
||||
@@ -339,7 +339,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-order",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Shell scatter must preserve node/component full-DOF order.");
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ Status validateRecoveryInputs(const AnalysisModel& model,
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Every active shell requires one twenty-four-DOF scatter map.");
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@ bool tryPositiveInteger(const std::string& text, std::int64_t& value) {
|
||||
Result<std::vector<EntityIndex>> resolveLoadTarget(const Domain& domain,
|
||||
const NodalLoad& load) {
|
||||
std::vector<const NodeSet*> sets;
|
||||
for (const auto& set : domain.nodeSets()) {
|
||||
for (const auto& set : domain.NodeSets()) {
|
||||
if (equalName(set.name, load.target)) {
|
||||
sets.push_back(&set);
|
||||
}
|
||||
@@ -389,8 +389,8 @@ Result<std::vector<EntityIndex>> resolveLoadTarget(const Domain& domain,
|
||||
std::vector<EntityIndex> nodes;
|
||||
std::int64_t sourceLabel = 0;
|
||||
if (tryPositiveInteger(load.target, sourceLabel)) {
|
||||
for (std::size_t node = 0U; node < domain.nodes().size(); ++node) {
|
||||
if (domain.nodes()[node].sourceId.source_label == sourceLabel) {
|
||||
for (std::size_t node = 0U; node < domain.Nodes().size(); ++node) {
|
||||
if (domain.Nodes()[node].source_id.source_label == sourceLabel) {
|
||||
nodes.push_back(static_cast<EntityIndex>(node));
|
||||
}
|
||||
}
|
||||
@@ -404,9 +404,9 @@ Result<std::vector<EntityIndex>> resolveLoadTarget(const Domain& domain,
|
||||
"A station-eligibility load target must resolve unambiguously.");
|
||||
}
|
||||
if (!sets.empty()) {
|
||||
std::vector<unsigned char> seen(domain.nodes().size(), 0U);
|
||||
for (const EntityIndex node : sets.front()->nodeIndices) {
|
||||
if (node >= domain.nodes().size() || seen[node] != 0U) {
|
||||
std::vector<unsigned char> seen(domain.Nodes().size(), 0U);
|
||||
for (const EntityIndex node : sets.front()->node_indices) {
|
||||
if (node >= domain.Nodes().size() || seen[node] != 0U) {
|
||||
return recoveryResultFailure<std::vector<EntityIndex>>(
|
||||
"invalid-node-station-entity",
|
||||
load.location,
|
||||
@@ -416,7 +416,7 @@ Result<std::vector<EntityIndex>> resolveLoadTarget(const Domain& domain,
|
||||
seen[node] = 1U;
|
||||
}
|
||||
return Result<std::vector<EntityIndex>>::Success(
|
||||
sets.front()->nodeIndices);
|
||||
sets.front()->node_indices);
|
||||
}
|
||||
if (!nodes.empty()) {
|
||||
return Result<std::vector<EntityIndex>>::Success(std::move(nodes));
|
||||
@@ -504,7 +504,7 @@ Status populateShellGlobalEvidence(
|
||||
double reactionForceScale = 0.0;
|
||||
double appliedMomentScale = 0.0;
|
||||
double reactionMomentScale = 0.0;
|
||||
for (std::size_t node = 0U; node < domain.nodes().size(); ++node) {
|
||||
for (std::size_t node = 0U; node < domain.Nodes().size(); ++node) {
|
||||
const std::size_t offset = node * kDofsPerNode;
|
||||
std::array<double, 3> nodalAppliedForce{};
|
||||
std::array<double, 3> nodalReactionForce{};
|
||||
@@ -524,9 +524,9 @@ Status populateShellGlobalEvidence(
|
||||
}
|
||||
|
||||
const auto appliedForceMoment =
|
||||
cross(domain.nodes()[node].coordinates, nodalAppliedForce);
|
||||
cross(domain.Nodes()[node].coordinates, nodalAppliedForce);
|
||||
const auto reactionForceMoment =
|
||||
cross(domain.nodes()[node].coordinates, nodalReactionForce);
|
||||
cross(domain.Nodes()[node].coordinates, nodalReactionForce);
|
||||
for (std::size_t component = 0U; component < 3U; ++component) {
|
||||
nodalAppliedMoment[component] += appliedForceMoment[component];
|
||||
nodalReactionMoment[component] += reactionForceMoment[component];
|
||||
@@ -541,8 +541,8 @@ Status populateShellGlobalEvidence(
|
||||
reactionMoment, reactionMomentScale, nodalReactionMoment)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
domain.nodes()[node].location,
|
||||
domain.nodes()[node].sourceId.source_label_text,
|
||||
domain.Nodes()[node].location,
|
||||
domain.Nodes()[node].source_id.source_label_text,
|
||||
"Global force and moment evidence must remain finite in source-node order.");
|
||||
}
|
||||
}
|
||||
@@ -569,7 +569,7 @@ Status populateShellGlobalEvidence(
|
||||
!finite(candidate.verificationMetrics)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
"global-equilibrium",
|
||||
"Global equilibrium values and their physical normalization scales must be finite.");
|
||||
}
|
||||
@@ -577,7 +577,7 @@ Status populateShellGlobalEvidence(
|
||||
momentMetric > kGlobalEquilibriumTolerance) {
|
||||
return recoveryFailure(
|
||||
"global-equilibrium-tolerance-failure",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
"global-equilibrium",
|
||||
"Normalized global force or moment balance exceeds 1e-10.");
|
||||
}
|
||||
@@ -586,8 +586,8 @@ Status populateShellGlobalEvidence(
|
||||
|
||||
std::optional<AxisSet> localAxes(const Domain& domain,
|
||||
const EulerBeam3DDefinition& element) {
|
||||
const auto& first = domain.nodes()[element.nodeIndices[0U]].coordinates;
|
||||
const auto& second = domain.nodes()[element.nodeIndices[1U]].coordinates;
|
||||
const auto& first = domain.Nodes()[element.node_indices[0U]].coordinates;
|
||||
const auto& second = domain.Nodes()[element.node_indices[1U]].coordinates;
|
||||
const std::array<double, 3> delta = {
|
||||
second[0U] - first[0U],
|
||||
second[1U] - first[1U],
|
||||
@@ -598,7 +598,7 @@ std::optional<AxisSet> localAxes(const Domain& domain,
|
||||
}
|
||||
const std::array<double, 3> ex = {
|
||||
delta[0U] / length, delta[1U] / length, delta[2U] / length};
|
||||
const auto& guide = domain.sections()[element.sectionIndex].firstAxis;
|
||||
const auto& guide = domain.Sections()[element.section_index].first_axis;
|
||||
const double projection = dot(guide, ex);
|
||||
const std::array<double, 3> eyTrial = {
|
||||
guide[0U] - projection * ex[0U],
|
||||
@@ -654,8 +654,8 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
if (!finite(internalForce)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
{model.domain().sourcePath(), 0U},
|
||||
model.domain().sourceContentIdentity(),
|
||||
{model.domain().SourcePath(), 0U},
|
||||
model.domain().SourceContentIdentity(),
|
||||
"Full stiffness multiplication must produce finite internal force.");
|
||||
}
|
||||
Vector residual{dofs.fullDofCount()};
|
||||
@@ -665,7 +665,7 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
if (!std::isfinite(residual[fullDof])) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
{model.domain().sourcePath(), 0U},
|
||||
{model.domain().SourcePath(), 0U},
|
||||
std::to_string(fullDof),
|
||||
"Internal-minus-external residual must remain finite.");
|
||||
}
|
||||
@@ -684,7 +684,7 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
if (!std::isfinite(residualNorm) || !std::isfinite(denominator)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
{model.domain().sourcePath(), 0U},
|
||||
{model.domain().SourcePath(), 0U},
|
||||
"free-residual",
|
||||
"Free residual and its physical normalization scale must be finite.");
|
||||
}
|
||||
@@ -699,7 +699,7 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
normalizedResidual > kFreeResidualTolerance) {
|
||||
return recoveryFailure(
|
||||
"free-residual-tolerance-failure",
|
||||
{model.domain().sourcePath(), 0U},
|
||||
{model.domain().SourcePath(), 0U},
|
||||
"free-residual",
|
||||
"The normalized free residual exceeds 1e-10.");
|
||||
}
|
||||
@@ -716,12 +716,12 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
gaussRows.reserve(model.activeElements().size() * 2U);
|
||||
const Domain& domain = model.domain();
|
||||
for (const EntityIndex elementIndex : model.activeElements()) {
|
||||
const auto& definition = domain.elements()[elementIndex];
|
||||
auto beam = EulerBeam3D::create(
|
||||
domain.nodes()[definition.nodeIndices[0U]],
|
||||
domain.nodes()[definition.nodeIndices[1U]],
|
||||
domain.sections()[definition.sectionIndex],
|
||||
domain.materials()[definition.materialIndex]);
|
||||
const auto& definition = domain.Elements()[elementIndex];
|
||||
auto beam = EulerBeam3D::Create(
|
||||
domain.Nodes()[definition.node_indices[0U]],
|
||||
domain.Nodes()[definition.node_indices[1U]],
|
||||
domain.Sections()[definition.section_index],
|
||||
domain.Materials()[definition.material_index]);
|
||||
if (!beam.HasValue()) {
|
||||
return beam.GetStatus();
|
||||
}
|
||||
@@ -735,52 +735,52 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
state.displacement()[scatter[localDof]];
|
||||
}
|
||||
const BeamRecovery recovered =
|
||||
beam.Value().recover(elementDisplacement);
|
||||
beam.Value().Recover(elementDisplacement);
|
||||
for (std::size_t endpoint = 0U; endpoint < 2U; ++endpoint) {
|
||||
if (!finite(recovered.equilibriumEndActions[endpoint]) ||
|
||||
!finite(recovered.endpointSectionResultants[endpoint])) {
|
||||
if (!finite(recovered.equilibrium_end_actions[endpoint]) ||
|
||||
!finite(recovered.endpoint_section_resultants[endpoint])) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Endpoint recovery values must be finite.");
|
||||
}
|
||||
endpointRows.push_back({
|
||||
elementIndex,
|
||||
static_cast<int>(endpoint),
|
||||
domain.nodes()[definition.nodeIndices[endpoint]].sourceId,
|
||||
recovered.equilibriumEndActions[endpoint],
|
||||
recovered.endpointSectionResultants[endpoint]});
|
||||
domain.Nodes()[definition.node_indices[endpoint]].source_id,
|
||||
recovered.equilibrium_end_actions[endpoint],
|
||||
recovered.endpoint_section_resultants[endpoint]});
|
||||
}
|
||||
for (std::size_t gauss = 0U; gauss < 2U; ++gauss) {
|
||||
if (!finite(recovered.gaussGeneralizedStrains[gauss]) ||
|
||||
!finite(recovered.gaussGeneralizedResultants[gauss])) {
|
||||
if (!finite(recovered.gauss_generalized_strains[gauss]) ||
|
||||
!finite(recovered.gauss_generalized_resultants[gauss])) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Gauss recovery values must be finite.");
|
||||
}
|
||||
gaussRows.push_back({
|
||||
elementIndex,
|
||||
static_cast<int>(gauss + 1U),
|
||||
recovered.gaussGeneralizedStrains[gauss],
|
||||
recovered.gaussGeneralizedResultants[gauss]});
|
||||
recovered.gauss_generalized_strains[gauss],
|
||||
recovered.gauss_generalized_resultants[gauss]});
|
||||
}
|
||||
for (const auto& point : recovered.stressPoints) {
|
||||
if ((point.gaussPoint != 1 && point.gaussPoint != 2) ||
|
||||
for (const auto& point : recovered.stress_points) {
|
||||
if ((point.gauss_point != 1 && point.gauss_point != 2) ||
|
||||
!std::isfinite(point.x1) || !std::isfinite(point.x2) ||
|
||||
!std::isfinite(point.s11)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Stress recovery identity and values must be finite and ordered.");
|
||||
}
|
||||
stressRows.push_back({
|
||||
elementIndex,
|
||||
point.gaussPoint,
|
||||
point.sectionPoint,
|
||||
point.gauss_point,
|
||||
point.section_point,
|
||||
point.x1,
|
||||
point.x2,
|
||||
point.s11,
|
||||
@@ -790,33 +790,33 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
|
||||
ShellStateCandidate shellCandidate{};
|
||||
std::vector<EntityIndex> expectedShellElements;
|
||||
if (!domain.shellElements().empty()) {
|
||||
if (domain.shellElements().size() >
|
||||
if (!domain.ShellElements().empty()) {
|
||||
if (domain.ShellElements().size() >
|
||||
(std::numeric_limits<std::size_t>::max)() /
|
||||
kShellLocationCount) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-dimensions",
|
||||
{domain.sourcePath(), 0U},
|
||||
domain.sourceContentIdentity(),
|
||||
{domain.SourcePath(), 0U},
|
||||
domain.SourceContentIdentity(),
|
||||
"The shell result-row inventory exceeds the addressable range.");
|
||||
}
|
||||
std::vector<std::optional<std::array<double, 3>>> directorsByNode(
|
||||
domain.nodes().size());
|
||||
for (const auto& frame : domain.shellNodeInitialFrames()) {
|
||||
if (frame.nodeIndex >= directorsByNode.size() ||
|
||||
directorsByNode[frame.nodeIndex].has_value()) {
|
||||
domain.Nodes().size());
|
||||
for (const auto& frame : domain.ShellNodeInitialFrames()) {
|
||||
if (frame.node_index >= directorsByNode.size() ||
|
||||
directorsByNode[frame.node_index].has_value()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
{domain.sourcePath(), 0U},
|
||||
std::to_string(frame.nodeIndex),
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(frame.node_index),
|
||||
"Shell initial directors must map uniquely to model nodes.");
|
||||
}
|
||||
directorsByNode[frame.nodeIndex] = frame.director;
|
||||
directorsByNode[frame.node_index] = frame.director;
|
||||
}
|
||||
|
||||
shellCandidate.rows.reserve(
|
||||
domain.shellElements().size() * kShellLocationCount);
|
||||
expectedShellElements.reserve(domain.shellElements().size());
|
||||
domain.ShellElements().size() * kShellLocationCount);
|
||||
expectedShellElements.reserve(domain.ShellElements().size());
|
||||
constexpr std::array<ShellMidsurfaceLocation, kShellLocationCount>
|
||||
locations{
|
||||
ShellMidsurfaceLocation::gp1,
|
||||
@@ -829,33 +829,33 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
ShellSectionPosition::top};
|
||||
constexpr std::array<double, 3> zeta{-1.0, 0.0, 1.0};
|
||||
for (std::size_t elementOrder = 0U;
|
||||
elementOrder < domain.shellElements().size();
|
||||
elementOrder < domain.ShellElements().size();
|
||||
++elementOrder) {
|
||||
const EntityIndex elementIndex =
|
||||
static_cast<EntityIndex>(elementOrder);
|
||||
const auto& definition = domain.shellElements()[elementOrder];
|
||||
const auto& definition = domain.ShellElements()[elementOrder];
|
||||
std::array<const Node*, 4> nodes{};
|
||||
std::array<std::array<double, 3>, 4> directors{};
|
||||
for (std::size_t nodePosition = 0U;
|
||||
nodePosition < definition.nodeIndices.size();
|
||||
nodePosition < definition.node_indices.size();
|
||||
++nodePosition) {
|
||||
const EntityIndex node = definition.nodeIndices[nodePosition];
|
||||
const EntityIndex node = definition.node_indices[nodePosition];
|
||||
if (!directorsByNode[node].has_value()) {
|
||||
return recoveryFailure(
|
||||
"invalid-recovery-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Shell recovery requires one initial director per element node.");
|
||||
}
|
||||
nodes[nodePosition] = &domain.nodes()[node];
|
||||
nodes[nodePosition] = &domain.Nodes()[node];
|
||||
directors[nodePosition] = *directorsByNode[node];
|
||||
}
|
||||
|
||||
auto shell = Mitc4Shell::create(
|
||||
auto shell = Mitc4Shell::Create(
|
||||
nodes,
|
||||
directors,
|
||||
domain.shellSections()[definition.sectionIndex],
|
||||
domain.materials()[definition.materialIndex]);
|
||||
domain.ShellSections()[definition.section_index],
|
||||
domain.Materials()[definition.material_index]);
|
||||
if (!shell.HasValue()) {
|
||||
return shell.GetStatus();
|
||||
}
|
||||
@@ -867,19 +867,19 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
elementDisplacement[localDof] =
|
||||
state.displacement()[scatter[localDof]];
|
||||
}
|
||||
auto recovered = shell.Value().recoverPhysical(
|
||||
auto recovered = shell.Value().RecoverPhysical(
|
||||
elementDisplacement);
|
||||
if (!recovered.HasValue()) {
|
||||
return recovered.GetStatus();
|
||||
}
|
||||
const double accumulatedEnergy =
|
||||
shellCandidate.physicalStrainEnergy +
|
||||
recovered.Value().strainEnergy;
|
||||
recovered.Value().strain_energy;
|
||||
if (!std::isfinite(accumulatedEnergy)) {
|
||||
return recoveryFailure(
|
||||
"nonfinite-recovery-value",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Source-order physical shell energy reduction must remain finite.");
|
||||
}
|
||||
shellCandidate.physicalStrainEnergy = accumulatedEnergy;
|
||||
@@ -892,20 +892,20 @@ Status ResultRecovery::recover(const AnalysisModel& model,
|
||||
ShellResultRow row{};
|
||||
row.element = elementIndex;
|
||||
row.location = locations[point];
|
||||
row.naturalCoordinates = physicalPoint.naturalCoordinates;
|
||||
row.naturalCoordinates = physicalPoint.natural_coordinates;
|
||||
row.localFrame = {
|
||||
physicalPoint.localFrame.e1,
|
||||
physicalPoint.localFrame.e2,
|
||||
physicalPoint.localFrame.e3};
|
||||
row.generalizedStrain = physicalPoint.generalizedStrain;
|
||||
row.sectionResultant = physicalPoint.sectionResultant;
|
||||
physicalPoint.local_frame.e1,
|
||||
physicalPoint.local_frame.e2,
|
||||
physicalPoint.local_frame.e3};
|
||||
row.generalizedStrain = physicalPoint.generalized_strain;
|
||||
row.sectionResultant = physicalPoint.section_resultant;
|
||||
for (std::size_t position = 0U;
|
||||
position < positions.size();
|
||||
++position) {
|
||||
row.stress[position] = {
|
||||
positions[position],
|
||||
zeta[position],
|
||||
physicalPoint.inPlaneStress[position]};
|
||||
physicalPoint.in_plane_stress[position]};
|
||||
}
|
||||
shellCandidate.rows.push_back(std::move(row));
|
||||
}
|
||||
@@ -951,7 +951,7 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
if (!std::isfinite(tolerance) || tolerance < 0.0) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"invalid-node-station-tolerance",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
"component-tolerances",
|
||||
"Node-station component tolerances must be finite and nonnegative.");
|
||||
}
|
||||
@@ -961,50 +961,50 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
endpointRows.size() != model.activeElements().size() * 2U) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"invalid-node-station-shape",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(endpointRows.size()),
|
||||
"Endpoint rows must contain exactly two rows per active element.");
|
||||
}
|
||||
|
||||
std::vector<std::vector<const EndpointResultRow*>> rowsByNode(
|
||||
domain.nodes().size());
|
||||
domain.Nodes().size());
|
||||
for (std::size_t order = 0U;
|
||||
order < model.activeElements().size();
|
||||
++order) {
|
||||
const EntityIndex elementIndex = model.activeElements()[order];
|
||||
if (elementIndex >= domain.elements().size()) {
|
||||
if (elementIndex >= domain.Elements().size()) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"invalid-node-station-entity",
|
||||
{domain.sourcePath(), 0U},
|
||||
{domain.SourcePath(), 0U},
|
||||
std::to_string(elementIndex),
|
||||
"Every active station element must be a valid stable entity.");
|
||||
}
|
||||
const auto& definition = domain.elements()[elementIndex];
|
||||
const auto& definition = domain.Elements()[elementIndex];
|
||||
for (std::size_t endpoint = 0U; endpoint < 2U; ++endpoint) {
|
||||
const auto& row = endpointRows[order * 2U + endpoint];
|
||||
const EntityIndex nodeIndex = definition.nodeIndices[endpoint];
|
||||
if (nodeIndex >= domain.nodes().size() ||
|
||||
const EntityIndex nodeIndex = definition.node_indices[endpoint];
|
||||
if (nodeIndex >= domain.Nodes().size() ||
|
||||
row.element != elementIndex ||
|
||||
row.endpoint != static_cast<int>(endpoint) ||
|
||||
!sameSourceIdentity(row.node, domain.nodes()[nodeIndex].sourceId)) {
|
||||
!sameSourceIdentity(row.node, domain.Nodes()[nodeIndex].source_id)) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"invalid-node-station-entity",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Endpoint rows must preserve active element, endpoint, and source-node order.");
|
||||
}
|
||||
if (!finite(row.sectionResultant)) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"nonfinite-node-station-value",
|
||||
definition.location,
|
||||
definition.sourceId.source_label_text,
|
||||
definition.source_id.source_label_text,
|
||||
"Node-station section resultants must be finite.");
|
||||
}
|
||||
rowsByNode[nodeIndex].push_back(&row);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> loadedNodes(domain.nodes().size(), 0U);
|
||||
std::vector<unsigned char> loadedNodes(domain.Nodes().size(), 0U);
|
||||
if (model.activeLoads().size() != model.step().loads.size()) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"invalid-node-station-entity",
|
||||
@@ -1042,7 +1042,7 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
}
|
||||
|
||||
std::vector<NodeStationResultRow> stations;
|
||||
stations.reserve(domain.nodes().size());
|
||||
stations.reserve(domain.Nodes().size());
|
||||
for (std::size_t nodeIndex = 0U;
|
||||
nodeIndex < rowsByNode.size();
|
||||
++nodeIndex) {
|
||||
@@ -1052,7 +1052,7 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
}
|
||||
if (incident.size() == 1U) {
|
||||
stations.push_back({
|
||||
domain.nodes()[nodeIndex].sourceId,
|
||||
domain.Nodes()[nodeIndex].source_id,
|
||||
incident.front()->element,
|
||||
incident.front()->sectionResultant});
|
||||
continue;
|
||||
@@ -1060,13 +1060,13 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
if (incident.size() != 2U || loadedNodes[nodeIndex] != 0U) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"ineligible-node-station",
|
||||
domain.nodes()[nodeIndex].location,
|
||||
domain.nodes()[nodeIndex].sourceId.source_label_text,
|
||||
domain.Nodes()[nodeIndex].location,
|
||||
domain.Nodes()[nodeIndex].source_id.source_label_text,
|
||||
"Interior station collapse requires exactly two unloaded endpoints.");
|
||||
}
|
||||
|
||||
const auto& firstElement = domain.elements()[incident[0U]->element];
|
||||
const auto& secondElement = domain.elements()[incident[1U]->element];
|
||||
const auto& firstElement = domain.Elements()[incident[0U]->element];
|
||||
const auto& secondElement = domain.Elements()[incident[1U]->element];
|
||||
const bool chainOrientation =
|
||||
incident[0U]->endpoint != incident[1U]->endpoint &&
|
||||
((incident[0U]->endpoint == 1 && incident[1U]->endpoint == 0) ||
|
||||
@@ -1074,13 +1074,13 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
const auto firstAxes = localAxes(domain, firstElement);
|
||||
const auto secondAxes = localAxes(domain, secondElement);
|
||||
if (!chainOrientation ||
|
||||
firstElement.sectionIndex != secondElement.sectionIndex ||
|
||||
firstElement.section_index != secondElement.section_index ||
|
||||
!firstAxes.has_value() || !secondAxes.has_value() ||
|
||||
!sameAxes(*firstAxes, *secondAxes)) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"ineligible-node-station",
|
||||
domain.nodes()[nodeIndex].location,
|
||||
domain.nodes()[nodeIndex].sourceId.source_label_text,
|
||||
domain.Nodes()[nodeIndex].location,
|
||||
domain.Nodes()[nodeIndex].source_id.source_label_text,
|
||||
"Interior station endpoints require one consistent section and local-axis chain.");
|
||||
}
|
||||
|
||||
@@ -1096,15 +1096,15 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
if (!std::isfinite(difference)) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"nonfinite-node-station-value",
|
||||
domain.nodes()[nodeIndex].location,
|
||||
domain.nodes()[nodeIndex].sourceId.source_label_text,
|
||||
domain.Nodes()[nodeIndex].location,
|
||||
domain.Nodes()[nodeIndex].source_id.source_label_text,
|
||||
"Endpoint comparison must produce a finite difference.");
|
||||
}
|
||||
if (difference > componentTolerances[component]) {
|
||||
return recoveryResultFailure<std::vector<NodeStationResultRow>>(
|
||||
"node-station-tolerance-failure",
|
||||
domain.nodes()[nodeIndex].location,
|
||||
domain.nodes()[nodeIndex].sourceId.source_label_text,
|
||||
domain.Nodes()[nodeIndex].location,
|
||||
domain.Nodes()[nodeIndex].source_id.source_label_text,
|
||||
"Interior endpoint resultants disagree beyond component tolerance.");
|
||||
}
|
||||
}
|
||||
@@ -1114,7 +1114,7 @@ ResultRecovery::normalizeSectionResultantsToNodeStations(
|
||||
? incident[0U]
|
||||
: incident[1U];
|
||||
stations.push_back({
|
||||
domain.nodes()[nodeIndex].sourceId,
|
||||
domain.Nodes()[nodeIndex].source_id,
|
||||
representative->element,
|
||||
representative->sectionResultant});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user