124 lines
4.0 KiB
C++
124 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include "fesa/Core/Core.hpp"
|
|
|
|
#include <array>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace fesa {
|
|
|
|
struct FieldOutput {
|
|
std::string name;
|
|
std::string position = "NODAL";
|
|
std::string entity_type = "node";
|
|
std::string basis = "GLOBAL";
|
|
std::string description;
|
|
std::vector<GlobalId> entity_ids;
|
|
std::vector<std::string> component_labels;
|
|
std::vector<std::array<Real, 6>> values;
|
|
};
|
|
|
|
struct ResultFrame {
|
|
LocalIndex frame_id = 0;
|
|
LocalIndex increment = 1;
|
|
LocalIndex iteration = 0;
|
|
Real step_time = 1.0;
|
|
Real total_time = 1.0;
|
|
bool converged = true;
|
|
std::string description = "Phase 1 linear static frame";
|
|
std::map<std::string, FieldOutput> field_outputs;
|
|
};
|
|
|
|
struct ResultStep {
|
|
std::string name;
|
|
std::vector<ResultFrame> frames;
|
|
};
|
|
|
|
struct ResultFile {
|
|
std::string schema_name = "FESA_RESULTS";
|
|
LocalIndex schema_version = 1;
|
|
std::string solver_name = "FESA";
|
|
std::string dof_convention = "UX,UY,UZ,RX,RY,RZ";
|
|
std::string sign_convention = "Abaqus-compatible";
|
|
std::string precision = "double";
|
|
std::string index_type = "int64";
|
|
std::vector<GlobalId> node_ids;
|
|
std::vector<Vec3> coordinates;
|
|
std::vector<GlobalId> element_ids;
|
|
std::vector<std::string> element_types;
|
|
std::vector<std::array<GlobalId, 4>> connectivity;
|
|
std::vector<ResultStep> steps;
|
|
};
|
|
|
|
class InMemoryResultsWriter {
|
|
public:
|
|
void writeLinearStatic(const Domain& domain,
|
|
const DofManager& dofs,
|
|
const std::vector<Real>& u_full,
|
|
const std::vector<Real>& rf_full) {
|
|
const auto model = buildLinearStaticAnalysisModel(domain);
|
|
writeLinearStatic(domain, model, dofs, u_full, rf_full);
|
|
}
|
|
|
|
void writeLinearStatic(const Domain& domain,
|
|
const AnalysisModel& model,
|
|
const DofManager& dofs,
|
|
const std::vector<Real>& u_full,
|
|
const std::vector<Real>& rf_full) {
|
|
result_ = ResultFile{};
|
|
for (const auto& [node_id, node] : domain.nodes) {
|
|
result_.node_ids.push_back(node_id);
|
|
result_.coordinates.push_back(node.coordinates);
|
|
}
|
|
for (const auto& [element_id, element] : domain.elements) {
|
|
result_.element_ids.push_back(element_id);
|
|
result_.element_types.push_back(elementTypeLabel(element.type));
|
|
result_.connectivity.push_back(element.node_ids);
|
|
}
|
|
ResultStep step;
|
|
step.name = model.step.name.empty() ? "Step-1" : model.step.name;
|
|
ResultFrame frame;
|
|
frame.frame_id = 0;
|
|
frame.field_outputs["U"] = buildNodalField("U", displacementComponentLabels(), "Nodal displacement and rotation", domain, dofs, u_full);
|
|
frame.field_outputs["RF"] = buildNodalField("RF", reactionComponentLabels(), "Nodal reaction force and moment", domain, dofs, rf_full);
|
|
step.frames.push_back(frame);
|
|
result_.steps.push_back(step);
|
|
}
|
|
|
|
const ResultFile& result() const {
|
|
return result_;
|
|
}
|
|
|
|
private:
|
|
static FieldOutput buildNodalField(const std::string& name,
|
|
const std::vector<std::string>& labels,
|
|
const std::string& description,
|
|
const Domain& domain,
|
|
const DofManager& dofs,
|
|
const std::vector<Real>& full_values) {
|
|
FieldOutput field;
|
|
field.name = name;
|
|
field.position = "NODAL";
|
|
field.entity_type = "node";
|
|
field.basis = "GLOBAL";
|
|
field.description = description;
|
|
field.component_labels = labels;
|
|
for (const auto& [node_id, node] : domain.nodes) {
|
|
(void)node;
|
|
field.entity_ids.push_back(node_id);
|
|
std::array<Real, 6> values{};
|
|
for (Dof dof : allDofs()) {
|
|
values[static_cast<std::size_t>(dofIndex(dof))] = full_values[static_cast<std::size_t>(dofs.fullIndex(node_id, dof))];
|
|
}
|
|
field.values.push_back(values);
|
|
}
|
|
return field;
|
|
}
|
|
|
|
ResultFile result_;
|
|
};
|
|
|
|
} // namespace fesa
|