refactor: store runtime objects in domain

This commit is contained in:
김경종
2026-06-09 10:08:34 +09:00
parent 8f24213ab7
commit f4196efb10
20 changed files with 754 additions and 368 deletions
+91 -166
View File
@@ -1,6 +1,11 @@
#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>
@@ -154,28 +159,37 @@ void Domain::addNode(Node node) {
}
}
void Domain::addElement(ElementDefinition element) {
const ElementId id = element.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()) {
for (const NodeId node_id : element->connectivity()) {
if (findNode(node_id) == nullptr) {
throw std::invalid_argument("element references missing node id");
}
}
if (findShellProperty(element->propertyId()) == nullptr) {
throw std::invalid_argument("element references missing shell property id");
}
elements_.emplace(id, std::move(element));
}
void Domain::addMaterial(LinearElasticMaterialDefinition material) {
const MaterialId id = material.id();
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::addShellProperty(ShellPropertyDefinition property) {
void Domain::addShellProperty(fesa::property::ShellProperty property) {
const PropertyId id = property.id();
if (shell_properties_.find(id) != shell_properties_.end()) {
throw std::invalid_argument("duplicate shell property id");
@@ -210,21 +224,48 @@ void Domain::addElementSet(std::string name, std::vector<ElementId> element_ids)
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");
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(condition);
boundary_conditions_.push_back(std::move(boundary));
return index;
}
std::size_t Domain::addNodalLoad(NodalLoadDefinition load) {
if (findNode(load.nodeId()) == nullptr) {
throw std::invalid_argument("nodal load references missing node id");
std::size_t Domain::addLoad(std::unique_ptr<fesa::load::Load> load) {
if (!load) {
throw std::invalid_argument("load is null");
}
const std::size_t index = nodal_loads_.size();
nodal_loads_.push_back(load);
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;
}
@@ -239,79 +280,13 @@ void Domain::addStep(LinearStaticStepDefinition step) {
}
}
for (const std::size_t index : step.loadIndices()) {
if (index >= nodal_loads_.size()) {
throw std::invalid_argument("step references missing nodal load");
if (index >= loads_.size()) {
throw std::invalid_argument("step references missing load");
}
}
steps_.emplace(id, std::move(step));
}
void Domain::addElementObject(std::unique_ptr<fesa::element::Element> element) {
if (!element) {
throw std::invalid_argument("element object is null");
}
const ElementId id = element->id();
if (element_objects_.find(id) != element_objects_.end()) {
throw std::invalid_argument("duplicate element object id");
}
for (const NodeId node_id : element->connectivity()) {
if (findNode(node_id) == nullptr) {
throw std::invalid_argument("element object references missing node id");
}
}
element_objects_.emplace(id, std::move(element));
}
void Domain::addMaterialObject(std::unique_ptr<fesa::material::Material> material) {
if (!material) {
throw std::invalid_argument("material object is null");
}
const MaterialId id = material->id();
const auto inserted = material_objects_.emplace(id, std::move(material));
if (!inserted.second) {
throw std::invalid_argument("duplicate material object id");
}
}
std::size_t Domain::addLoadObject(std::unique_ptr<fesa::load::Load> load) {
if (!load) {
throw std::invalid_argument("load object is null");
}
if (const auto* nodal = dynamic_cast<const fesa::load::NodalLoad*>(load.get())) {
for (const auto& existing : load_objects_) {
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 = load_objects_.size();
load_objects_.push_back(std::move(load));
return index;
}
std::size_t Domain::addBoundaryObject(std::unique_ptr<fesa::boundary::BoundaryCondition> boundary) {
if (!boundary) {
throw std::invalid_argument("boundary object is null");
}
if (const auto* spc = dynamic_cast<const fesa::boundary::SinglePointConstraint*>(boundary.get())) {
for (const auto& existing : boundary_objects_) {
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 object key");
}
}
}
const std::size_t index = boundary_objects_.size();
boundary_objects_.push_back(std::move(boundary));
return index;
}
const Node* Domain::findNode(NodeId id) const noexcept {
const auto it = nodes_.find(id);
return it == nodes_.end() ? nullptr : &it->second;
@@ -329,13 +304,13 @@ std::size_t Domain::nodeCount() const noexcept {
return nodes_.size();
}
const ElementDefinition* Domain::findElement(ElementId id) const noexcept {
const fesa::element::Element* Domain::findElement(ElementId id) const noexcept {
const auto it = elements_.find(id);
return it == elements_.end() ? nullptr : &it->second;
return it == elements_.end() ? nullptr : it->second.get();
}
const ElementDefinition& Domain::element(ElementId id) const {
const ElementDefinition* found = findElement(id);
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");
}
@@ -346,13 +321,13 @@ std::size_t Domain::elementCount() const noexcept {
return elements_.size();
}
const LinearElasticMaterialDefinition* Domain::findMaterial(MaterialId id) const noexcept {
const fesa::material::Material* Domain::findMaterial(MaterialId id) const noexcept {
const auto it = materials_.find(id);
return it == materials_.end() ? nullptr : &it->second;
return it == materials_.end() ? nullptr : it->second.get();
}
const LinearElasticMaterialDefinition& Domain::material(MaterialId id) const {
const LinearElasticMaterialDefinition* found = findMaterial(id);
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");
}
@@ -363,13 +338,13 @@ std::size_t Domain::materialCount() const noexcept {
return materials_.size();
}
const ShellPropertyDefinition* Domain::findShellProperty(PropertyId id) const noexcept {
const fesa::property::ShellProperty* 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);
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");
}
@@ -414,20 +389,36 @@ 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);
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 NodalLoadDefinition& Domain::nodalLoad(std::size_t index) const {
return nodal_loads_.at(index);
const fesa::load::Load* Domain::findLoad(std::size_t index) const noexcept {
return index < loads_.size() ? loads_[index].get() : nullptr;
}
std::size_t Domain::nodalLoadCount() const noexcept {
return nodal_loads_.size();
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 {
@@ -447,70 +438,4 @@ std::size_t Domain::stepCount() const noexcept {
return steps_.size();
}
const fesa::element::Element* Domain::findElementObject(ElementId id) const noexcept {
const auto it = element_objects_.find(id);
return it == element_objects_.end() ? nullptr : it->second.get();
}
const fesa::element::Element& Domain::elementObject(ElementId id) const {
const fesa::element::Element* found = findElementObject(id);
if (found == nullptr) {
throw std::out_of_range("element object id not found");
}
return *found;
}
std::size_t Domain::elementObjectCount() const noexcept {
return element_objects_.size();
}
const fesa::material::Material* Domain::findMaterialObject(MaterialId id) const noexcept {
const auto it = material_objects_.find(id);
return it == material_objects_.end() ? nullptr : it->second.get();
}
const fesa::material::Material& Domain::materialObject(MaterialId id) const {
const fesa::material::Material* found = findMaterialObject(id);
if (found == nullptr) {
throw std::out_of_range("material object id not found");
}
return *found;
}
std::size_t Domain::materialObjectCount() const noexcept {
return material_objects_.size();
}
const fesa::load::Load* Domain::findLoadObject(std::size_t index) const noexcept {
return index < load_objects_.size() ? load_objects_[index].get() : nullptr;
}
const fesa::load::Load& Domain::loadObject(std::size_t index) const {
const fesa::load::Load* found = findLoadObject(index);
if (found == nullptr) {
throw std::out_of_range("load object index not found");
}
return *found;
}
std::size_t Domain::loadObjectCount() const noexcept {
return load_objects_.size();
}
const fesa::boundary::BoundaryCondition* Domain::findBoundaryObject(std::size_t index) const noexcept {
return index < boundary_objects_.size() ? boundary_objects_[index].get() : nullptr;
}
const fesa::boundary::BoundaryCondition& Domain::boundaryObject(std::size_t index) const {
const fesa::boundary::BoundaryCondition* found = findBoundaryObject(index);
if (found == nullptr) {
throw std::out_of_range("boundary object index not found");
}
return *found;
}
std::size_t Domain::boundaryObjectCount() const noexcept {
return boundary_objects_.size();
}
} // namespace fesa::core