feat: add domain model foundation
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user