Integrate Refactor solver sources and dual MSVC CMake builds

This commit is contained in:
KOKO\Mimi
2026-10-18 02:10:51 +09:00
parent 7ee32e5837
commit 12d51480de
218 changed files with 17842 additions and 9689 deletions
@@ -0,0 +1,23 @@
#ifndef FESA_ANALYSIS_ANALYSIS_PROCEDURE_H_
#define FESA_ANALYSIS_ANALYSIS_PROCEDURE_H_
#include "fesa/analysis/prepared_analysis_outcome.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
/// @brief Executes one prepared Domain without opening result files.
/// @note The Domain and injected adapters outlive Execute. Accepted histories
/// remain procedure-specific and are returned only after validation.
class AnalysisProcedure {
public:
virtual ~AnalysisProcedure() = default;
/// @brief Returns the original typed completed payload or first failure.
virtual Result<PreparedAnalysisOutcome> Execute(const Domain& domain) = 0;
};
} // namespace fesa
#endif // FESA_ANALYSIS_ANALYSIS_PROCEDURE_H_
+2 -1
View File
@@ -6,12 +6,13 @@
#include <vector>
#include "fesa/core/status.h"
#include "fesa/fem/dof_manager.h"
#include "fesa/math/vector.h"
#include "fesa/results/result_records.h"
namespace fesa {
class DofManager;
/// @brief Owns mutable quantities required by the V0 linear-static frame.
class AnalysisState {
public:
@@ -0,0 +1,19 @@
#ifndef FESA_ANALYSIS_DYNAMIC_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_DYNAMIC_EXECUTION_RESULT_H_
#include <vector>
#include "fesa/analysis/dynamic_analysis_state.h"
#include "fesa/core/diagnostic.h"
namespace fesa {
/// @brief Stores a complete HHT history before atomic result finalization.
struct DynamicExecutionResult {
DynamicAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
} // namespace fesa
#endif // FESA_ANALYSIS_DYNAMIC_EXECUTION_RESULT_H_
+1 -1
View File
@@ -8,7 +8,7 @@
#include <vector>
#include "fesa/math/matrix.h"
#include "fesa/solvers/eigen/mkl_feast_eigen_solver.h"
#include "fesa/solvers/eigen/eigen_solver.h"
namespace fesa {
@@ -1,10 +1,14 @@
#ifndef FESA_ANALYSIS_HHT_DYNAMIC_PROCEDURE_H_
#define FESA_ANALYSIS_HHT_DYNAMIC_PROCEDURE_H_
#include "fesa/analysis/prepared_analysis.h"
#include "fesa/analysis/dynamic_execution_result.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
class LinearSolver;
class NewtonIterationLogWriter;
class ParallelFor;
class TangentSolver;
@@ -6,13 +6,23 @@
namespace fesa {
class Domain;
class EigenSolver;
/// @brief Executes the supported linear MITC4 frequency procedure.
class LinearFrequencyProcedureExecutor final {
public:
/// @brief Preserves default FEAST construction for existing callers.
LinearFrequencyProcedureExecutor() = default;
/// @brief Borrows a solver that must outlive this executor and its calls.
explicit LinearFrequencyProcedureExecutor(const EigenSolver& solver) : solver_(&solver) {}
/// @brief Builds, solves, and validates one frequency modal candidate.
/// @return Requested physical modes plus all-c validation evidence.
Result<EigenAnalysisState> Execute(const Domain& domain) const;
private:
const EigenSolver* solver_{nullptr};
};
} // namespace fesa
@@ -0,0 +1,19 @@
#ifndef FESA_ANALYSIS_LINEAR_STATIC_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_LINEAR_STATIC_EXECUTION_RESULT_H_
#include <vector>
#include "fesa/analysis/analysis_state.h"
#include "fesa/core/diagnostic.h"
namespace fesa {
/// @brief Stores a completed linear-static calculation before result writing.
struct LinearStaticExecutionResult {
AnalysisState state;
std::vector<Diagnostic> diagnostics;
};
} // namespace fesa
#endif // FESA_ANALYSIS_LINEAR_STATIC_EXECUTION_RESULT_H_
@@ -1,10 +1,13 @@
#ifndef FESA_ANALYSIS_LINEAR_STATIC_PROCEDURE_H_
#define FESA_ANALYSIS_LINEAR_STATIC_PROCEDURE_H_
#include "fesa/analysis/prepared_analysis.h"
#include "fesa/analysis/linear_static_execution_result.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
class LinearSolver;
class ParallelFor;
@@ -0,0 +1,20 @@
#ifndef FESA_ANALYSIS_NONLINEAR_STATIC_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_NONLINEAR_STATIC_EXECUTION_RESULT_H_
#include <vector>
#include "fesa/analysis/nonlinear_analysis_state.h"
#include "fesa/core/diagnostic.h"
namespace fesa {
/// @brief Stores a completed nonlinear-static calculation before result
/// writing.
struct NonlinearStaticExecutionResult {
NonlinearAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
} // namespace fesa
#endif // FESA_ANALYSIS_NONLINEAR_STATIC_EXECUTION_RESULT_H_
@@ -1,10 +1,13 @@
#ifndef FESA_ANALYSIS_NONLINEAR_STATIC_PROCEDURE_H_
#define FESA_ANALYSIS_NONLINEAR_STATIC_PROCEDURE_H_
#include "fesa/analysis/prepared_analysis.h"
#include "fesa/analysis/nonlinear_static_execution_result.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
class NewtonIterationLogWriter;
class ParallelFor;
class TangentSolver;
+19 -32
View File
@@ -2,23 +2,21 @@
#define FESA_ANALYSIS_PREPARED_ANALYSIS_H_
#include <filesystem>
#include <variant>
#include <memory>
#include <vector>
#include "fesa/analysis/analysis_state.h"
#include "fesa/analysis/dynamic_analysis_state.h"
#include "fesa/analysis/eigen_analysis_state.h"
#include "fesa/analysis/nonlinear_analysis_state.h"
#include "fesa/analysis/solid_frequency_state.h"
#include "fesa/analysis/solid_hht_dynamic_procedure.h"
#include "fesa/analysis/solid_static_procedure.h"
#include "fesa/analysis/transient_heat_procedure.h"
#include "fesa/analysis/analysis_procedure.h"
#include "fesa/analysis/prepared_analysis_outcome.h"
#include "fesa/core/diagnostic.h"
#include "fesa/core/status.h"
#include "fesa/model/domain.h"
namespace fesa {
class ParallelFor;
class LinearSolver;
class TangentSolver;
class EigenSolver;
class LinearStaticProcedureExecutor;
class LinearFrequencyProcedureExecutor;
class EigenResultsWriter;
@@ -31,6 +29,9 @@ class DynamicResultsWriter;
class ThermalResultsWriter;
class SolidResultsWriter;
class SolidFrequencyProcedureExecutor;
class SolidStaticProcedureExecutor;
class SolidHhtDynamicProcedureExecutor;
class TransientHeatProcedureExecutor;
struct DerivedOutputPaths;
/// @brief Owns one parsed and semantically mapped analysis input.
@@ -46,30 +47,16 @@ struct PreparedAnalysisInput {
Result<PreparedAnalysisInput> PrepareAnalysisInput(
const std::filesystem::path& input_path);
/// @brief Stores a completed linear-static calculation before result writing.
struct LinearStaticExecutionResult {
AnalysisState state;
std::vector<Diagnostic> diagnostics;
};
/// @brief Creates exactly one selected family with caller-owned adapters.
/// @note Domain and adapters remain alive and unmoved throughout execution.
Result<std::unique_ptr<AnalysisProcedure>> CreateAnalysisProcedure(
const Domain &domain, const ParallelFor &parallel_for,
LinearSolver &linear_solver, TangentSolver &tangent_solver,
const EigenSolver &eigen_solver, NewtonIterationLogWriter &log);
/// @brief Stores a completed nonlinear-static calculation before result
/// writing.
struct NonlinearStaticExecutionResult {
NonlinearAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
/// @brief Stores a complete HHT history before atomic result finalization.
struct DynamicExecutionResult {
DynamicAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
using PreparedAnalysisOutcome =
std::variant<LinearStaticExecutionResult, NonlinearStaticExecutionResult,
EigenAnalysisState, DynamicExecutionResult,
ThermalExecutionResult, SolidStaticExecutionResult,
SolidFrequencyState, SolidDynamicExecutionResult>;
/// @brief Executes a caller-selected procedure through the common interface.
Result<PreparedAnalysisOutcome>
ExecutePreparedAnalysis(const Domain &domain, AnalysisProcedure &procedure);
/// @brief Selects the approved procedure from a prepared Domain.
/// @pre The executors and log outlive this call.
@@ -0,0 +1,26 @@
#ifndef FESA_ANALYSIS_PREPARED_ANALYSIS_OUTCOME_H_
#define FESA_ANALYSIS_PREPARED_ANALYSIS_OUTCOME_H_
#include <variant>
#include "fesa/analysis/dynamic_execution_result.h"
#include "fesa/analysis/eigen_analysis_state.h"
#include "fesa/analysis/linear_static_execution_result.h"
#include "fesa/analysis/nonlinear_static_execution_result.h"
#include "fesa/analysis/solid_dynamic_execution_result.h"
#include "fesa/analysis/solid_frequency_state.h"
#include "fesa/analysis/solid_static_execution_result.h"
#include "fesa/analysis/thermal_execution_result.h"
namespace fesa {
/// @brief Owns a completed procedure result before result-file finalization.
using PreparedAnalysisOutcome =
std::variant<LinearStaticExecutionResult, NonlinearStaticExecutionResult,
EigenAnalysisState, DynamicExecutionResult,
ThermalExecutionResult, SolidStaticExecutionResult,
SolidFrequencyState, SolidDynamicExecutionResult>;
} // namespace fesa
#endif // FESA_ANALYSIS_PREPARED_ANALYSIS_OUTCOME_H_
@@ -0,0 +1,17 @@
#ifndef FESA_ANALYSIS_SOLID_DYNAMIC_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_SOLID_DYNAMIC_EXECUTION_RESULT_H_
#include "fesa/analysis/solid_dynamic_analysis_state.h"
#include "fesa/fem/dof_manager.h"
namespace fesa {
/// @brief Owns the validated 3N dynamic result independently of serialization.
struct SolidDynamicExecutionResult {
DofManager dofs;
SolidDynamicAnalysisState state;
};
} // namespace fesa
#endif // FESA_ANALYSIS_SOLID_DYNAMIC_EXECUTION_RESULT_H_
@@ -5,14 +5,24 @@
namespace fesa {
class Domain;
class EigenSolver;
/// @brief Executes unloaded reference-state C3D8 generalized frequency
/// analysis.
class SolidFrequencyProcedureExecutor final {
public:
/// @brief Preserves default FEAST construction for existing callers.
SolidFrequencyProcedureExecutor() = default;
/// @brief Borrows a solver that must outlive this executor and its calls.
explicit SolidFrequencyProcedureExecutor(const EigenSolver& solver) : solver_(&solver) {}
/// @brief Returns lowest requested modes after validating every returned
/// pair.
/// @note Domain is immutable and must remain alive during execution.
Result<SolidFrequencyState> Execute(const Domain& domain) const;
private:
const EigenSolver* solver_{nullptr};
};
} // namespace fesa
#endif // FESA_ANALYSIS_SOLID_FREQUENCY_PROCEDURE_H_
@@ -8,7 +8,7 @@
#include <vector>
#include "fesa/math/matrix.h"
#include "fesa/solvers/eigen/mkl_feast_eigen_solver.h"
#include "fesa/solvers/eigen/eigen_solver.h"
namespace fesa {
/// @brief Identifies a source-ordered physical Solid eigenmode.
@@ -1,19 +1,13 @@
#ifndef FESA_ANALYSIS_SOLID_HHT_DYNAMIC_PROCEDURE_H_
#define FESA_ANALYSIS_SOLID_HHT_DYNAMIC_PROCEDURE_H_
#include "fesa/analysis/solid_dynamic_analysis_state.h"
#include "fesa/analysis/solid_dynamic_execution_result.h"
namespace fesa {
class LinearSolver;
class ParallelFor;
class TangentSolver;
/// @brief Owns the validated 3N dynamic result independently of serialization.
struct SolidDynamicExecutionResult {
DofManager dofs;
SolidDynamicAnalysisState state;
};
/// @brief Integrates linear or TL Solid mechanics with constant consistent
/// mass.
class SolidHhtDynamicProcedureExecutor {
@@ -0,0 +1,19 @@
#ifndef FESA_ANALYSIS_SOLID_STATIC_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_SOLID_STATIC_EXECUTION_RESULT_H_
#include <vector>
#include "fesa/analysis/solid_static_state.h"
#include "fesa/core/diagnostic.h"
namespace fesa {
/// @brief Owns successful static frames and sorted model diagnostics.
struct SolidStaticExecutionResult {
SolidStaticState state;
std::vector<Diagnostic> diagnostics;
};
} // namespace fesa
#endif // FESA_ANALYSIS_SOLID_STATIC_EXECUTION_RESULT_H_
@@ -1,19 +1,13 @@
#ifndef FESA_ANALYSIS_SOLID_STATIC_PROCEDURE_H_
#define FESA_ANALYSIS_SOLID_STATIC_PROCEDURE_H_
#include "fesa/analysis/solid_static_state.h"
#include "fesa/analysis/solid_static_execution_result.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:
+1 -1
View File
@@ -99,7 +99,7 @@ class SolidStaticState {
const noexcept;
private:
friend class SolidStaticProcedureExecutor;
friend class SolidStaticCore;
bool initialized_{false};
bool nonlinear_{false};
std::vector<SolidIntegrationPointRow> reference_points_;
@@ -6,11 +6,15 @@
#include <vector>
#include "fesa/analysis/thermal_time_grid.h"
#include "fesa/assembly/thermal_assembler.h"
#include "fesa/core/status.h"
#include "fesa/results/thermal_result_records.h"
namespace fesa {
class AnalysisModel;
class DofManager;
class ThermalAssembly;
/// @brief Owns the immutable thermal result inventory and accepted history.
/// @note No Domain/model/assembly references survive Create; state may outlive
/// them. Numerical equilibrium and energy checks belong to the procedure before
@@ -0,0 +1,19 @@
#ifndef FESA_ANALYSIS_THERMAL_EXECUTION_RESULT_H_
#define FESA_ANALYSIS_THERMAL_EXECUTION_RESULT_H_
#include <vector>
#include "fesa/analysis/thermal_analysis_state.h"
#include "fesa/core/diagnostic.h"
namespace fesa {
/// @brief Owns complete thermal history before any result output is opened.
struct ThermalExecutionResult {
ThermalAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
} // namespace fesa
#endif // FESA_ANALYSIS_THERMAL_EXECUTION_RESULT_H_
@@ -1,21 +1,14 @@
#ifndef FESA_ANALYSIS_TRANSIENT_HEAT_PROCEDURE_H_
#define FESA_ANALYSIS_TRANSIENT_HEAT_PROCEDURE_H_
#include <vector>
#include "fesa/analysis/thermal_analysis_state.h"
#include "fesa/analysis/thermal_execution_result.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
class LinearSolver;
class ParallelFor;
/// @brief Owns complete thermal history before any result output is opened.
struct ThermalExecutionResult {
ThermalAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
/// @brief Executes fixed-increment backward Euler with checked thermal
/// recovery.
class TransientHeatProcedureExecutor final {
+2 -1
View File
@@ -30,7 +30,8 @@ class LoadAssembler {
double step_time = 0.0);
/// @brief Forms Ff-Kfc*dc in stable free/constrained order.
/// @note This operation neither factorizes nor invokes a solver.
/// @note Compatibility facade delegates to EssentialConstraintPolicy; this
/// operation neither factorizes nor invokes a solver.
static Result<Vector> EffectiveFreeRhs(const Vector& full_load,
const SparseMatrix& kfc,
const Vector& prescribed_values,
@@ -2,10 +2,12 @@
#define FESA_ASSEMBLY_THERMAL_ASSEMBLER_H_
#include <array>
#include <memory>
#include <vector>
#include "fesa/analysis/analysis_model.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/elements/element_capabilities.h"
#include "fesa/elements/thermal_shell.h"
#include "fesa/fem/dof_manager.h"
#include "fesa/math/sparse_matrix.h"
@@ -50,6 +52,8 @@ class ThermalAssembly final {
const std::vector<EntityIndex>& ElementOrder() const noexcept;
/// @brief Returns checked kernels in stable active element order.
const std::vector<ThermalShell>& Kernels() const noexcept;
/// @brief Returns typed views bound after the final kernel buffer is placed.
const std::vector<std::unique_ptr<ThermalElement>>& Elements() const noexcept;
/// @brief Returns node-major twenty-entry full DOF scatters in kernel order.
const std::vector<std::array<std::size_t, 20>>& Scatters() const noexcept;
/// @brief Checks source Domain identity and the complete supplied equation
@@ -79,7 +83,10 @@ class ThermalAssembly final {
SparseMatrix capacity_error_;
Vector input_error_;
std::vector<EntityIndex> element_order_;
// Never resized after construction. Moving the owning vector transfers its
// buffer, so bound references survive ThermalAssembly moves.
std::vector<ThermalShell> kernels_;
std::vector<std::unique_ptr<ThermalElement>> elements_;
std::vector<std::array<std::size_t, 20>> scatters_;
};
@@ -24,6 +24,16 @@ class EssentialConstraintPolicy {
Result<PartitionedStiffness> Partition(const SparseMatrix& full_stiffness,
const DofManager& dof_manager) const;
/// @brief Forms Ff-Kfc*dc in stable free/constrained order.
/// @return A finite RHS candidate or the established load diagnostic.
/// @note Preserves independent CSR products and ordered row reductions;
/// no factorization or solver operation is performed. Inputs are borrowed
/// only for this call and remain unchanged on failure.
Result<Vector> EffectiveFreeRhs(const Vector& full_load,
const SparseMatrix& kfc,
const Vector& prescribed_values,
const DofManager& dofs) const;
/// @brief Gathers a full vector in stable free-equation order.
Vector GatherFree(const Vector& full_values,
const DofManager& dof_manager) const;
@@ -5,7 +5,7 @@
#include "fesa/constraints/boundary_condition.h"
#include "fesa/core/diagnostic.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_dof_layout.h"
#include "fesa/model/source_target_resolver.h"
namespace fesa {
+6
View File
@@ -2,6 +2,7 @@
#define FESA_CORE_ASCII_H_
#include <cstdint>
#include <string>
#include <string_view>
#include "fesa/core/status.h"
@@ -12,6 +13,11 @@ namespace fesa {
/// @return The lowercase ASCII byte, or the input byte when it is not A-Z.
char AsciiLower(char value) noexcept;
/// @brief Returns an uppercase ASCII copy without changing other source bytes.
/// @note Embedded nulls and non-ASCII bytes are preserved without locale
/// folding.
std::string AsciiUppercase(std::string value);
/// @brief Compares two byte strings with ASCII-only case folding.
/// @return True when the strings have equal length and equal ASCII-folded
/// bytes.
+8
View File
@@ -24,6 +24,14 @@ struct SourceEntityId {
std::string source_label_text;
};
/// @brief Compares all preserved source fields without canonicalizing spelling.
inline bool SourceIdentityEquals(const SourceEntityId& left,
const SourceEntityId& right) noexcept {
return left.instance_name == right.instance_name &&
left.source_label == right.source_label &&
left.source_label_text == right.source_label_text;
}
} // namespace fesa
#endif // FESA_CORE_SOURCE_IDENTITY_H_
+2 -2
View File
@@ -98,11 +98,11 @@ class Result {
struct FailureTag {};
/// @brief Constructs the successful value alternative.
Result(SuccessTag, T value)
Result(SuccessTag, T&& value)
: value_{std::move(value)}, status_{Status::Ok()} {}
/// @brief Constructs the failed status alternative.
Result(FailureTag, Status status)
Result(FailureTag, Status&& status)
: value_{std::nullopt}, status_{std::move(status)} {}
std::optional<T> value_;
+1 -24
View File
@@ -1,13 +1,11 @@
#ifndef FESA_ELEMENTS_ELEMENT_H_
#define FESA_ELEMENTS_ELEMENT_H_
#include <cstdint>
#include <functional>
#include <variant>
#include <vector>
#include "fesa/core/source_identity.h"
#include "fesa/core/status.h"
#include "fesa/elements/element_dof_layout.h"
#include "fesa/math/matrix.h"
#include "fesa/math/vector.h"
#include "fesa/results/result_records.h"
@@ -15,23 +13,6 @@
namespace fesa {
/// @brief Identifies one component in the stable six-DOF node layout.
enum class DofComponent : std::uint8_t {
kUx,
kUy,
kUz,
kUrx,
kUry,
kUrz,
};
/// @brief Describes one runtime element's stable node and component order.
struct ElementDofLayout {
SourceEntityId source_id;
std::vector<EntityIndex> node_indices;
std::vector<DofComponent> components_per_node;
};
/// @brief Carries one element-local stiffness in its declared DOF order.
struct ElementStiffnessContribution {
ElementDofLayout layout;
@@ -78,10 +59,6 @@ class Element {
const Vector& element_displacement) const = 0;
};
/// @brief Provides non-owning runtime elements in stable owner order.
/// @note Every referenced element must outlive this view.
using ElementView = std::vector<std::reference_wrapper<const Element>>;
} // namespace fesa
#endif // FESA_ELEMENTS_ELEMENT_H_
@@ -0,0 +1,200 @@
#ifndef FESA_ELEMENTS_ELEMENT_CAPABILITIES_H_
#define FESA_ELEMENTS_ELEMENT_CAPABILITIES_H_
#include <array>
#include <cstddef>
#include "fesa/elements/element.h"
#include "fesa/elements/thermal_element_layout.h"
#include "fesa/math/vector3.h"
namespace fesa {
class Hex8Element;
class Mitc4Shell;
class NonlinearMitc4Shell;
class NonlinearMitc4Inertia;
class ThermalShell;
struct Hex8Response;
struct Hex8HighLowResponse;
struct Mitc4Stiffness;
struct Mitc4Mass;
struct NonlinearMitc4TrialDofs;
struct NonlinearMitc4InternalEquilibrium;
struct NonlinearMitc4ExternalDrillingConstraint;
struct NonlinearMitc4InertiaEvaluation;
struct ThermalShellRecovery;
/// @brief Evaluates immutable shell trials; accepted history belongs to the procedure.
class ShellTrialElement {
public:
virtual ~ShellTrialElement() = default;
/// @brief Returns stable source-local node/component order, never equations.
virtual const ElementDofLayout& DofLayout() const noexcept = 0;
/// @brief Returns the complete force/tangent/recovery at a fixed-global trial.
/// @param coordinate_direction Optional 24-vector for D2(f_int)[v,v].
/// @note Failure preserves the kernel, caller inputs and earlier responses.
virtual Result<NonlinearMitc4InternalEquilibrium> EvaluateTrial(
const NonlinearMitc4TrialDofs& trial,
const Vector* coordinate_direction = nullptr) const = 0;
/// @copydoc NonlinearMitc4Shell::EvaluateExternalDrillingConstraint
virtual Result<NonlinearMitc4ExternalDrillingConstraint>
EvaluateExternalDrillingConstraint(
std::size_t node, const Vector3& phi, const Vector3& phi_dot,
const Vector3& force, const Vector3& force_rate,
const Vector3& force_acceleration) const = 0;
};
/// @brief Borrows the same immutable shell kernel for every trial operation.
/// @note The kernel must outlive this adapter and remain at its bound address.
class Mitc4TrialAdapter final : public ShellTrialElement {
public:
Mitc4TrialAdapter(ElementDofLayout layout, const NonlinearMitc4Shell& kernel);
const ElementDofLayout& DofLayout() const noexcept override;
Result<NonlinearMitc4InternalEquilibrium> EvaluateTrial(
const NonlinearMitc4TrialDofs& trial,
const Vector* coordinate_direction = nullptr) const override;
Result<NonlinearMitc4ExternalDrillingConstraint>
EvaluateExternalDrillingConstraint(
std::size_t node, const Vector3& phi, const Vector3& phi_dot,
const Vector3& force, const Vector3& force_rate,
const Vector3& force_acceleration) const override;
private:
ElementDofLayout layout_;
const NonlinearMitc4Shell& kernel_;
};
/// @brief Keeps complete paired solid responses and reference mass typed.
class SolidTrialElement : public Element {
public:
~SolidTrialElement() override = default;
/// @copydoc Hex8Element::EvaluateLinear
virtual Result<Hex8Response> EvaluateLinear(const Vector& u) const = 0;
/// @copydoc Hex8Element::EvaluateNonlinear
virtual Result<Hex8Response> EvaluateNonlinear(const Vector& u) const = 0;
/// @copydoc Hex8Element::EvaluateLinearHighLow
virtual Result<Hex8HighLowResponse> EvaluateLinearHighLow(
const Vector& high, const Vector& low) const = 0;
/// @copydoc Hex8Element::EvaluateNonlinearHighLow
virtual Result<Hex8HighLowResponse> EvaluateNonlinearHighLow(
const Vector& high, const Vector& low) const = 0;
/// @copydoc Hex8Element::ComputeMass
virtual Result<ElementStiffnessContribution> ComputeMass() const = 0;
/// @brief Returns fixed Gauss weights used by the frequency mass bound.
virtual std::array<double, 8> ReferenceWeights() const noexcept = 0;
};
/// @brief Borrows one stable Hex8 kernel shared by all local operations.
/// @note The kernel must outlive this adapter and remain at its bound address.
class Hex8TrialAdapter final : public SolidTrialElement {
public:
explicit Hex8TrialAdapter(const Hex8Element& kernel);
const ElementDofLayout& DofLayout() const noexcept override;
Result<ElementStiffnessContribution> ComputeStiffness() const override;
Result<ElementResultBundle> Recover(const Vector& u) const override;
Result<Hex8Response> EvaluateLinear(const Vector& u) const override;
Result<Hex8Response> EvaluateNonlinear(const Vector& u) const override;
Result<Hex8HighLowResponse> EvaluateLinearHighLow(
const Vector& high, const Vector& low) const override;
Result<Hex8HighLowResponse> EvaluateNonlinearHighLow(
const Vector& high, const Vector& low) const override;
Result<ElementStiffnessContribution> ComputeMass() const override;
std::array<double, 8> ReferenceWeights() const noexcept override;
private:
const Hex8Element& kernel_;
};
/// @brief Returns the complete physical inertia response in fixed chart DOFs.
class ShellInertiaElement {
public:
virtual ~ShellInertiaElement() = default;
virtual const ElementDofLayout& DofLayout() const noexcept = 0;
/// @copydoc NonlinearMitc4Inertia::Evaluate
virtual Result<NonlinearMitc4InertiaEvaluation> Evaluate(
const NonlinearMitc4TrialDofs& trial, const Vector& velocity24,
const Vector& physical_acceleration24) const = 0;
};
/// @brief Borrows immutable inertia geometry, never shared mutable scratch.
/// @note The kernel must outlive this adapter and remain at its bound address.
class Mitc4InertiaAdapter final : public ShellInertiaElement {
public:
Mitc4InertiaAdapter(ElementDofLayout layout,
const NonlinearMitc4Inertia& kernel);
const ElementDofLayout& DofLayout() const noexcept override;
Result<NonlinearMitc4InertiaEvaluation> Evaluate(
const NonlinearMitc4TrialDofs& trial, const Vector& velocity24,
const Vector& physical_acceleration24) const override;
private:
ElementDofLayout layout_;
const NonlinearMitc4Inertia& kernel_;
};
/// @brief Keeps DS4 DOFs 11-15 and all four-by-six flux traces independent.
class ThermalElement {
public:
virtual ~ThermalElement() = default;
/// @brief Returns node-major stations 11-15 and original source identity.
virtual const ThermalElementDofLayout& DofLayout() const noexcept = 0;
/// @copydoc ThermalShell::Conductivity
virtual const Matrix& Conductivity() const noexcept = 0;
/// @copydoc ThermalShell::Capacity
virtual const Matrix& Capacity() const noexcept = 0;
/// @copydoc ThermalShell::ConductivityError
virtual const Matrix& ConductivityError() const noexcept = 0;
/// @copydoc ThermalShell::CapacityError
virtual const Matrix& CapacityError() const noexcept = 0;
/// @copydoc ThermalShell::Recover
virtual Result<ThermalShellRecovery> Recover(
const std::array<double, 20>& temperature) const = 0;
};
/// @brief Borrows the same DS4 kernel for matrices, intervals and recovery.
/// @note The kernel must outlive this adapter and remain at its bound address.
class Ds4ThermalAdapter final : public ThermalElement {
public:
explicit Ds4ThermalAdapter(const ThermalShell& kernel);
const ThermalElementDofLayout& DofLayout() const noexcept override;
const Matrix& Conductivity() const noexcept override;
const Matrix& Capacity() const noexcept override;
const Matrix& ConductivityError() const noexcept override;
const Matrix& CapacityError() const noexcept override;
Result<ThermalShellRecovery> Recover(
const std::array<double, 20>& temperature) const override;
private:
ThermalElementDofLayout layout_;
const ThermalShell& kernel_;
};
/// @brief Supplies shell frequency operators with their distinct mass contract.
class ShellReferenceElement : public Element {
public:
~ShellReferenceElement() override = default;
/// @copydoc Mitc4Shell::Stiffness
virtual Result<Mitc4Stiffness> Stiffness() const = 0;
/// @copydoc Mitc4Shell::Mass
virtual Result<Mitc4Mass> Mass(double density) const = 0;
};
/// @brief Borrows the same linear MITC4 kernel for stiffness and recovery.
/// @note The kernel must outlive this adapter and remain at its bound address.
class Mitc4ReferenceAdapter final : public ShellReferenceElement {
public:
explicit Mitc4ReferenceAdapter(const Mitc4Shell& kernel);
const ElementDofLayout& DofLayout() const noexcept override;
Result<ElementStiffnessContribution> ComputeStiffness() const override;
Result<ElementResultBundle> Recover(const Vector& u) const override;
Result<Mitc4Stiffness> Stiffness() const override;
Result<Mitc4Mass> Mass(double density) const override;
private:
const Mitc4Shell& kernel_;
};
} // namespace fesa
#endif // FESA_ELEMENTS_ELEMENT_CAPABILITIES_H_
@@ -0,0 +1,38 @@
#ifndef FESA_ELEMENTS_ELEMENT_DOF_LAYOUT_H_
#define FESA_ELEMENTS_ELEMENT_DOF_LAYOUT_H_
#include <cstdint>
#include <functional>
#include <vector>
#include "fesa/core/source_identity.h"
namespace fesa {
/// @brief Identifies one component in the stable six-DOF node layout.
enum class DofComponent : std::uint8_t {
kUx,
kUy,
kUz,
kUrx,
kUry,
kUrz,
};
/// @brief Describes one runtime element's stable node and component order.
struct ElementDofLayout {
SourceEntityId source_id;
std::vector<EntityIndex> node_indices;
std::vector<DofComponent> components_per_node;
};
class Element;
/// @brief Provides non-owning runtime elements in stable owner order.
/// @note Every referenced element must outlive this view.
using ElementView = std::vector<std::reference_wrapper<const Element>>;
} // namespace fesa
#endif // FESA_ELEMENTS_ELEMENT_DOF_LAYOUT_H_
+9
View File
@@ -5,6 +5,7 @@
#include "fesa/core/status.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_capabilities.h"
namespace fesa {
@@ -21,6 +22,14 @@ class ElementFactory {
Result<std::unique_ptr<Element>> Create(const ElementDefinition& definition,
const Domain& domain) const;
/// @brief Binds a typed view of an existing stable runtime kernel.
/// @note Returns null for a different family. The kernel must outlive the
/// returned adapter and remain at its address; no second kernel is created.
std::unique_ptr<SolidTrialElement> BindSolidTrial(const Element& kernel) const;
/// @copydoc BindSolidTrial
std::unique_ptr<ShellReferenceElement> BindShellReference(
const Element& kernel) const;
private:
/// @brief Creates one checked B33 runtime candidate.
Result<std::unique_ptr<Element>> CreateBeam(
+1 -34
View File
@@ -4,12 +4,11 @@
#include <array>
#include <cstddef>
#include <string>
#include <string_view>
#include <vector>
#include "fesa/core/status.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_definition.h"
#include "fesa/elements/euler_beam_3d_definition.h"
#include "fesa/materials/isotropic_linear_elastic_material.h"
#include "fesa/math/matrix.h"
#include "fesa/math/vector.h"
@@ -17,40 +16,8 @@
namespace fesa {
class Domain;
struct Node;
/// @brief Defines one two-node B33 semantic element.
class EulerBeam3DDefinition final : public ElementDefinition {
public:
/// @brief Constructs a parser-validated semantic definition.
EulerBeam3DDefinition(SourceEntityId source_id,
std::array<EntityIndex, 2> node_indices,
EntityIndex material_index, EntityIndex section_index,
SourceLocation location);
ElementDefinitionKind Kind() const noexcept override;
const SourceEntityId& SourceId() const noexcept override;
std::string_view SourceElementType() const noexcept override;
const std::vector<EntityIndex>& NodeIndices() const noexcept override;
EntityIndex MaterialIndex() const noexcept override;
EntityIndex PropertyIndex() const noexcept override;
SourceEntityId source_id;
std::array<EntityIndex, 2> node_indices;
EntityIndex material_index;
EntityIndex section_index;
SourceLocation location;
private:
friend class Domain;
/// @brief Synchronizes the base view after parser-candidate construction.
void SynchronizeNodeIndices();
std::vector<EntityIndex> node_indices_view_;
};
/// @brief Stores constant line-load components in the beam local frame.
struct ConstantLocalLineLoad {
double px;
@@ -0,0 +1,48 @@
#ifndef FESA_ELEMENTS_EULER_BEAM_3D_DEFINITION_H_
#define FESA_ELEMENTS_EULER_BEAM_3D_DEFINITION_H_
#include <array>
#include <string_view>
#include <vector>
#include "fesa/elements/element_definition.h"
namespace fesa {
class Domain;
/// @brief Defines one two-node B33 semantic element.
class EulerBeam3DDefinition final : public ElementDefinition {
public:
/// @brief Constructs a parser-validated semantic definition.
EulerBeam3DDefinition(SourceEntityId source_id,
std::array<EntityIndex, 2> node_indices,
EntityIndex material_index, EntityIndex section_index,
SourceLocation location);
ElementDefinitionKind Kind() const noexcept override;
const SourceEntityId& SourceId() const noexcept override;
std::string_view SourceElementType() const noexcept override;
const std::vector<EntityIndex>& NodeIndices() const noexcept override;
EntityIndex MaterialIndex() const noexcept override;
EntityIndex PropertyIndex() const noexcept override;
SourceEntityId source_id;
std::array<EntityIndex, 2> node_indices;
EntityIndex material_index;
EntityIndex section_index;
SourceLocation location;
private:
friend class Domain;
/// @brief Synchronizes the base view after parser-candidate construction.
void SynchronizeNodeIndices();
std::vector<EntityIndex> node_indices_view_;
};
} // namespace fesa
#endif // FESA_ELEMENTS_EULER_BEAM_3D_DEFINITION_H_
+6 -4
View File
@@ -33,11 +33,13 @@ Matrix ExpSkew(const Vector3& phi);
/// @pre phi is finite and lies inside the approved principal chart.
Matrix LeftJacobianSO3(const Vector3& phi);
/// @brief Computes the inverse transpose of the SO(3) left Jacobian.
/// @param phi Fixed-global rotation coordinate in radians.
/// @return The 3-by-3 inverse-transpose left Jacobian.
/// @brief Solves J(phi)^T * moment = generalized for a spatial moment.
/// @param phi Fixed-global principal-chart rotation coordinate in radians.
/// @param generalized Work-conjugate moment in fixed-global chart coordinates.
/// @return A finite spatial moment in the same force-length units, or failure.
/// @pre phi is finite and lies inside the approved principal chart.
Matrix InverseTransposeLeftJacobianSO3(const Vector3& phi);
/// @note Inputs remain unchanged; no inverse Jacobian is constructed.
Result<Vector3> SpatialMomentSO3(const Vector3& phi, const Vector3& generalized);
/// @brief Builds a checked finite-rotation state from its reference frame.
/// @param phi Fixed-global principal-chart rotation coordinate in radians.
+2 -48
View File
@@ -3,12 +3,11 @@
#include <array>
#include <string>
#include <string_view>
#include <vector>
#include "fesa/core/status.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_definition.h"
#include "fesa/elements/mitc4_shell_definition.h"
#include "fesa/materials/isotropic_linear_elastic_material.h"
#include "fesa/math/matrix.h"
#include "fesa/math/vector.h"
@@ -17,52 +16,8 @@
namespace fesa {
class Domain;
struct Node;
/// @brief Preserves the source shell type independently of formulation.
enum class ShellSourceElementType { kS4, kS4r };
/// @brief Names the internal shell formulation selected by S4 and S4R.
inline constexpr std::string_view kMitc4InternalFormulation{"FESA-MITC4"};
/// @brief Defines one four-node S4/S4R semantic element.
class Mitc4ShellDefinition final : public ElementDefinition {
public:
/// @brief Constructs a parser-validated semantic definition.
Mitc4ShellDefinition(SourceEntityId source_id,
ShellSourceElementType source_type,
std::array<EntityIndex, 4> node_indices,
EntityIndex material_index, EntityIndex section_index,
SourceLocation location);
ElementDefinitionKind Kind() const noexcept override;
const SourceEntityId& SourceId() const noexcept override;
std::string_view SourceElementType() const noexcept override;
const std::vector<EntityIndex>& NodeIndices() const noexcept override;
EntityIndex MaterialIndex() const noexcept override;
EntityIndex PropertyIndex() const noexcept override;
SourceEntityId source_id;
ShellSourceElementType source_type;
std::array<EntityIndex, 4> node_indices;
EntityIndex material_index;
EntityIndex section_index;
SourceLocation location;
private:
friend class Domain;
/// @brief Rebinds a shell-local section index to the unified property view.
void SetPropertyIndex(EntityIndex property_index) noexcept;
/// @brief Synchronizes the base view after parser-candidate construction.
void SynchronizeNodeIndices();
EntityIndex property_index_;
std::vector<EntityIndex> node_indices_view_;
};
/// @brief Stores bilinear shape values and natural-coordinate derivatives.
struct Mitc4ShapeFunctions {
std::array<double, 4> values;
@@ -213,11 +168,10 @@ class Mitc4Shell final : public Element {
void BindRuntime(ElementDofLayout layout, EntityIndex element_index,
SourceLocation location);
/// @brief Stores covariant, reciprocal, frame, and Jacobian data at one
/// @brief Stores covariant, frame, and Jacobian data at one
/// point.
struct GeometryData {
std::array<Vector3, 3> covariant;
std::array<Vector3, 3> reciprocal;
Mitc4LocalFrame frame;
double jacobian;
};
@@ -0,0 +1,60 @@
#ifndef FESA_ELEMENTS_MITC4_SHELL_DEFINITION_H_
#define FESA_ELEMENTS_MITC4_SHELL_DEFINITION_H_
#include <array>
#include <string_view>
#include <vector>
#include "fesa/elements/element_definition.h"
namespace fesa {
class Domain;
/// @brief Preserves the source shell type independently of formulation.
enum class ShellSourceElementType { kS4, kS4r };
/// @brief Names the internal shell formulation selected by S4 and S4R.
inline constexpr std::string_view kMitc4InternalFormulation{"FESA-MITC4"};
/// @brief Defines one four-node S4/S4R semantic element.
class Mitc4ShellDefinition final : public ElementDefinition {
public:
/// @brief Constructs a parser-validated semantic definition.
Mitc4ShellDefinition(SourceEntityId source_id,
ShellSourceElementType source_type,
std::array<EntityIndex, 4> node_indices,
EntityIndex material_index, EntityIndex section_index,
SourceLocation location);
ElementDefinitionKind Kind() const noexcept override;
const SourceEntityId& SourceId() const noexcept override;
std::string_view SourceElementType() const noexcept override;
const std::vector<EntityIndex>& NodeIndices() const noexcept override;
EntityIndex MaterialIndex() const noexcept override;
EntityIndex PropertyIndex() const noexcept override;
SourceEntityId source_id;
ShellSourceElementType source_type;
std::array<EntityIndex, 4> node_indices;
EntityIndex material_index;
EntityIndex section_index;
SourceLocation location;
private:
friend class Domain;
/// @brief Rebinds a shell-local section index to the unified property view.
void SetPropertyIndex(EntityIndex property_index) noexcept;
/// @brief Synchronizes the base view after parser-candidate construction.
void SynchronizeNodeIndices();
EntityIndex property_index_;
std::vector<EntityIndex> node_indices_view_;
};
} // namespace fesa
#endif // FESA_ELEMENTS_MITC4_SHELL_DEFINITION_H_
@@ -0,0 +1,20 @@
#ifndef FESA_ELEMENTS_THERMAL_DOF_COMPONENT_H_
#define FESA_ELEMENTS_THERMAL_DOF_COMPONENT_H_
namespace fesa {
/// @brief Identifies the fixed bottom-to-top thermal station source DOFs.
/// @note This is separate from the six-component structural DofComponent.
enum class ThermalDofComponent : int {
kBottom = 11,
kLower = 12,
kMiddle = 13,
kUpper = 14,
kTop = 15
};
} // namespace fesa
#endif // FESA_ELEMENTS_THERMAL_DOF_COMPONENT_H_
@@ -3,7 +3,8 @@
#include <array>
#include "fesa/model/model_types.h"
#include "fesa/core/source_identity.h"
#include "fesa/elements/thermal_dof_component.h"
namespace fesa {
+3 -8
View File
@@ -6,25 +6,20 @@
#include <optional>
#include <vector>
#include "fesa/analysis/analysis_model.h"
#include "fesa/constraints/boundary_condition.h"
#include "fesa/elements/element.h"
#include "fesa/elements/element_dof_layout.h"
#include "fesa/elements/thermal_element_layout.h"
#include "fesa/math/sparse_pattern.h"
#include "fesa/math/vector.h"
namespace fesa {
class AnalysisModel;
class DofManagerTestAccess;
/// @brief Distinguishes six-component, Solid translation, and thermal maps.
enum class DofProfile { kStructural, kThermal, kSolidStructural };
/// @brief Stores the stable full-space CSR pattern.
struct SparsePattern {
std::vector<std::size_t> row_offsets;
std::vector<std::size_t> column_indices;
};
/// @brief Owns full/free/constrained numbering, scatter maps, and CSR pattern.
class DofManager {
public:
+20
View File
@@ -32,6 +32,26 @@ class Matrix {
/// @brief Returns the column count.
std::size_t Columns() const noexcept;
/// @brief Returns mutable row-major contiguous storage.
/// @note Borrows Rows()*Columns() entries until storage is moved, assigned
/// or destroyed.
double* Data() noexcept;
/// @brief Returns immutable row-major contiguous storage.
/// @note Borrows Rows()*Columns() entries until storage is moved, assigned
/// or destroyed.
const double* Data() const noexcept;
/// @brief Computes the robust Frobenius norm through the dense backend.
/// @note Empty storage has zero norm; nonfinite values propagate as in Vector.
/// @throws std::length_error if storage exceeds the backend integer range.
double Norm() const;
/// @brief Scales every entry by alpha through the dense backend.
/// @note Empty storage is unchanged; nonfinite values follow BLAS semantics.
/// @throws std::length_error if storage exceeds the backend integer range.
void Scale(double alpha);
/// @brief Returns a bounds-checked mutable entry.
/// @throws std::out_of_range if the index is outside the matrix.
double& operator()(std::size_t row, std::size_t column);
+1 -2
View File
@@ -5,12 +5,11 @@
#include <vector>
#include "fesa/core/status.h"
#include "fesa/math/sparse_pattern.h"
#include "fesa/math/vector.h"
namespace fesa {
struct SparsePattern;
/// @brief Carries one deterministic element-local COO contribution.
struct CooContribution {
std::size_t row;
+18
View File
@@ -0,0 +1,18 @@
#ifndef FESA_MATH_SPARSE_PATTERN_H_
#define FESA_MATH_SPARSE_PATTERN_H_
#include <cstddef>
#include <vector>
namespace fesa {
/// @brief Stores the stable full-space CSR pattern.
struct SparsePattern {
std::vector<std::size_t> row_offsets;
std::vector<std::size_t> column_indices;
};
} // namespace fesa
#endif // FESA_MATH_SPARSE_PATTERN_H_
+2
View File
@@ -11,6 +11,8 @@
#include "fesa/constraints/boundary_condition.h"
#include "fesa/constraints/prescribed_displacement.h"
#include "fesa/core/status.h"
#include "fesa/elements/ds4_thermal.h"
#include "fesa/materials/isotropic_thermal_material.h"
#include "fesa/loads/concentrated_nodal_load.h"
#include "fesa/loads/load.h"
#include "fesa/model/model_types.h"
+3 -14
View File
@@ -13,12 +13,11 @@
#include "fesa/core/diagnostic.h"
#include "fesa/core/source_identity.h"
#include "fesa/elements/ds4_thermal.h"
#include "fesa/elements/euler_beam_3d.h"
#include "fesa/elements/euler_beam_3d_definition.h"
#include "fesa/elements/hex8_definition.h"
#include "fesa/elements/mitc4_shell.h"
#include "fesa/elements/mitc4_shell_definition.h"
#include "fesa/elements/thermal_dof_component.h"
#include "fesa/materials/isotropic_linear_elastic_material.h"
#include "fesa/materials/isotropic_thermal_material.h"
#include "fesa/properties/general_beam_section.h"
#include "fesa/properties/shell_section.h"
#include "fesa/properties/solid_section.h"
@@ -302,16 +301,6 @@ struct ThermalInitialConditionDefinition {
SourceLocation location;
};
/// @brief Identifies the fixed bottom-to-top thermal station source DOFs.
/// @note This is separate from the six-component structural DofComponent.
enum class ThermalDofComponent : int {
kBottom = 11,
kLower = 12,
kMiddle = 13,
kUpper = 14,
kTop = 15
};
/// @brief Stores one prescribed thermal source DOF value.
struct ThermalBoundaryConditionDefinition {
EntityIndex node_index;
@@ -38,6 +38,14 @@ class SourceTargetIndex {
/// @return An owning index that preserves Domain declaration order.
static SourceTargetIndex FromDomain(const Domain& domain);
/// @brief Copies node and set identities before Domain ownership begins.
/// @param nodes Semantic nodes in stable expanded declaration order.
/// @param node_sets Node memberships in stable source order.
/// @return An owning node-only index preserving raw spelling and scope.
/// @note The returned index outlives its inputs; no Domain is constructed.
static SourceTargetIndex FromNodeDefinitions(
const std::vector<Node>& nodes, const std::vector<NodeSet>& node_sets);
/// @brief Returns owned entries without exposing mutable index state.
const std::vector<SourceTargetIndexEntry>& Entries() const noexcept;
@@ -0,0 +1,39 @@
#ifndef FESA_RESULTS_PREPARED_RESULTS_WRITER_H_
#define FESA_RESULTS_PREPARED_RESULTS_WRITER_H_
#include <filesystem>
#include <vector>
#include "fesa/analysis/prepared_analysis_outcome.h"
#include "fesa/core/diagnostic.h"
#include "fesa/core/status.h"
namespace fesa {
class Domain;
class ResultsWriter;
class NonlinearResultsWriter;
class EigenResultsWriter;
class DynamicResultsWriter;
class ThermalResultsWriter;
class SolidResultsWriter;
/// @brief Routes one completed typed outcome to its authoritative writer.
/// @pre Domain, outcome, diagnostics, and adapters remain alive for this call.
/// The caller has closed its analysis log successfully before publication.
/// @param results_path Explicit output path, retaining each writer's contract.
/// @note Optional adapters are required only for their matching outcome family.
/// @return The selected writer's Status after candidate validation/finalization,
/// or the existing missing-adapter output failure without invoking a writer.
Status WritePreparedAnalysisResult(
const std::filesystem::path& results_path, const Domain& domain,
const PreparedAnalysisOutcome& outcome,
const std::vector<Diagnostic>& diagnostics, ResultsWriter& linear_writer,
NonlinearResultsWriter& nonlinear_writer, EigenResultsWriter& eigen_writer,
DynamicResultsWriter* dynamic_writer = nullptr,
ThermalResultsWriter* thermal_writer = nullptr,
SolidResultsWriter* solid_writer = nullptr);
} // namespace fesa
#endif // FESA_RESULTS_PREPARED_RESULTS_WRITER_H_
+99
View File
@@ -0,0 +1,99 @@
#ifndef FESA_SOLVERS_EIGEN_EIGEN_SOLVER_H_
#define FESA_SOLVERS_EIGEN_EIGEN_SOLVER_H_
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "fesa/core/status.h"
#include "fesa/math/matrix.h"
namespace fesa {
class SparseMatrix;
/// @brief Records one deterministic private-backend invocation.
struct FeastBackendCall {
std::size_t ordinal;
std::string kind;
std::string purpose;
double lower;
double upper;
std::size_t allocated_m0;
int info;
bool count_available;
std::size_t count;
bool loop_available;
int loop;
bool epsout_available;
double epsout;
std::string outcome;
std::string decision_reason;
};
/// @brief Owns the complete validated FEAST interval result before public N
/// selection.
struct FeastEigenResult {
std::size_t requested_modes;
std::vector<double> eigenvalues;
Matrix eigenvectors;
double operator_scale;
std::vector<std::size_t> column_ids;
std::vector<bool> backend_res_available;
std::vector<double> backend_res;
std::vector<double> normalized_eigenvalues;
std::vector<double> whitened_residuals;
double gram_error;
std::vector<FeastBackendCall> backend_calls;
std::vector<std::int64_t> base_fpm;
std::string runtime_version;
std::string integer_abi;
std::size_t thread_count;
std::uint64_t seed;
double enclosure_lower;
double enclosure_upper;
double solve_lower;
double solve_upper;
std::string upper_search_termination;
};
/// @brief Solves symmetric standard or definite generalized eigenproblems.
/// @note Inputs remain caller-owned and are borrowed only for each call.
class EigenSolver {
public:
/// @brief Destroys a backend-neutral eigen solver.
virtual ~EigenSolver() = default;
/// @brief Computes all validated interval pairs for a requested lowest-mode
/// prefix.
/// @param whitened_operator Symmetric physical-lambda operator after
/// whitening.
/// @param requested_modes Number of lowest modes eventually exposed by the
/// caller.
/// @param zero_operator_scale Positive physical scale used only when A is
/// exactly zero.
/// @return Sorted all-c eigenpairs in physical lambda units or a solver
/// failure.
virtual Result<FeastEigenResult> Solve(
const SparseMatrix& whitened_operator, std::size_t requested_modes,
double zero_operator_scale) const = 0;
/// @brief Solves the original sparse symmetric definite K/M pencil.
/// @param mass_lower_bound Certified positive lower spectral bound of M,
/// including floating-point assembly uncertainty; never a diagonal estimate.
/// @param classification_scale Positive max |Kii|/Mii in physical units.
/// @note Eigenvectors are mass-normalized. For this API the historical
/// whitened_residuals field contains original-pencil eta_r; no whitening
/// is performed. Intervals/eigenvalues in normalized backend evidence use
/// classification_scale, while eigenvalues are returned in physical units.
virtual Result<FeastEigenResult> SolveGeneralized(
const SparseMatrix& stiffness, const SparseMatrix& mass,
std::size_t requested_modes, double mass_lower_bound,
double classification_scale) const = 0;
};
} // namespace fesa
#endif // FESA_SOLVERS_EIGEN_EIGEN_SOLVER_H_
@@ -1,65 +1,12 @@
#ifndef FESA_SOLVERS_EIGEN_MKL_FEAST_EIGEN_SOLVER_H_
#define FESA_SOLVERS_EIGEN_MKL_FEAST_EIGEN_SOLVER_H_
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "fesa/core/status.h"
#include "fesa/math/matrix.h"
#include "fesa/solvers/eigen/eigen_solver.h"
namespace fesa {
class SparseMatrix;
/// @brief Records one deterministic private-backend invocation.
struct FeastBackendCall {
std::size_t ordinal;
std::string kind;
std::string purpose;
double lower;
double upper;
std::size_t allocated_m0;
int info;
bool count_available;
std::size_t count;
bool loop_available;
int loop;
bool epsout_available;
double epsout;
std::string outcome;
std::string decision_reason;
};
/// @brief Owns the complete validated FEAST interval result before public N
/// selection.
struct FeastEigenResult {
std::size_t requested_modes;
std::vector<double> eigenvalues;
Matrix eigenvectors;
double operator_scale;
std::vector<std::size_t> column_ids;
std::vector<bool> backend_res_available;
std::vector<double> backend_res;
std::vector<double> normalized_eigenvalues;
std::vector<double> whitened_residuals;
double gram_error;
std::vector<FeastBackendCall> backend_calls;
std::vector<std::int64_t> base_fpm;
std::string runtime_version;
std::string integer_abi;
std::size_t thread_count;
std::uint64_t seed;
double enclosure_lower;
double enclosure_upper;
double solve_lower;
double solve_upper;
std::string upper_search_termination;
};
/// @brief Adapts standard and symmetric-definite sparse pencils to FEAST.
class MklFeastEigenSolver final {
class MklFeastEigenSolver final : public EigenSolver {
public:
/// @brief Computes all validated interval pairs for a requested lowest-mode
/// prefix.
@@ -74,8 +21,8 @@ class MklFeastEigenSolver final {
/// @note The implementation fixes oneMKL local thread count to one during
/// every call.
Result<FeastEigenResult> Solve(const SparseMatrix& whitened_operator,
std::size_t requested_modes,
double zero_operator_scale) const;
std::size_t requested_modes,
double zero_operator_scale) const override;
/// @brief Solves the original sparse symmetric definite K/M pencil.
/// @param mass_lower_bound Certified positive lower spectral bound of M,
/// including floating-point assembly uncertainty; never a diagonal estimate.
@@ -86,16 +33,16 @@ class MklFeastEigenSolver final {
/// classification_scale, while eigenvalues are returned in physical units.
Result<FeastEigenResult> SolveGeneralized(const SparseMatrix& stiffness,
const SparseMatrix& mass,
std::size_t requested_modes,
std::size_t requested_modes,
double mass_lower_bound,
double classification_scale) const;
double classification_scale) const override;
private:
/// @brief Shares deterministic count/search controls without changing
/// pencils.
Result<FeastEigenResult> SolveImpl(const SparseMatrix& stiffness,
const SparseMatrix* mass,
std::size_t requested_modes,
std::size_t requested_modes,
double physical_scale,
double mass_lower_bound) const;
};