feat(analysis): implement Hex8 solid static procedures

This commit is contained in:
KOKO\Mimi
2026-10-09 02:18:20 +09:00
parent ca806100c9
commit 7a527e88e5
6 changed files with 1639 additions and 0 deletions
@@ -0,0 +1,39 @@
#ifndef FESA_ANALYSIS_SOLID_STATIC_PROCEDURE_H_
#define FESA_ANALYSIS_SOLID_STATIC_PROCEDURE_H_
#include "fesa/analysis/solid_static_state.h"
namespace fesa {
class LinearSolver;
class ParallelFor;
class TangentSolver;
/// @brief Owns successful static frames and sorted model diagnostics.
struct SolidStaticExecutionResult {
SolidStaticState state;
std::vector<Diagnostic> diagnostics;
};
/// @brief Executes linear K0 or fixed-factor TL StVK static analysis.
class SolidStaticProcedureExecutor {
public:
/// @brief Uses non-owned adapters, which must outlive this executor.
/// @param tangent_solver Must support indefinite stressed tangents.
SolidStaticProcedureExecutor(const ParallelFor& parallel_for,
LinearSolver& linear_solver,
TangentSolver& tangent_solver);
/// @brief Returns validated results; no I/O or final-file replacement.
Result<SolidStaticExecutionResult> Execute(const Domain& domain) const;
/// @brief Executes into a fresh observer retaining accepted history on
/// failure.
/// @note A previously initialized observer is rejected without mutation.
Status ExecuteInto(const Domain& domain, SolidStaticState& state) const;
private:
const ParallelFor& parallel_for_;
LinearSolver& linear_solver_;
TangentSolver& tangent_solver_;
};
} // namespace fesa
#endif // FESA_ANALYSIS_SOLID_STATIC_PROCEDURE_H_
+115
View File
@@ -0,0 +1,115 @@
#ifndef FESA_ANALYSIS_SOLID_STATIC_STATE_H_
#define FESA_ANALYSIS_SOLID_STATIC_STATE_H_
#include <array>
#include <cstdint>
#include <string>
#include <vector>
#include "fesa/analysis/nonlinear_static_control.h"
#include "fesa/results/solid_result_records.h"
namespace fesa {
/// @brief Keeps raw current-arm balance and its free-residual explanation.
/// @note Internal evidence only; no additional persistent result fields.
struct SolidStaticBalanceEvidence {
std::array<double, 3> internal_force_sum{};
std::array<double, 3> reference_internal_moment{};
std::array<double, 3> current_internal_moment{};
std::array<double, 3> free_residual_moment{};
std::array<double, 3> linearization_moment{};
std::array<double, 3> internal_force_scale{};
std::array<double, 3> reference_moment_scale{};
std::array<double, 3> current_moment_scale{};
};
/// @brief Owns a complete accepted static frame in stable node/source order.
/// @note Vectors are node-major UX/UY/UZ; reaction is constrained residual.
struct SolidStaticFrame {
std::uint32_t frame_index{0U};
std::uint32_t increment_index{0U};
double load_factor{0.0};
std::uint32_t iteration_count{0U};
bool is_factor_one{false};
std::vector<EntityIndex> nodal_internal_order;
std::vector<SourceEntityId> nodal_source_ids;
Vector displacement{0U};
Vector internal_force{0U};
Vector external_force{0U};
Vector residual{0U};
Vector reaction{0U};
std::vector<SolidIntegrationPointRow> solid_results;
double physical_strain_energy{0.0};
// Applied plus support forces, then moments about global zero at X+u.
std::array<double, 6> global_equilibrium{};
SolidStaticBalanceEvidence balance;
};
/// @brief Records two physical static channels, including failed iterations.
struct SolidStaticIterationRecord {
std::uint32_t increment_index{0U};
double load_factor{0.0};
std::uint32_t iteration{0U};
NewtonChannelDecision force_residual{"residual_force",
0.0,
0.0,
NewtonConvergenceBranch::kZeroScale,
kNewtonZeroScaleThreshold,
NewtonChannelUnit::kForce,
false};
NewtonChannelDecision translation_correction{
"correction_translation",
0.0,
0.0,
NewtonConvergenceBranch::kZeroScale,
kNewtonZeroScaleThreshold,
NewtonChannelUnit::kLength,
false};
bool convergence_evaluated{false};
bool accepted{false};
std::string diagnostic_code;
std::string stage;
std::string failure_reason;
};
/// @brief Evaluates translation-only static criteria with input force/length.
/// @note Exact-zero external force selects the absolute residual branch.
Result<SolidStaticIterationRecord> EvaluateSolidStaticConvergence(
const Vector& residual, const Vector& internal, const Vector& external,
const Vector& correction, const Vector& increment);
/// @brief Owns committed static state independently of caller trial work.
class SolidStaticState {
public:
/// @brief Creates an uninitialized observer usable with ExecuteInto().
SolidStaticState() = default;
/// @brief Copies immutable source inventory and the zero-factor baseline.
static Result<SolidStaticState> Create(const Domain& domain,
const DofManager& dofs);
/// @brief Validates complete recovery, then appends and replaces atomically.
/// @note The executor certifies trial geometry before this state boundary.
Status CommitAcceptedFrame(const SolidStaticFrame& frame);
/// @brief Returns authoritative accepted frames; baseline is not a frame.
const std::vector<SolidStaticFrame>& AcceptedFrames() const noexcept;
/// @brief Returns baseline or the most recently accepted complete state.
const SolidStaticFrame& CommittedState() const noexcept;
/// @brief Returns all iteration evidence, including the final failed trial.
const std::vector<SolidStaticIterationRecord>& IterationRecords()
const noexcept;
private:
friend class SolidStaticProcedureExecutor;
bool initialized_{false};
bool nonlinear_{false};
std::vector<SolidIntegrationPointRow> reference_points_;
std::vector<std::size_t> constrained_dofs_;
Vector prescribed_values_{0U};
SolidStaticFrame committed_;
std::vector<SolidStaticFrame> accepted_frames_;
std::vector<SolidStaticIterationRecord> iterations_;
};
} // namespace fesa
#endif // FESA_ANALYSIS_SOLID_STATIC_STATE_H_