feat: add domain model foundation

This commit is contained in:
김경종
2026-06-08 16:40:04 +09:00
parent e4e2f57808
commit fdeac602f4
38 changed files with 2685 additions and 5 deletions
+381
View File
@@ -0,0 +1,381 @@
#include "fesa/core/Domain.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(ElementDefinition element) {
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");
}
}
elements_.emplace(id, std::move(element));
}
void Domain::addMaterial(LinearElasticMaterialDefinition material) {
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::addShellProperty(ShellPropertyDefinition property) {
const PropertyId id = property.id();
if (shell_properties_.find(id) != shell_properties_.end()) {
throw std::invalid_argument("duplicate shell property id");
}
if (findMaterial(property.materialId()) == nullptr) {
throw std::invalid_argument("shell property references missing material id");
}
shell_properties_.emplace(id, 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(BoundaryCondition condition) {
if (findNode(condition.nodeId()) == nullptr) {
throw std::invalid_argument("boundary condition references missing node id");
}
const std::size_t index = boundary_conditions_.size();
boundary_conditions_.push_back(condition);
return index;
}
std::size_t Domain::addNodalLoad(NodalLoadDefinition load) {
if (findNode(load.nodeId()) == nullptr) {
throw std::invalid_argument("nodal load references missing node id");
}
const std::size_t index = nodal_loads_.size();
nodal_loads_.push_back(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 >= nodal_loads_.size()) {
throw std::invalid_argument("step references missing nodal 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 ElementDefinition* Domain::findElement(ElementId id) const noexcept {
const auto it = elements_.find(id);
return it == elements_.end() ? nullptr : &it->second;
}
const ElementDefinition& Domain::element(ElementId id) const {
const ElementDefinition* 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 LinearElasticMaterialDefinition* Domain::findMaterial(MaterialId id) const noexcept {
const auto it = materials_.find(id);
return it == materials_.end() ? nullptr : &it->second;
}
const LinearElasticMaterialDefinition& Domain::material(MaterialId id) const {
const LinearElasticMaterialDefinition* 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 ShellPropertyDefinition* Domain::findShellProperty(PropertyId id) const noexcept {
const auto it = shell_properties_.find(id);
return it == shell_properties_.end() ? nullptr : &it->second;
}
const ShellPropertyDefinition& Domain::shellProperty(PropertyId id) const {
const ShellPropertyDefinition* 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 shell_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 BoundaryCondition& Domain::boundaryCondition(std::size_t index) const {
return boundary_conditions_.at(index);
}
std::size_t Domain::boundaryConditionCount() const noexcept {
return boundary_conditions_.size();
}
const NodalLoadDefinition& Domain::nodalLoad(std::size_t index) const {
return nodal_loads_.at(index);
}
std::size_t Domain::nodalLoadCount() const noexcept {
return nodal_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