This commit is contained in:
김경종
2026-06-10 10:03:11 +09:00
parent 87529c811a
commit 0912ee6f3b
174 changed files with 414 additions and 8544 deletions
-24
View File
@@ -1,24 +0,0 @@
#include "fesa/boundary/SinglePointConstraint.hpp"
namespace fesa::boundary {
SinglePointConstraint::SinglePointConstraint(NodeId node_id, Dof dof, double value)
: node_id_(node_id), dof_(dof), value_(value) {}
BoundaryConditionKind SinglePointConstraint::kind() const noexcept {
return BoundaryConditionKind::SinglePointConstraint;
}
NodeId SinglePointConstraint::nodeId() const noexcept {
return node_id_;
}
Dof SinglePointConstraint::dof() const noexcept {
return dof_;
}
double SinglePointConstraint::value() const noexcept {
return value_;
}
} // namespace fesa::boundary
-115
View File
@@ -1,115 +0,0 @@
#include "fesa/core/AnalysisState.hpp"
#include <algorithm>
#include <stdexcept>
#include <utility>
namespace fesa::core {
AnalysisState::AnalysisState()
: AnalysisState(0) {}
AnalysisState::AnalysisState(std::size_t dof_count)
: dof_count_(0),
current_time_(0.0),
increment_index_(0),
iteration_index_(0) {
resize(dof_count);
}
std::size_t AnalysisState::dofCount() const noexcept {
return dof_count_;
}
void AnalysisState::resize(std::size_t dof_count) {
dof_count_ = dof_count;
displacement_.assign(dof_count_, 0.0);
external_force_.assign(dof_count_, 0.0);
internal_force_.assign(dof_count_, 0.0);
residual_.assign(dof_count_, 0.0);
reaction_.assign(dof_count_, 0.0);
}
const std::vector<double>& AnalysisState::displacement() const noexcept {
return displacement_;
}
const std::vector<double>& AnalysisState::externalForce() const noexcept {
return external_force_;
}
const std::vector<double>& AnalysisState::internalForce() const noexcept {
return internal_force_;
}
const std::vector<double>& AnalysisState::residual() const noexcept {
return residual_;
}
const std::vector<double>& AnalysisState::reaction() const noexcept {
return reaction_;
}
void AnalysisState::setDisplacement(std::vector<double> values) {
setVector(displacement_, std::move(values));
}
void AnalysisState::setExternalForce(std::vector<double> values) {
setVector(external_force_, std::move(values));
}
void AnalysisState::setInternalForce(std::vector<double> values) {
setVector(internal_force_, std::move(values));
}
void AnalysisState::setResidual(std::vector<double> values) {
setVector(residual_, std::move(values));
}
void AnalysisState::setReaction(std::vector<double> values) {
setVector(reaction_, std::move(values));
}
void AnalysisState::clearForces() noexcept {
zero(external_force_);
zero(internal_force_);
zero(residual_);
zero(reaction_);
}
double AnalysisState::currentTime() const noexcept {
return current_time_;
}
void AnalysisState::setCurrentTime(double value) noexcept {
current_time_ = value;
}
std::int64_t AnalysisState::incrementIndex() const noexcept {
return increment_index_;
}
void AnalysisState::setIncrementIndex(std::int64_t value) noexcept {
increment_index_ = value;
}
std::int64_t AnalysisState::iterationIndex() const noexcept {
return iteration_index_;
}
void AnalysisState::setIterationIndex(std::int64_t value) noexcept {
iteration_index_ = value;
}
void AnalysisState::setVector(std::vector<double>& target, std::vector<double> values) {
if (values.size() != dof_count_) {
throw std::invalid_argument("analysis state vector size mismatch");
}
target = std::move(values);
}
void AnalysisState::zero(std::vector<double>& values) noexcept {
std::fill(values.begin(), values.end(), 0.0);
}
} // namespace fesa::core
-470
View File
@@ -1,470 +0,0 @@
#include "fesa/core/Domain.hpp"
#include "fesa/boundary/SinglePointConstraint.hpp"
#include "fesa/core/BoundaryCondition.hpp"
#include "fesa/core/ElementDefinition.hpp"
#include "fesa/core/LoadDefinition.hpp"
#include "fesa/core/MaterialDefinition.hpp"
#include "fesa/core/PropertyDefinition.hpp"
#include "fesa/load/NodalLoad.hpp"
#include <stdexcept>
#include <utility>
namespace fesa::core {
BoundaryCondition::BoundaryCondition(NodeId node_id, Dof dof, double value)
: node_id_(node_id), dof_(dof), value_(value) {}
NodeId BoundaryCondition::nodeId() const noexcept {
return node_id_;
}
Dof BoundaryCondition::dof() const noexcept {
return dof_;
}
double BoundaryCondition::value() const noexcept {
return value_;
}
ElementDefinition::ElementDefinition(
ElementId id,
ElementType type,
std::array<NodeId, 4> connectivity,
PropertyId property_id)
: id_(id), type_(type), connectivity_(connectivity), property_id_(property_id) {}
ElementId ElementDefinition::id() const noexcept {
return id_;
}
ElementType ElementDefinition::type() const noexcept {
return type_;
}
const std::array<NodeId, 4>& ElementDefinition::connectivity() const noexcept {
return connectivity_;
}
PropertyId ElementDefinition::propertyId() const noexcept {
return property_id_;
}
LinearElasticMaterialDefinition::LinearElasticMaterialDefinition(
MaterialId id,
double young_modulus,
double poisson_ratio)
: id_(id), young_modulus_(young_modulus), poisson_ratio_(poisson_ratio) {}
MaterialId LinearElasticMaterialDefinition::id() const noexcept {
return id_;
}
double LinearElasticMaterialDefinition::youngModulus() const noexcept {
return young_modulus_;
}
double LinearElasticMaterialDefinition::poissonRatio() const noexcept {
return poisson_ratio_;
}
LinearStaticStepDefinition::LinearStaticStepDefinition(
StepId id,
std::string name,
std::vector<std::size_t> boundary_condition_indices,
std::vector<std::size_t> load_indices)
: id_(id),
name_(std::move(name)),
boundary_condition_indices_(std::move(boundary_condition_indices)),
load_indices_(std::move(load_indices)) {}
StepId LinearStaticStepDefinition::id() const noexcept {
return id_;
}
const std::string& LinearStaticStepDefinition::name() const noexcept {
return name_;
}
const std::vector<std::size_t>& LinearStaticStepDefinition::boundaryConditionIndices() const noexcept {
return boundary_condition_indices_;
}
const std::vector<std::size_t>& LinearStaticStepDefinition::loadIndices() const noexcept {
return load_indices_;
}
NodalLoadDefinition::NodalLoadDefinition(NodeId node_id, Dof dof, double value)
: node_id_(node_id), dof_(dof), value_(value) {}
NodeId NodalLoadDefinition::nodeId() const noexcept {
return node_id_;
}
Dof NodalLoadDefinition::dof() const noexcept {
return dof_;
}
double NodalLoadDefinition::value() const noexcept {
return value_;
}
Node::Node(NodeId id, double x, double y, double z)
: id_(id), coordinates_{x, y, z} {}
NodeId Node::id() const noexcept {
return id_;
}
double Node::x() const noexcept {
return coordinates_[0];
}
double Node::y() const noexcept {
return coordinates_[1];
}
double Node::z() const noexcept {
return coordinates_[2];
}
const std::array<double, 3>& Node::coordinates() const noexcept {
return coordinates_;
}
ShellPropertyDefinition::ShellPropertyDefinition(
PropertyId id,
MaterialId material_id,
double thickness)
: id_(id), material_id_(material_id), thickness_(thickness) {}
PropertyId ShellPropertyDefinition::id() const noexcept {
return id_;
}
MaterialId ShellPropertyDefinition::materialId() const noexcept {
return material_id_;
}
double ShellPropertyDefinition::thickness() const noexcept {
return thickness_;
}
void Domain::addNode(Node node) {
const NodeId id = node.id();
const auto inserted = nodes_.emplace(id, std::move(node));
if (!inserted.second) {
throw std::invalid_argument("duplicate node id");
}
}
void Domain::addElement(std::unique_ptr<fesa::element::Element> element) {
if (!element) {
throw std::invalid_argument("element is null");
}
const ElementId id = element->id();
if (elements_.find(id) != elements_.end()) {
throw std::invalid_argument("duplicate element id");
}
for (const NodeId node_id : element->connectivity()) {
if (findNode(node_id) == nullptr) {
throw std::invalid_argument("element references missing node id");
}
}
if (findProperty(element->propertyId()) == nullptr) {
throw std::invalid_argument("element references missing property id");
}
elements_.emplace(id, std::move(element));
}
void Domain::addMaterial(std::unique_ptr<fesa::material::Material> material) {
if (!material) {
throw std::invalid_argument("material is null");
}
const MaterialId id = material->id();
const auto inserted = materials_.emplace(id, std::move(material));
if (!inserted.second) {
throw std::invalid_argument("duplicate material id");
}
}
void Domain::addProperty(std::unique_ptr<fesa::property::Property> property) {
if (!property) {
throw std::invalid_argument("property is null");
}
const PropertyId id = property->id();
if (properties_.find(id) != properties_.end()) {
throw std::invalid_argument("duplicate property id");
}
if (property->kind() == fesa::property::PropertyKind::Shell) {
const auto* shell_property = dynamic_cast<const fesa::property::ShellProperty*>(property.get());
if (shell_property == nullptr) {
throw std::invalid_argument("shell property kind does not match shell property type");
}
if (findMaterial(shell_property->materialId()) == nullptr) {
throw std::invalid_argument("shell property references missing material id");
}
}
properties_.emplace(id, std::move(property));
}
void Domain::addShellProperty(std::unique_ptr<fesa::property::ShellProperty> property) {
addProperty(std::move(property));
}
void Domain::addNodeSet(std::string name, std::vector<NodeId> node_ids) {
if (node_sets_.find(name) != node_sets_.end()) {
throw std::invalid_argument("duplicate node set name");
}
for (const NodeId node_id : node_ids) {
if (findNode(node_id) == nullptr) {
throw std::invalid_argument("node set references missing node id");
}
}
node_sets_.emplace(std::move(name), std::move(node_ids));
}
void Domain::addElementSet(std::string name, std::vector<ElementId> element_ids) {
if (element_sets_.find(name) != element_sets_.end()) {
throw std::invalid_argument("duplicate element set name");
}
for (const ElementId element_id : element_ids) {
if (findElement(element_id) == nullptr) {
throw std::invalid_argument("element set references missing element id");
}
}
element_sets_.emplace(std::move(name), std::move(element_ids));
}
std::size_t Domain::addBoundaryCondition(std::unique_ptr<fesa::boundary::BoundaryCondition> boundary) {
if (!boundary) {
throw std::invalid_argument("boundary condition is null");
}
if (const auto* spc = dynamic_cast<const fesa::boundary::SinglePointConstraint*>(boundary.get())) {
if (findNode(spc->nodeId()) == nullptr) {
throw std::invalid_argument("boundary condition references missing node id");
}
for (const auto& existing : boundary_conditions_) {
const auto* existing_spc =
dynamic_cast<const fesa::boundary::SinglePointConstraint*>(existing.get());
if (existing_spc != nullptr &&
existing_spc->nodeId() == spc->nodeId() &&
existing_spc->dof() == spc->dof()) {
throw std::invalid_argument("duplicate boundary condition key");
}
}
}
const std::size_t index = boundary_conditions_.size();
boundary_conditions_.push_back(std::move(boundary));
return index;
}
std::size_t Domain::addLoad(std::unique_ptr<fesa::load::Load> load) {
if (!load) {
throw std::invalid_argument("load is null");
}
if (const auto* nodal = dynamic_cast<const fesa::load::NodalLoad*>(load.get())) {
if (findNode(nodal->nodeId()) == nullptr) {
throw std::invalid_argument("nodal load references missing node id");
}
for (const auto& existing : loads_) {
const auto* existing_nodal = dynamic_cast<const fesa::load::NodalLoad*>(existing.get());
if (existing_nodal != nullptr &&
existing_nodal->nodeId() == nodal->nodeId() &&
existing_nodal->dof() == nodal->dof()) {
throw std::invalid_argument("duplicate nodal load key");
}
}
}
const std::size_t index = loads_.size();
loads_.push_back(std::move(load));
return index;
}
void Domain::addStep(LinearStaticStepDefinition step) {
const StepId id = step.id();
if (steps_.find(id) != steps_.end()) {
throw std::invalid_argument("duplicate step id");
}
for (const std::size_t index : step.boundaryConditionIndices()) {
if (index >= boundary_conditions_.size()) {
throw std::invalid_argument("step references missing boundary condition");
}
}
for (const std::size_t index : step.loadIndices()) {
if (index >= loads_.size()) {
throw std::invalid_argument("step references missing load");
}
}
steps_.emplace(id, std::move(step));
}
const Node* Domain::findNode(NodeId id) const noexcept {
const auto it = nodes_.find(id);
return it == nodes_.end() ? nullptr : &it->second;
}
const Node& Domain::node(NodeId id) const {
const Node* found = findNode(id);
if (found == nullptr) {
throw std::out_of_range("node id not found");
}
return *found;
}
std::size_t Domain::nodeCount() const noexcept {
return nodes_.size();
}
const fesa::element::Element* Domain::findElement(ElementId id) const noexcept {
const auto it = elements_.find(id);
return it == elements_.end() ? nullptr : it->second.get();
}
const fesa::element::Element& Domain::element(ElementId id) const {
const fesa::element::Element* found = findElement(id);
if (found == nullptr) {
throw std::out_of_range("element id not found");
}
return *found;
}
std::size_t Domain::elementCount() const noexcept {
return elements_.size();
}
const fesa::material::Material* Domain::findMaterial(MaterialId id) const noexcept {
const auto it = materials_.find(id);
return it == materials_.end() ? nullptr : it->second.get();
}
const fesa::material::Material& Domain::material(MaterialId id) const {
const fesa::material::Material* found = findMaterial(id);
if (found == nullptr) {
throw std::out_of_range("material id not found");
}
return *found;
}
std::size_t Domain::materialCount() const noexcept {
return materials_.size();
}
const fesa::property::Property* Domain::findProperty(PropertyId id) const noexcept {
const auto it = properties_.find(id);
return it == properties_.end() ? nullptr : it->second.get();
}
const fesa::property::Property& Domain::property(PropertyId id) const {
const fesa::property::Property* found = findProperty(id);
if (found == nullptr) {
throw std::out_of_range("property id not found");
}
return *found;
}
std::size_t Domain::propertyCount() const noexcept {
return properties_.size();
}
const fesa::property::ShellProperty* Domain::findShellProperty(PropertyId id) const noexcept {
return dynamic_cast<const fesa::property::ShellProperty*>(findProperty(id));
}
const fesa::property::ShellProperty& Domain::shellProperty(PropertyId id) const {
const fesa::property::ShellProperty* found = findShellProperty(id);
if (found == nullptr) {
throw std::out_of_range("shell property id not found");
}
return *found;
}
std::size_t Domain::shellPropertyCount() const noexcept {
return properties_.size();
}
const std::vector<NodeId>* Domain::findNodeSet(const std::string& name) const noexcept {
const auto it = node_sets_.find(name);
return it == node_sets_.end() ? nullptr : &it->second;
}
const std::vector<NodeId>& Domain::nodeSet(const std::string& name) const {
const std::vector<NodeId>* found = findNodeSet(name);
if (found == nullptr) {
throw std::out_of_range("node set not found");
}
return *found;
}
std::size_t Domain::nodeSetCount() const noexcept {
return node_sets_.size();
}
const std::vector<ElementId>* Domain::findElementSet(const std::string& name) const noexcept {
const auto it = element_sets_.find(name);
return it == element_sets_.end() ? nullptr : &it->second;
}
const std::vector<ElementId>& Domain::elementSet(const std::string& name) const {
const std::vector<ElementId>* found = findElementSet(name);
if (found == nullptr) {
throw std::out_of_range("element set not found");
}
return *found;
}
std::size_t Domain::elementSetCount() const noexcept {
return element_sets_.size();
}
const fesa::boundary::BoundaryCondition* Domain::findBoundaryCondition(std::size_t index) const noexcept {
return index < boundary_conditions_.size() ? boundary_conditions_[index].get() : nullptr;
}
const fesa::boundary::BoundaryCondition& Domain::boundaryCondition(std::size_t index) const {
const fesa::boundary::BoundaryCondition* found = findBoundaryCondition(index);
if (found == nullptr) {
throw std::out_of_range("boundary condition index not found");
}
return *found;
}
std::size_t Domain::boundaryConditionCount() const noexcept {
return boundary_conditions_.size();
}
const fesa::load::Load* Domain::findLoad(std::size_t index) const noexcept {
return index < loads_.size() ? loads_[index].get() : nullptr;
}
const fesa::load::Load& Domain::load(std::size_t index) const {
const fesa::load::Load* found = findLoad(index);
if (found == nullptr) {
throw std::out_of_range("load index not found");
}
return *found;
}
std::size_t Domain::loadCount() const noexcept {
return loads_.size();
}
const LinearStaticStepDefinition* Domain::findStep(StepId id) const noexcept {
const auto it = steps_.find(id);
return it == steps_.end() ? nullptr : &it->second;
}
const LinearStaticStepDefinition& Domain::step(StepId id) const {
const LinearStaticStepDefinition* found = findStep(id);
if (found == nullptr) {
throw std::out_of_range("step id not found");
}
return *found;
}
std::size_t Domain::stepCount() const noexcept {
return steps_.size();
}
} // namespace fesa::core
-37
View File
@@ -1,37 +0,0 @@
#include "fesa/element/Mitc4Element.hpp"
#include "fesa/core/Node.hpp"
namespace fesa::element {
Mitc4Element::Mitc4Element(
ElementId id,
std::array<NodeId, 4> connectivity,
PropertyId property_id)
: id_(id), connectivity_(connectivity), property_id_(property_id) {}
ElementId Mitc4Element::id() const noexcept {
return id_;
}
ElementType Mitc4Element::type() const noexcept {
return ElementType::Mitc4;
}
std::size_t Mitc4Element::nodeCount() const noexcept {
return connectivity_.size();
}
std::size_t Mitc4Element::dofCount() const noexcept {
return connectivity_.size() * fesa::core::Node::dofCount();
}
const std::array<NodeId, 4>& Mitc4Element::connectivity() const noexcept {
return connectivity_;
}
PropertyId Mitc4Element::propertyId() const noexcept {
return property_id_;
}
} // namespace fesa::element
-19
View File
@@ -1,19 +0,0 @@
#include "fesa/io/Hdf5ResultWriter.hpp"
#include <stdexcept>
#include <utility>
namespace fesa::io {
Hdf5ResultWriter::Hdf5ResultWriter(std::string file_path)
: file_path_(std::move(file_path)) {
if (file_path_.empty()) {
throw std::invalid_argument("HDF5 result writer path must not be empty");
}
}
const std::string& Hdf5ResultWriter::filePath() const noexcept {
return file_path_;
}
} // namespace fesa::io
-24
View File
@@ -1,24 +0,0 @@
#include "fesa/load/NodalLoad.hpp"
namespace fesa::load {
NodalLoad::NodalLoad(NodeId node_id, Dof dof, double value)
: node_id_(node_id), dof_(dof), value_(value) {}
LoadKind NodalLoad::kind() const noexcept {
return LoadKind::Nodal;
}
NodeId NodalLoad::nodeId() const noexcept {
return node_id_;
}
Dof NodalLoad::dof() const noexcept {
return dof_;
}
double NodalLoad::value() const noexcept {
return value_;
}
} // namespace fesa::load
-23
View File
@@ -1,23 +0,0 @@
#include "fesa/material/LinearElasticMaterial.hpp"
namespace fesa::material {
LinearElasticMaterial::LinearElasticMaterial(
MaterialId id,
double young_modulus,
double poisson_ratio)
: id_(id), young_modulus_(young_modulus), poisson_ratio_(poisson_ratio) {}
MaterialId LinearElasticMaterial::id() const noexcept {
return id_;
}
double LinearElasticMaterial::youngModulus() const noexcept {
return young_modulus_;
}
double LinearElasticMaterial::poissonRatio() const noexcept {
return poisson_ratio_;
}
} // namespace fesa::material
-30
View File
@@ -1,30 +0,0 @@
#include "fesa/property/ShellProperty.hpp"
#include <stdexcept>
namespace fesa::property {
ShellProperty::ShellProperty(PropertyId id, MaterialId material_id, double thickness)
: id_(id), material_id_(material_id), thickness_(thickness) {
if (thickness <= 0.0) {
throw std::invalid_argument("shell property thickness must be positive");
}
}
PropertyId ShellProperty::id() const noexcept {
return id_;
}
PropertyKind ShellProperty::kind() const noexcept {
return PropertyKind::Shell;
}
MaterialId ShellProperty::materialId() const noexcept {
return material_id_;
}
double ShellProperty::thickness() const noexcept {
return thickness_;
}
} // namespace fesa::property