feat(cpp-object-oriented-modular-refactoring): step 5 - solver-workflow-google-style
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
|
||||
#include "fesa/io/hdf5/hdf5_results_writer.hpp"
|
||||
|
||||
#include "fesa/analysis/analysis_model.hpp"
|
||||
#include "fesa/analysis/analysis_model.h"
|
||||
#include "fesa/build_info.h"
|
||||
#include "fesa/fem/dof_manager.hpp"
|
||||
#include "fesa/fem/dof_manager.h"
|
||||
|
||||
#include <hdf5.h>
|
||||
|
||||
@@ -389,38 +389,38 @@ Status validateShellWriterInput(
|
||||
std::size_t expectedRows = 0U;
|
||||
if (!sizeProductFits(
|
||||
domain.ShellElements().size(), kShellLocationCount, expectedRows) ||
|
||||
state.shellResults().size() != expectedRows) {
|
||||
state.ShellResults().size() != expectedRows) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Shell output requires exactly GP1 through GP4 for every shell element.");
|
||||
}
|
||||
const double gauss = 1.0 / std::sqrt(3.0);
|
||||
const std::array<ShellMidsurfaceLocation, kShellLocationCount> locations{
|
||||
ShellMidsurfaceLocation::gp1,
|
||||
ShellMidsurfaceLocation::gp2,
|
||||
ShellMidsurfaceLocation::gp3,
|
||||
ShellMidsurfaceLocation::gp4};
|
||||
ShellMidsurfaceLocation::kGp1,
|
||||
ShellMidsurfaceLocation::kGp2,
|
||||
ShellMidsurfaceLocation::kGp3,
|
||||
ShellMidsurfaceLocation::kGp4};
|
||||
const std::array<std::array<double, 2>, kShellLocationCount> coordinates{{
|
||||
{-gauss, -gauss},
|
||||
{gauss, -gauss},
|
||||
{gauss, gauss},
|
||||
{-gauss, gauss}}};
|
||||
const std::array<ShellSectionPosition, kShellSectionPositionCount> positions{
|
||||
ShellSectionPosition::bottom,
|
||||
ShellSectionPosition::middle,
|
||||
ShellSectionPosition::top};
|
||||
ShellSectionPosition::kBottom,
|
||||
ShellSectionPosition::kMiddle,
|
||||
ShellSectionPosition::kTop};
|
||||
constexpr std::array<double, kShellSectionPositionCount> zeta{-1.0, 0.0, 1.0};
|
||||
for (std::size_t rowIndex = 0U;
|
||||
rowIndex < state.shellResults().size();
|
||||
rowIndex < state.ShellResults().size();
|
||||
++rowIndex) {
|
||||
const auto& row = state.shellResults()[rowIndex];
|
||||
const auto& row = state.ShellResults()[rowIndex];
|
||||
const std::size_t element = rowIndex / kShellLocationCount;
|
||||
const std::size_t location = rowIndex % kShellLocationCount;
|
||||
if (row.element != element || row.location != locations[location] ||
|
||||
row.naturalCoordinates != coordinates[location] ||
|
||||
!isOrthonormalRightHanded(row.localFrame) ||
|
||||
!isFinite(row.generalizedStrain) ||
|
||||
!isFinite(row.sectionResultant)) {
|
||||
row.natural_coordinates != coordinates[location] ||
|
||||
!isOrthonormalRightHanded(row.local_frame) ||
|
||||
!isFinite(row.generalized_strain) ||
|
||||
!isFinite(row.section_resultant)) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Shell result rows must be finite and preserve element/GP/frame identity.");
|
||||
@@ -437,9 +437,9 @@ Status validateShellWriterInput(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!std::isfinite(state.physicalStrainEnergy()) ||
|
||||
!isFinite(state.equilibrium()) ||
|
||||
!isFinite(state.verificationMetrics())) {
|
||||
if (!std::isfinite(state.PhysicalStrainEnergy()) ||
|
||||
!isFinite(state.Equilibrium()) ||
|
||||
!isFinite(state.VerificationMetrics())) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Shell energy, equilibrium, and verification metrics must be finite.");
|
||||
@@ -457,8 +457,8 @@ Status validateWriterInput(
|
||||
return outputFailure(
|
||||
"invalid-output-path", "The HDF5 output path must name a file.");
|
||||
}
|
||||
if (state.identity().stepName != kStepName ||
|
||||
state.identity().frameIndex != kFrameIndex) {
|
||||
if (state.Identity().step_name != kStepName ||
|
||||
state.Identity().frame_index != kFrameIndex) {
|
||||
return outputFailure(
|
||||
"invalid-result-state",
|
||||
"Schema v0 requires literal Step-1 and frame index 0.");
|
||||
@@ -470,7 +470,7 @@ Status validateWriterInput(
|
||||
if (!shellValidation.IsOk()) {
|
||||
return shellValidation;
|
||||
}
|
||||
} else if (!state.shellResults().empty()) {
|
||||
} else if (!state.ShellResults().empty()) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Beam output cannot contain shell recovery rows.");
|
||||
@@ -482,11 +482,11 @@ Status validateWriterInput(
|
||||
"invalid-result-state", "The nodal result shape overflows size_t.");
|
||||
}
|
||||
const std::array<const Vector*, 5> vectors = {
|
||||
&state.displacement(),
|
||||
&state.externalForce(),
|
||||
&state.internalForce(),
|
||||
&state.residual(),
|
||||
&state.reaction()};
|
||||
&state.Displacement(),
|
||||
&state.ExternalForce(),
|
||||
&state.InternalForce(),
|
||||
&state.Residual(),
|
||||
&state.Reaction()};
|
||||
for (const Vector* vector : vectors) {
|
||||
if (vector->Size() != fullDofCount) {
|
||||
return outputFailure(
|
||||
@@ -542,42 +542,42 @@ Status validateWriterInput(
|
||||
std::size_t gaussCount = 0U;
|
||||
if (!sizeProductFits(domain.Elements().size(), kEndpointCount, endpointCount) ||
|
||||
!sizeProductFits(domain.Elements().size(), kGaussPointCount, gaussCount) ||
|
||||
state.endpointResults().size() != endpointCount ||
|
||||
state.gaussResults().size() != gaussCount) {
|
||||
state.EndpointResults().size() != endpointCount ||
|
||||
state.GaussResults().size() != gaussCount) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Endpoint and Gauss row counts must match every element and location.");
|
||||
}
|
||||
for (std::size_t rowIndex = 0U;
|
||||
rowIndex < state.endpointResults().size();
|
||||
rowIndex < state.EndpointResults().size();
|
||||
++rowIndex) {
|
||||
const EntityIndex expectedElement =
|
||||
static_cast<EntityIndex>(rowIndex / kEndpointCount);
|
||||
const int expectedEndpoint = static_cast<int>(rowIndex % kEndpointCount);
|
||||
const EndpointResultRow& row = state.endpointResults()[rowIndex];
|
||||
const EndpointResultRow& row = state.EndpointResults()[rowIndex];
|
||||
const auto& element = domain.Elements()[expectedElement];
|
||||
const auto& expectedNode =
|
||||
domain.Nodes()[element.node_indices[static_cast<std::size_t>(expectedEndpoint)]];
|
||||
if (row.element != expectedElement || row.endpoint != expectedEndpoint ||
|
||||
!sameIdentity(row.node, expectedNode.source_id) ||
|
||||
!isFinite(row.endAction) || !isFinite(row.sectionResultant)) {
|
||||
!isFinite(row.end_action) || !isFinite(row.section_resultant)) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Endpoint result rows must follow element/endpoint order and identity.");
|
||||
}
|
||||
}
|
||||
for (std::size_t rowIndex = 0U;
|
||||
rowIndex < state.gaussResults().size();
|
||||
rowIndex < state.GaussResults().size();
|
||||
++rowIndex) {
|
||||
const EntityIndex expectedElement =
|
||||
static_cast<EntityIndex>(rowIndex / kGaussPointCount);
|
||||
const int expectedGaussPoint =
|
||||
static_cast<int>(rowIndex % kGaussPointCount) + 1;
|
||||
const GaussResultRow& row = state.gaussResults()[rowIndex];
|
||||
const GaussResultRow& row = state.GaussResults()[rowIndex];
|
||||
if (row.element != expectedElement ||
|
||||
row.gaussPoint != expectedGaussPoint ||
|
||||
!isFinite(row.generalizedStrain) ||
|
||||
!isFinite(row.generalizedResultant)) {
|
||||
row.gauss_point != expectedGaussPoint ||
|
||||
!isFinite(row.generalized_strain) ||
|
||||
!isFinite(row.generalized_resultant)) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Gauss result rows must follow element/Gauss order and identity.");
|
||||
@@ -594,19 +594,19 @@ Status validateWriterInput(
|
||||
for (std::size_t gauss = 0U; gauss < kGaussPointCount; ++gauss) {
|
||||
const std::size_t count = sectionPoints.empty() ? 1U : sectionPoints.size();
|
||||
for (std::size_t point = 0U; point < count; ++point) {
|
||||
if (stressIndex >= state.stressResults().size()) {
|
||||
if (stressIndex >= state.StressResults().size()) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows",
|
||||
"Axial stress rows are missing required element/Gauss/section locations.");
|
||||
}
|
||||
const StressS11Row& row = state.stressResults()[stressIndex++];
|
||||
const StressS11Row& row = state.StressResults()[stressIndex++];
|
||||
const std::size_t expectedPoint = sectionPoints.empty() ? 0U : point + 1U;
|
||||
const double expectedX1 = sectionPoints.empty() ? 0.0 : sectionPoints[point][0U];
|
||||
const double expectedX2 = sectionPoints.empty() ? 0.0 : sectionPoints[point][1U];
|
||||
const char* expectedSource = sectionPoints.empty() ? "fesa-default" : "input";
|
||||
if (row.element != static_cast<EntityIndex>(elementIndex) ||
|
||||
row.gaussPoint != static_cast<int>(gauss + 1U) ||
|
||||
row.sectionPoint != expectedPoint ||
|
||||
row.gauss_point != static_cast<int>(gauss + 1U) ||
|
||||
row.section_point != expectedPoint ||
|
||||
row.x1 != expectedX1 || row.x2 != expectedX2 ||
|
||||
row.source != expectedSource || !isValidUtf8(row.source) ||
|
||||
!std::isfinite(row.x1) || !std::isfinite(row.x2) ||
|
||||
@@ -618,7 +618,7 @@ Status validateWriterInput(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stressIndex != state.stressResults().size()) {
|
||||
if (stressIndex != state.StressResults().size()) {
|
||||
return outputFailure(
|
||||
"invalid-result-rows", "Axial stress output contains extra rows.");
|
||||
}
|
||||
@@ -635,7 +635,7 @@ Status validateWriterInput(
|
||||
}
|
||||
|
||||
|
||||
auto analysisModelResult = AnalysisModel::create(domain);
|
||||
auto analysisModelResult = AnalysisModel::Create(domain);
|
||||
if (!analysisModelResult.HasValue()) {
|
||||
return outputFailure(
|
||||
"invalid-result-state",
|
||||
@@ -643,7 +643,7 @@ Status validateWriterInput(
|
||||
}
|
||||
const AnalysisModel analysisModel =
|
||||
std::move(analysisModelResult.Value());
|
||||
auto dofResult = DofManager::create(analysisModel);
|
||||
auto dofResult = DofManager::Create(analysisModel);
|
||||
if (!dofResult.HasValue()) {
|
||||
return outputFailure(
|
||||
"invalid-result-state",
|
||||
@@ -652,16 +652,16 @@ Status validateWriterInput(
|
||||
const DofManager dofs = std::move(dofResult.Value());
|
||||
modelData.constraintMask.assign(fullDofCount, 0U);
|
||||
modelData.prescribedDisplacement.assign(fullDofCount, 0.0);
|
||||
if (dofs.constrainedDofs().size() != dofs.prescribedValues().Size()) {
|
||||
if (dofs.ConstrainedDofs().size() != dofs.PrescribedValues().Size()) {
|
||||
return outputFailure(
|
||||
"invalid-result-state",
|
||||
"Constraint identities and prescribed values have inconsistent sizes.");
|
||||
}
|
||||
for (std::size_t index = 0U;
|
||||
index < dofs.constrainedDofs().size();
|
||||
index < dofs.ConstrainedDofs().size();
|
||||
++index) {
|
||||
const std::size_t fullDof = dofs.constrainedDofs()[index];
|
||||
const double prescribed = dofs.prescribedValues()[index];
|
||||
const std::size_t fullDof = dofs.ConstrainedDofs()[index];
|
||||
const double prescribed = dofs.PrescribedValues()[index];
|
||||
if (fullDof >= fullDofCount || !std::isfinite(prescribed)) {
|
||||
return outputFailure(
|
||||
"invalid-result-state",
|
||||
@@ -1422,9 +1422,9 @@ std::vector<double> flattenEndpointValues(
|
||||
for (const auto& row : rows) {
|
||||
if (sectionResultants) {
|
||||
values.insert(
|
||||
values.end(), row.sectionResultant.begin(), row.sectionResultant.end());
|
||||
values.end(), row.section_resultant.begin(), row.section_resultant.end());
|
||||
} else {
|
||||
values.insert(values.end(), row.endAction.begin(), row.endAction.end());
|
||||
values.insert(values.end(), row.end_action.begin(), row.end_action.end());
|
||||
}
|
||||
}
|
||||
return values;
|
||||
@@ -1437,7 +1437,7 @@ std::vector<double> flattenGaussValues(
|
||||
values.reserve(rows.size() * kGeneralizedComponentCount);
|
||||
for (const auto& row : rows) {
|
||||
const auto& rowValues =
|
||||
resultants ? row.generalizedResultant : row.generalizedStrain;
|
||||
resultants ? row.generalized_resultant : row.generalized_strain;
|
||||
values.insert(values.end(), rowValues.begin(), rowValues.end());
|
||||
}
|
||||
return values;
|
||||
@@ -1445,12 +1445,12 @@ std::vector<double> flattenGaussValues(
|
||||
|
||||
void writeStress(const hid_t file, const AnalysisState& state) {
|
||||
std::vector<StressWriteRow> rows;
|
||||
rows.reserve(state.stressResults().size());
|
||||
for (const auto& row : state.stressResults()) {
|
||||
rows.reserve(state.StressResults().size());
|
||||
for (const auto& row : state.StressResults()) {
|
||||
rows.push_back({
|
||||
static_cast<std::uint64_t>(row.element),
|
||||
static_cast<std::uint64_t>(row.gaussPoint),
|
||||
static_cast<std::uint64_t>(row.sectionPoint),
|
||||
static_cast<std::uint64_t>(row.gauss_point),
|
||||
static_cast<std::uint64_t>(row.section_point),
|
||||
row.x1,
|
||||
row.x2,
|
||||
row.source.c_str(),
|
||||
@@ -1544,26 +1544,26 @@ void writeShellResultDatasets(
|
||||
std::vector<double> generalizedStrains;
|
||||
std::vector<double> sectionResultants;
|
||||
std::vector<double> stresses;
|
||||
localFrames.reserve(state.shellResults().size() * 9U);
|
||||
localFrames.reserve(state.ShellResults().size() * 9U);
|
||||
generalizedStrains.reserve(
|
||||
state.shellResults().size() * kShellGeneralizedComponentCount);
|
||||
state.ShellResults().size() * kShellGeneralizedComponentCount);
|
||||
sectionResultants.reserve(
|
||||
state.shellResults().size() * kShellGeneralizedComponentCount);
|
||||
state.ShellResults().size() * kShellGeneralizedComponentCount);
|
||||
stresses.reserve(
|
||||
state.shellResults().size() * kShellSectionPositionCount *
|
||||
state.ShellResults().size() * kShellSectionPositionCount *
|
||||
kShellStressComponentCount);
|
||||
for (const auto& row : state.shellResults()) {
|
||||
for (const auto& axis : row.localFrame) {
|
||||
for (const auto& row : state.ShellResults()) {
|
||||
for (const auto& axis : row.local_frame) {
|
||||
localFrames.insert(localFrames.end(), axis.begin(), axis.end());
|
||||
}
|
||||
generalizedStrains.insert(
|
||||
generalizedStrains.end(),
|
||||
row.generalizedStrain.begin(),
|
||||
row.generalizedStrain.end());
|
||||
row.generalized_strain.begin(),
|
||||
row.generalized_strain.end());
|
||||
sectionResultants.insert(
|
||||
sectionResultants.end(),
|
||||
row.sectionResultant.begin(),
|
||||
row.sectionResultant.end());
|
||||
row.section_resultant.begin(),
|
||||
row.section_resultant.end());
|
||||
for (const auto& position : row.stress) {
|
||||
stresses.insert(
|
||||
stresses.end(),
|
||||
@@ -1624,22 +1624,22 @@ void writeShellResultDatasets(
|
||||
"shell-local", "section-position");
|
||||
writeShellResultIdentity(file, stressPath, true);
|
||||
|
||||
const double energy = state.physicalStrainEnergy();
|
||||
const double energy = state.PhysicalStrainEnergy();
|
||||
writeDoubleDataset(
|
||||
file, std::string{kStepRoot} + "/global/energy", {1U},
|
||||
&energy, 1U, "PHYSICAL_STRAIN_ENERGY", "force*length",
|
||||
"global", "global");
|
||||
writeDoubleDataset(
|
||||
file, std::string{kStepRoot} + "/global/equilibrium", {6U},
|
||||
state.equilibrium().data(), state.equilibrium().size(),
|
||||
state.Equilibrium().data(), state.Equilibrium().size(),
|
||||
"FORCE_1,FORCE_2,FORCE_3,MOMENT_1,MOMENT_2,MOMENT_3",
|
||||
"force,force,force,force*length,force*length,force*length",
|
||||
"global-cartesian", "global-origin");
|
||||
const std::string metricsPath =
|
||||
std::string{kStepRoot} + "/global/verification_metrics";
|
||||
writeDoubleDataset(
|
||||
file, metricsPath, {3U}, state.verificationMetrics().data(),
|
||||
state.verificationMetrics().size(),
|
||||
file, metricsPath, {3U}, state.VerificationMetrics().data(),
|
||||
state.VerificationMetrics().size(),
|
||||
"FREE_RESIDUAL_NORMALIZED,FORCE_BALANCE_NORMALIZED,MOMENT_BALANCE_NORMALIZED",
|
||||
"1,1,1", "global", "verification");
|
||||
{
|
||||
@@ -1735,8 +1735,8 @@ void writeResultDatasets(
|
||||
file,
|
||||
std::string{kStepRoot} + "/nodal/displacement",
|
||||
nodalDimensions,
|
||||
state.displacement().Data(),
|
||||
state.displacement().Size(),
|
||||
state.Displacement().Data(),
|
||||
state.Displacement().Size(),
|
||||
"UX,UY,UZ,URX,URY,URZ",
|
||||
"length,length,length,radian,radian,radian",
|
||||
"global-cartesian",
|
||||
@@ -1745,8 +1745,8 @@ void writeResultDatasets(
|
||||
file,
|
||||
std::string{kStepRoot} + "/nodal/reaction",
|
||||
nodalDimensions,
|
||||
state.reaction().Data(),
|
||||
state.reaction().Size(),
|
||||
state.Reaction().Data(),
|
||||
state.Reaction().Size(),
|
||||
"RF1,RF2,RF3,RM1,RM2,RM3",
|
||||
"force,force,force,force*length,force*length,force*length",
|
||||
"global-cartesian",
|
||||
@@ -1765,7 +1765,7 @@ void writeResultDatasets(
|
||||
static_cast<hsize_t>(domain.Elements().size()),
|
||||
kEndpointCount,
|
||||
kGeneralizedComponentCount};
|
||||
const auto endActions = flattenEndpointValues(state.endpointResults(), false);
|
||||
const auto endActions = flattenEndpointValues(state.EndpointResults(), false);
|
||||
writeDoubleDataset(
|
||||
file,
|
||||
std::string{kStepRoot} + "/element/end_force_local",
|
||||
@@ -1777,7 +1777,7 @@ void writeResultDatasets(
|
||||
"beam-local",
|
||||
"endpoint-outward-action");
|
||||
const auto sectionResultants =
|
||||
flattenEndpointValues(state.endpointResults(), true);
|
||||
flattenEndpointValues(state.EndpointResults(), true);
|
||||
writeDoubleDataset(
|
||||
file,
|
||||
std::string{kStepRoot} + "/element/section_resultant",
|
||||
@@ -1789,7 +1789,7 @@ void writeResultDatasets(
|
||||
"beam-local",
|
||||
"endpoint-positive-local-x-section-cut");
|
||||
const auto generalizedStrains =
|
||||
flattenGaussValues(state.gaussResults(), false);
|
||||
flattenGaussValues(state.GaussResults(), false);
|
||||
writeDoubleDataset(
|
||||
file,
|
||||
std::string{kStepRoot} + "/element/generalized_strain",
|
||||
@@ -1801,7 +1801,7 @@ void writeResultDatasets(
|
||||
"beam-local",
|
||||
"integration-point");
|
||||
const auto generalizedResultants =
|
||||
flattenGaussValues(state.gaussResults(), true);
|
||||
flattenGaussValues(state.GaussResults(), true);
|
||||
writeDoubleDataset(
|
||||
file,
|
||||
std::string{kStepRoot} + "/element/generalized_resultant",
|
||||
@@ -2494,7 +2494,7 @@ void selfCheckFile(
|
||||
"beam-local", "integration-point");
|
||||
requireCompoundDataset(
|
||||
file.get(), "/steps/Step-1/frames/0/element/stress_s11",
|
||||
static_cast<hsize_t>(state.stressResults().size()),
|
||||
static_cast<hsize_t>(state.StressResults().size()),
|
||||
{"internal_element_id", "gauss_point_index", "section_point_index",
|
||||
"x1", "x2", "source", "S11"});
|
||||
auto stress = openDatasetForCheck(
|
||||
@@ -2563,7 +2563,7 @@ bool finalizeFile(
|
||||
|
||||
} // namespace
|
||||
|
||||
Status Hdf5ResultsWriter::write(
|
||||
Status Hdf5ResultsWriter::Write(
|
||||
const std::filesystem::path& outputPath,
|
||||
const Domain& domain,
|
||||
const AnalysisState& state,
|
||||
|
||||
Reference in New Issue
Block a user