feat(linear-static-3d-euler-beam): step 23 - hdf5-results-writer
This commit is contained in:
@@ -44,10 +44,13 @@ if(NOT TARGET TBB::tbb)
|
|||||||
message(FATAL_ERROR "The oneTBB CONFIG package did not define TBB::tbb")
|
message(FATAL_ERROR "The oneTBB CONFIG package did not define TBB::tbb")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TARGET hdf5::hdf5-static)
|
# Prefer the packaged shared C runtime when both variants exist. The Windows
|
||||||
set(_fesa_hdf5_target hdf5::hdf5-static)
|
# static archive may carry compiler-runtime requirements that are not part of
|
||||||
elseif(TARGET hdf5::hdf5-shared)
|
# the HDF5 imported target's transitive link interface.
|
||||||
|
if(TARGET hdf5::hdf5-shared)
|
||||||
set(_fesa_hdf5_target hdf5::hdf5-shared)
|
set(_fesa_hdf5_target hdf5::hdf5-shared)
|
||||||
|
elseif(TARGET hdf5::hdf5-static)
|
||||||
|
set(_fesa_hdf5_target hdf5::hdf5-static)
|
||||||
elseif(TARGET HDF5::HDF5)
|
elseif(TARGET HDF5::HDF5)
|
||||||
set(_fesa_hdf5_target HDF5::HDF5)
|
set(_fesa_hdf5_target HDF5::HDF5)
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -1130,3 +1130,82 @@
|
|||||||
the subsequent uncontended serial build, targeted, discovery, full sequence
|
the subsequent uncontended serial build, targeted, discovery, full sequence
|
||||||
followed by a separate successful audit command.
|
followed by a separate successful audit command.
|
||||||
- concerns: none; no upstream-contract conflict or critical blocker remains.
|
- concerns: none; no upstream-contract conflict or critical blocker remains.
|
||||||
|
|
||||||
|
## Step 23 — hdf5-results-writer
|
||||||
|
|
||||||
|
- task_id: `TASK-23`
|
||||||
|
- status: `completed`
|
||||||
|
- changed_files: `include/fesa/results/results_writer.hpp`,
|
||||||
|
`include/fesa/io/hdf5/hdf5_results_writer.hpp`,
|
||||||
|
`src/fesa/io/hdf5/hdf5_results_writer.cpp`,
|
||||||
|
`tests/unit/results/results_writer_test.cpp`,
|
||||||
|
`tests/unit/io/hdf5/hdf5_results_writer_test.cpp`,
|
||||||
|
`src/fesa/CMakeLists.txt`, `tests/CMakeLists.txt`,
|
||||||
|
`cmake/FesaDependencies.cmake`,
|
||||||
|
`docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`,
|
||||||
|
`phases/linear-static-3d-euler-beam/index.json`
|
||||||
|
- requirement_ids: `FESA-REQ-LS3DEB-003`, `FESA-REQ-LS3DEB-015`,
|
||||||
|
`FESA-REQ-LS3DEB-019`, `FESA-REQ-LS3DEB-020`,
|
||||||
|
`FESA-REQ-LS3DEB-023`, `FESA-REQ-LS3DEB-025`,
|
||||||
|
`FESA-REQ-LS3DEB-028`, `FESA-REQ-LS3DEB-029`,
|
||||||
|
`FESA-REQ-LS3DEB-030`, `FESA-REQ-LS3DEB-031`,
|
||||||
|
`FESA-REQ-LS3DEB-032`, `FESA-REQ-LS3DEB-034`
|
||||||
|
- test_ids: `T23-HDF5-001`, `T23-HDF5-002`, `T23-HDF5-003`,
|
||||||
|
`T23-HDF5-004`, `T23-HDF5-005`
|
||||||
|
|
||||||
|
| stage | exact command | exit_code | expected_or_observed_result | evidence_tail |
|
||||||
|
| --- | --- | ---: | --- | --- |
|
||||||
|
| RED-build | `cmake --build .harness/build --config Debug --target fesa_tests` | 1 | All five ledger tests were registered before either public production header existed | MSVC C1083 reported missing `fesa/results/results_writer.hpp` and `fesa/io/hdf5/hdf5_results_writer.hpp` |
|
||||||
|
| INFRA-link | `cmake --build .harness/build --config Debug --target fesa_tests` | 1 | Production and tests compiled, but the packaged static HDF5 target could not link in this environment | LNK1104 reported missing `libircmt.lib`; this is infrastructure evidence, not the feature RED |
|
||||||
|
| INFRA-runtime-discovery | `cmake --build .harness/build --config Debug --target fesa_tests` | 1 | Shared HDF5 linked after normalized-target repair, but post-build GoogleTest discovery could not load a transitive runtime | discovery exited `0xc0000135`; `dumpbin /dependents hdf5.dll` identified `libmmd.dll` |
|
||||||
|
| GREEN-build | `cmake --build .harness/build --config Debug --target fesa_tests` | 0 | Minimum schema-v0 writer, tests, solver library, and unit executable compile/link after the approved runtime repair | `hdf5_results_writer.cpp` and both tests built under `/W4 /WX`; required runtime DLLs were staged before discovery |
|
||||||
|
| GREEN-test | `ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure` | 0 | Exact schema, mandatory outputs, diagnostics/centroid, failure preservation, and successful replacement pass | 5/5 exact `Hdf5ResultsWriter` tests passed |
|
||||||
|
| VERIFY-configure | `cmake -S . -B .harness/build -A x64 -DFESA_GTEST_SOURCE_DIR=C:/git/googletest "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake"` | 0 | Approved explicit-dependency MSVC x64 build tree generates | Visual Studio 18/MSVC x64, Windows SDK 10.0.26100.0, oneMKL, oneTBB, and shared HDF5 resolved; configure/generate completed |
|
||||||
|
| VERIFY-build | `cmake --build .harness/build --config Debug` | 0 | Full Debug build passes without a new FESA warning | `fesa_solver.lib` and `fesa_unit_tests.exe` built under `/W4 /WX` |
|
||||||
|
| VERIFY-targeted | `ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure` | 0 | Focused Step 23 suite remains green | 5/5 exact `Hdf5ResultsWriter` tests passed |
|
||||||
|
| VERIFY-discovery | `ctest --test-dir .harness/build -C Debug --show-only=json-v1` | 0 | CTest discovers the accumulated suite and all five exact ledger names | 73 tests discovered, including exactly 5 `Hdf5ResultsWriter` tests |
|
||||||
|
| VERIFY-full | `ctest --test-dir .harness/build -C Debug --output-on-failure` | 0 | Full accumulated C++ suite has zero failures | 73/73 tests passed in 2.75 seconds |
|
||||||
|
| VERIFY-runtime | `& 'C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.51.36231\bin\Hostx64\x64\dumpbin.exe' /dependents 'C:\Program Files\HDF_Group\HDF5\2.1.1\bin\hdf5.dll'` | 0 | The package DLL's undeclared Intel runtime requirement is traceable | dependencies include `libmmd.dll`; the WIN32 staging guard copies `${OMP_DLL_DIR}/libmmd.dll` |
|
||||||
|
| VERIFY-contract-scans | Public HDF5/Win32 type scan, exact-test count, finalizer/RAII scope scan, forbidden shear/averaging/filter scan, `git diff --check`, and reference diff/status | 0 | Backend boundary, exact mandatory-output scope, atomic finalization, and reference immutability remain isolated | public backend leaks 0; exact tests 5; checked file closes and exact Replace/Move split present; forbidden scope 0; whitespace clean; reference unchanged |
|
||||||
|
|
||||||
|
- contract_checks: `ResultsWriter` and `Hdf5ResultsWriter` expose only the
|
||||||
|
approved backend-free signatures. HDF5, Win32 handles, macros, RAII wrappers,
|
||||||
|
schema construction, self-check, and atomic finalization stay private to the
|
||||||
|
implementation; `Fesa::HDF5` is linked privately.
|
||||||
|
- contract_checks: schema v0 writes every literal metadata, model, and
|
||||||
|
`/steps/Step-1/frames/0` path, including `generalized_resultant`. Numeric
|
||||||
|
fields use IEEE little-endian float64, stable identities use little-endian
|
||||||
|
uint64 compound members, text uses UTF-8 variable-length strings, and exact
|
||||||
|
component/unit/coordinate/location/step/frame attributes are pinned.
|
||||||
|
- contract_checks: non-axis-aligned element axes, node/element identity,
|
||||||
|
connectivity, and representative first/last nonzero values for displacement,
|
||||||
|
reaction, end action, section resultant, generalized strain, and generalized
|
||||||
|
resultant prove solved state is connected to output. Output requests do not
|
||||||
|
filter any mandatory field; shear/averaged stress was not added.
|
||||||
|
- contract_checks: diagnostics are stable-sorted and preserved, an empty input
|
||||||
|
produces an exact zero-row compound dataset, and the default centroid stress
|
||||||
|
row serializes axial `S11` only. Dimensions, row identity/order, source
|
||||||
|
identity, and all numeric values are validated before finalization.
|
||||||
|
- atomicity: a unique same-directory temporary file is fully written, flushed,
|
||||||
|
checked-closed, reopened read-only for exact schema self-check, and
|
||||||
|
checked-closed before finalization. Existing finals use only
|
||||||
|
`ReplaceFileW(final,temp,nullptr,...)`; new finals use only
|
||||||
|
`MoveFileExW(temp,final,MOVEFILE_WRITE_THROUGH)`. Failure removes the temp,
|
||||||
|
leaves no partial new final, and preserves pre-existing final bytes.
|
||||||
|
- infrastructure_resolution: the approved normalized HDF5 dependency now
|
||||||
|
prefers the package shared target, with static and `HDF5::HDF5` fallbacks.
|
||||||
|
Tests stage `$<TARGET_RUNTIME_DLLS:fesa_unit_tests>` plus the package DLL's
|
||||||
|
verified `${OMP_DLL_DIR}/libmmd.dll` dependency without directly naming an
|
||||||
|
HDF5 package target or hardcoding an Intel installation path.
|
||||||
|
- generated_evidence: `.harness/build/src/fesa/Debug/fesa_solver.lib`,
|
||||||
|
`.harness/build/tests/Debug/fesa_unit_tests.exe`; all test HDF5/temp artifacts
|
||||||
|
are confined to build-tree temporary directories and cleaned by their owners.
|
||||||
|
- reference_diff: unchanged; `git diff --exit-code -- reference/` and
|
||||||
|
`git status --short -- reference/` both report no change.
|
||||||
|
- handoff: Step 24 can construct the backend-free writer and rely on mandatory
|
||||||
|
schema-v0 output and fail-atomic replacement. Its production executable must
|
||||||
|
stage the selected HDF5 target runtime DLLs and `${OMP_DLL_DIR}/libmmd.dll`
|
||||||
|
with the same portable target-expression/runtime-guard policy used by tests.
|
||||||
|
- concerns: no remaining critical implementation or upstream-contract blocker.
|
||||||
|
The HDF5 static-link and shared-runtime environment blockers were resolved
|
||||||
|
and are recorded separately from the valid missing-API RED.
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fesa/results/results_writer.hpp"
|
||||||
|
|
||||||
|
namespace fesa {
|
||||||
|
|
||||||
|
// Writes schema-v0 output while keeping backend and platform types private.
|
||||||
|
class Hdf5ResultsWriter final : public ResultsWriter {
|
||||||
|
public:
|
||||||
|
Status write(
|
||||||
|
const std::filesystem::path& outputPath,
|
||||||
|
const Domain& domain,
|
||||||
|
const AnalysisState& state,
|
||||||
|
const std::vector<Diagnostic>& diagnostics) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fesa
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fesa/analysis/analysis_state.hpp"
|
||||||
|
#include "fesa/core/diagnostic.hpp"
|
||||||
|
#include "fesa/core/status.hpp"
|
||||||
|
#include "fesa/model/domain.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace fesa {
|
||||||
|
|
||||||
|
// Keeps the solver core independent of the authoritative result-storage backend.
|
||||||
|
class ResultsWriter {
|
||||||
|
public:
|
||||||
|
virtual ~ResultsWriter() = default;
|
||||||
|
|
||||||
|
virtual Status write(
|
||||||
|
const std::filesystem::path& outputPath,
|
||||||
|
const Domain& domain,
|
||||||
|
const AnalysisState& state,
|
||||||
|
const std::vector<Diagnostic>& diagnostics) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fesa
|
||||||
@@ -14,6 +14,7 @@ add_library(
|
|||||||
fem/dof_manager.cpp
|
fem/dof_manager.cpp
|
||||||
io/abaqus/domain_mapper.cpp
|
io/abaqus/domain_mapper.cpp
|
||||||
io/abaqus/input_reader.cpp
|
io/abaqus/input_reader.cpp
|
||||||
|
io/hdf5/hdf5_results_writer.cpp
|
||||||
math/matrix.cpp
|
math/matrix.cpp
|
||||||
math/sparse_matrix.cpp
|
math/sparse_matrix.cpp
|
||||||
math/vector.cpp
|
math/vector.cpp
|
||||||
@@ -33,6 +34,7 @@ target_link_libraries(
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
Fesa::MKL
|
Fesa::MKL
|
||||||
Fesa::TBB
|
Fesa::TBB
|
||||||
|
Fesa::HDF5
|
||||||
)
|
)
|
||||||
|
|
||||||
# Product warnings are strict without imposing FESA policy on external targets.
|
# Product warnings are strict without imposing FESA policy on external targets.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,10 +20,12 @@ add_executable(
|
|||||||
unit/io/abaqus/domain_mapper_test.cpp
|
unit/io/abaqus/domain_mapper_test.cpp
|
||||||
unit/io/abaqus/input_reader_test.cpp
|
unit/io/abaqus/input_reader_test.cpp
|
||||||
unit/io/abaqus/input_syntax_test.cpp
|
unit/io/abaqus/input_syntax_test.cpp
|
||||||
|
unit/io/hdf5/hdf5_results_writer_test.cpp
|
||||||
unit/model/domain_test.cpp
|
unit/model/domain_test.cpp
|
||||||
unit/model/model_types_test.cpp
|
unit/model/model_types_test.cpp
|
||||||
unit/results/result_records_test.cpp
|
unit/results/result_records_test.cpp
|
||||||
unit/results/result_recovery_test.cpp
|
unit/results/result_recovery_test.cpp
|
||||||
|
unit/results/results_writer_test.cpp
|
||||||
unit/solvers/linear/linear_solver_test.cpp
|
unit/solvers/linear/linear_solver_test.cpp
|
||||||
unit/solvers/linear/mkl_pardiso_solver_test.cpp
|
unit/solvers/linear/mkl_pardiso_solver_test.cpp
|
||||||
)
|
)
|
||||||
@@ -32,6 +34,7 @@ target_link_libraries(
|
|||||||
fesa_unit_tests
|
fesa_unit_tests
|
||||||
PRIVATE
|
PRIVATE
|
||||||
fesa_solver
|
fesa_solver
|
||||||
|
Fesa::HDF5
|
||||||
GTest::gtest_main
|
GTest::gtest_main
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,6 +43,9 @@ if(WIN32)
|
|||||||
NOT OMP_DLL_DIR OR NOT OMP_DLLNAME)
|
NOT OMP_DLL_DIR OR NOT OMP_DLLNAME)
|
||||||
message(FATAL_ERROR "The oneMKL runtime files required by tests were not resolved")
|
message(FATAL_ERROR "The oneMKL runtime files required by tests were not resolved")
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT EXISTS "${OMP_DLL_DIR}/libmmd.dll")
|
||||||
|
message(FATAL_ERROR "The Intel runtime required by the selected HDF5 DLL was not resolved")
|
||||||
|
endif()
|
||||||
|
|
||||||
file(GLOB _fesa_mkl_dispatch_dlls "${MKL_ROOT}/bin/mkl_def.*.dll")
|
file(GLOB _fesa_mkl_dispatch_dlls "${MKL_ROOT}/bin/mkl_def.*.dll")
|
||||||
if(NOT _fesa_mkl_dispatch_dlls)
|
if(NOT _fesa_mkl_dispatch_dlls)
|
||||||
@@ -65,9 +71,18 @@ if(WIN32)
|
|||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${OMP_DLL_DIR}/${OMP_DLLNAME}"
|
"${OMP_DLL_DIR}/${OMP_DLLNAME}"
|
||||||
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
"${OMP_DLL_DIR}/libmmd.dll"
|
||||||
|
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
"${_fesa_mkl_dispatch_dll}"
|
"${_fesa_mkl_dispatch_dll}"
|
||||||
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
||||||
|
# Stage runtime DLLs selected through imported targets, including the
|
||||||
|
# normalized HDF5 backend, without naming a package-specific target.
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||||
|
"$<TARGET_RUNTIME_DLLS:fesa_unit_tests>"
|
||||||
|
"$<TARGET_FILE_DIR:fesa_unit_tests>"
|
||||||
|
COMMAND_EXPAND_LISTS
|
||||||
)
|
)
|
||||||
|
|
||||||
unset(_fesa_mkl_dispatch_dll)
|
unset(_fesa_mkl_dispatch_dll)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
|||||||
|
#include "fesa/results/results_writer.hpp"
|
||||||
|
|
||||||
|
#include "fesa/analysis/analysis_state.hpp"
|
||||||
|
#include "fesa/core/diagnostic.hpp"
|
||||||
|
#include "fesa/core/status.hpp"
|
||||||
|
#include "fesa/model/domain.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using WriteSignature = fesa::Status (fesa::ResultsWriter::*)(
|
||||||
|
const std::filesystem::path&,
|
||||||
|
const fesa::Domain&,
|
||||||
|
const fesa::AnalysisState&,
|
||||||
|
const std::vector<fesa::Diagnostic>&);
|
||||||
|
|
||||||
|
static_assert(std::has_virtual_destructor_v<fesa::ResultsWriter>);
|
||||||
|
static_assert(std::is_abstract_v<fesa::ResultsWriter>);
|
||||||
|
static_assert(std::is_same_v<decltype(&fesa::ResultsWriter::write), WriteSignature>);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
Reference in New Issue
Block a user