Connect MITC4 drilling evidence across analysis procedures
This commit is contained in:
@@ -48,7 +48,8 @@ Status CommitRecoveryCandidate(RecoveryCandidate candidate,
|
||||
!candidate.shell.rows.empty() ||
|
||||
candidate.shell.physical_strain_energy != 0.0 ||
|
||||
candidate.shell.equilibrium != zero_equilibrium ||
|
||||
candidate.shell.verification_metrics != zero_metrics;
|
||||
candidate.shell.verification_metrics != zero_metrics ||
|
||||
candidate.shell.mitc4_drilling.has_value();
|
||||
const bool has_complete_shell_inventory =
|
||||
!candidate.expected_shell_elements.empty() &&
|
||||
!candidate.shell.rows.empty();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "fesa/math/vector3.h"
|
||||
#include "results/mitc4_drilling_evidence.h"
|
||||
|
||||
namespace fesa::results_internal {
|
||||
namespace {
|
||||
@@ -243,11 +244,24 @@ Status RecoverShellGlobalEvidence(const Domain& domain, const DofManager& dofs,
|
||||
candidate.shell.equilibrium[component] = force_balance[component];
|
||||
candidate.shell.equilibrium[3U + component] = moment_balance[component];
|
||||
}
|
||||
Vector3 acceptance_moment = moment_balance;
|
||||
if (candidate.shell.mitc4_drilling) {
|
||||
CompleteDrillingEvidence(candidate.shell.equilibrium,
|
||||
&*candidate.shell.mitc4_drilling);
|
||||
if (!ValidDrillingEvidence(candidate.shell.mitc4_drilling,
|
||||
candidate.shell.equilibrium))
|
||||
return RecoveryFailure("invalid-shell-drilling-evidence",
|
||||
{domain.SourcePath(), 0U}, "global-equilibrium",
|
||||
"Shell drilling diagnostics must be finite and consistent.");
|
||||
if (candidate.shell.mitc4_drilling->mode == Mitc4DrillingMode::kDirectSpring)
|
||||
acceptance_moment = moment_balance -
|
||||
Vector3(candidate.shell.mitc4_drilling->drilling_moment);
|
||||
}
|
||||
const double force_metric =
|
||||
NormalizedBalance(force_balance.Components(),
|
||||
(std::max)(applied_force_scale, reaction_force_scale));
|
||||
const double moment_metric = NormalizedBalance(
|
||||
moment_balance.Components(),
|
||||
acceptance_moment.Components(),
|
||||
(std::max)(applied_moment_scale, reaction_moment_scale));
|
||||
candidate.shell.verification_metrics = {global.normalized_free_residual,
|
||||
force_metric, moment_metric};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef FESA_RESULTS_MITC4_DRILLING_EVIDENCE_H_
|
||||
#define FESA_RESULTS_MITC4_DRILLING_EVIDENCE_H_
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
|
||||
#include "fesa/results/result_records.h"
|
||||
|
||||
namespace fesa::results_internal {
|
||||
|
||||
inline bool ValidDrillingMode(const Mitc4DrillingMode mode) {
|
||||
return mode == Mitc4DrillingMode::kDirectSpring ||
|
||||
mode == Mitc4DrillingMode::kLegacyCorotatedTwist;
|
||||
}
|
||||
|
||||
/// @brief Validates exact raw-minus-internal diagnostics without a tolerance.
|
||||
inline bool ValidDrillingEvidence(
|
||||
const std::optional<Mitc4DrillingEvidence>& evidence,
|
||||
const std::array<double, 6>& raw) {
|
||||
if (!evidence) return true; // Older manually constructed fixtures.
|
||||
if (!ValidDrillingMode(evidence->mode)) return false;
|
||||
for (std::size_t i = 0U; i < 6U; ++i) {
|
||||
const double expected = i < 3U ? raw[i]
|
||||
: raw[i] - evidence->drilling_moment[i - 3U];
|
||||
if (!std::isfinite(raw[i]) || !std::isfinite(expected) ||
|
||||
!std::isfinite(evidence->equilibrium_with_drilling[i]) ||
|
||||
evidence->equilibrium_with_drilling[i] != expected)
|
||||
return false;
|
||||
}
|
||||
for (const double value : evidence->drilling_moment)
|
||||
if (!std::isfinite(value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SameDrillingInventory(
|
||||
const std::optional<Mitc4DrillingEvidence>& left,
|
||||
const std::optional<Mitc4DrillingEvidence>& right) {
|
||||
return left.has_value() == right.has_value() &&
|
||||
(!left || left->mode == right->mode);
|
||||
}
|
||||
|
||||
/// @brief Keeps force balance raw and subtracts positive artificial moment once.
|
||||
inline void CompleteDrillingEvidence(
|
||||
const std::array<double, 6>& raw, Mitc4DrillingEvidence* evidence) {
|
||||
evidence->equilibrium_with_drilling = raw;
|
||||
for (std::size_t i = 0U; i < 3U; ++i)
|
||||
evidence->equilibrium_with_drilling[3U + i] -= evidence->drilling_moment[i];
|
||||
}
|
||||
|
||||
} // namespace fesa::results_internal
|
||||
|
||||
#endif // FESA_RESULTS_MITC4_DRILLING_EVIDENCE_H_
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include "results/mitc4_drilling_evidence.h"
|
||||
|
||||
namespace fesa::results_internal {
|
||||
|
||||
bool IsFiniteShellRow(const ShellResultRow& row) {
|
||||
@@ -29,6 +31,27 @@ Status ShellResultRecovery(const SourceLocation& location,
|
||||
const EntityIndex expected_element,
|
||||
const ShellElementResultRows& rows,
|
||||
RecoveryCandidate& candidate) {
|
||||
if ((rows.drilling_mode && !ValidDrillingMode(*rows.drilling_mode)) ||
|
||||
!IsFiniteArray(rows.drilling_moment) ||
|
||||
(candidate.has_shell_results &&
|
||||
(candidate.shell.mitc4_drilling.has_value() != rows.drilling_mode.has_value() ||
|
||||
(rows.drilling_mode &&
|
||||
candidate.shell.mitc4_drilling->mode != *rows.drilling_mode)))) {
|
||||
return RecoveryFailure("invalid-shell-drilling-evidence", location,
|
||||
source_id.source_label_text,
|
||||
"Shell recovery requires one finite actual drilling mode.");
|
||||
}
|
||||
if (rows.drilling_mode) {
|
||||
if (!candidate.shell.mitc4_drilling)
|
||||
candidate.shell.mitc4_drilling = Mitc4DrillingEvidence{*rows.drilling_mode};
|
||||
for (std::size_t i = 0U; i < 3U; ++i) {
|
||||
candidate.shell.mitc4_drilling->drilling_moment[i] += rows.drilling_moment[i];
|
||||
if (!std::isfinite(candidate.shell.mitc4_drilling->drilling_moment[i]))
|
||||
return RecoveryFailure("nonfinite-recovery-value", location,
|
||||
source_id.source_label_text,
|
||||
"Source-ordered drilling moment overflowed.");
|
||||
}
|
||||
}
|
||||
const double accumulated_energy =
|
||||
candidate.shell.physical_strain_energy + rows.physical_strain_energy;
|
||||
if (!std::isfinite(rows.physical_strain_energy) ||
|
||||
|
||||
Reference in New Issue
Block a user