feat(cpp-object-oriented-modular-refactoring): step 12 - material-property-hierarchy

This commit is contained in:
KOKO\Mimi
2026-08-16 08:48:18 +09:00
parent ec9c3e250a
commit 64a7071986
14 changed files with 746 additions and 31 deletions
+3
View File
@@ -19,6 +19,7 @@ add_library(
io/abaqus/domain_mapper.cpp
io/abaqus/input_reader.cpp
io/hdf5/hdf5_results_writer.cpp
materials/isotropic_linear_elastic_material.cpp
math/dense_blas_internal.cpp
math/matrix.cpp
math/sparse_matrix.cpp
@@ -26,6 +27,8 @@ add_library(
model/domain.cpp
model/shell_geometry.cpp
model/source_target_resolver.cpp
properties/general_beam_section.cpp
properties/shell_section.cpp
results/result_recovery.cpp
solvers/linear/mkl_pardiso_solver.cpp
)
@@ -0,0 +1,89 @@
#include "fesa/materials/isotropic_linear_elastic_material.h"
#include <cmath>
#include <string>
#include <utility>
namespace fesa {
namespace {
Status InvalidMaterial(const SourceEntityId& source_id,
const SourceLocation& location,
const std::string& message) {
return Status::Failure(FailureCategory::kModel,
{{Severity::kError, "invalid-material", location,
"*MATERIAL", source_id.source_label_text, message}});
}
} // namespace
Result<IsotropicLinearElasticMaterial> IsotropicLinearElasticMaterial::Create(
SourceEntityId source_id, std::string name, double youngs_modulus,
double poissons_ratio, SourceLocation location) {
if (name.empty() || source_id.source_label_text.empty()) {
return Result<IsotropicLinearElasticMaterial>::Failure(InvalidMaterial(
source_id, location, "Material source identity must not be empty."));
}
const double denominator = 2.0 * (1.0 + poissons_ratio);
const double shear_modulus = youngs_modulus / denominator;
if (!std::isfinite(youngs_modulus) || !(youngs_modulus > 0.0) ||
!std::isfinite(poissons_ratio) || !std::isfinite(shear_modulus) ||
!(shear_modulus > 0.0)) {
return Result<IsotropicLinearElasticMaterial>::Failure(InvalidMaterial(
source_id, location,
"E and the derived G=E/(2*(1+nu)) must be finite and positive."));
}
return Result<IsotropicLinearElasticMaterial>::Success(
IsotropicLinearElasticMaterial{std::move(source_id), std::move(name),
youngs_modulus, poissons_ratio,
std::move(location)});
}
IsotropicLinearElasticMaterial::IsotropicLinearElasticMaterial(
std::string name_value, double youngs_modulus_value,
double poissons_ratio_value, SourceLocation location_value)
: name{std::move(name_value)},
youngs_modulus{youngs_modulus_value},
poisson_ratio{poissons_ratio_value},
location{std::move(location_value)},
source_id_{"", 0, name} {}
MaterialKind IsotropicLinearElasticMaterial::Kind() const noexcept {
return MaterialKind::kIsotropicLinearElastic;
}
const SourceEntityId& IsotropicLinearElasticMaterial::SourceId()
const noexcept {
return source_id_;
}
const SourceLocation& IsotropicLinearElasticMaterial::Location()
const noexcept {
return location;
}
const std::string& IsotropicLinearElasticMaterial::Name() const noexcept {
return name;
}
double IsotropicLinearElasticMaterial::YoungsModulus() const noexcept {
return youngs_modulus;
}
double IsotropicLinearElasticMaterial::PoissonsRatio() const noexcept {
return poisson_ratio;
}
IsotropicLinearElasticMaterial::IsotropicLinearElasticMaterial(
SourceEntityId source_id, std::string name_value,
double youngs_modulus_value, double poissons_ratio_value,
SourceLocation location_value)
: name{std::move(name_value)},
youngs_modulus{youngs_modulus_value},
poisson_ratio{poissons_ratio_value},
location{std::move(location_value)},
source_id_{std::move(source_id)} {}
} // namespace fesa
@@ -0,0 +1,140 @@
#include "fesa/properties/general_beam_section.h"
#include <algorithm>
#include <cmath>
#include <string>
#include <utility>
namespace fesa {
namespace {
Status InvalidBeamSection(const std::string& code,
const SourceEntityId& source_id,
const SourceLocation& location,
const std::string& message) {
return Status::Failure(
FailureCategory::kModel,
{{Severity::kError, code, location, "*BEAM GENERAL SECTION",
source_id.source_label_text, message}});
}
bool IsFinitePoint(const std::array<double, 2>& point) {
return std::isfinite(point[0]) && std::isfinite(point[1]);
}
} // namespace
Result<GeneralBeamSection> GeneralBeamSection::Create(
SourceEntityId source_id, std::string name, double area, double i11,
double i12, double i22, double torsional_constant,
std::array<double, 3> first_axis,
std::vector<std::array<double, 2>> section_points,
SourceLocation location) {
if (name.empty() || source_id.source_label_text.empty()) {
return Result<GeneralBeamSection>::Failure(
InvalidBeamSection("invalid-beam-property", source_id, location,
"Beam section source identity must not be empty."));
}
if (!std::isfinite(i12) || i12 != 0.0) {
return Result<GeneralBeamSection>::Failure(InvalidBeamSection(
std::isfinite(i12) ? "unsupported-coupled-section"
: "invalid-beam-property",
source_id, location,
"The general beam section requires finite exact I12=0."));
}
const std::array<double, 4> positive_properties = {area, i11, i22,
torsional_constant};
if (std::any_of(positive_properties.begin(), positive_properties.end(),
[](double property) {
return !std::isfinite(property) || !(property > 0.0);
}) ||
std::any_of(first_axis.begin(), first_axis.end(),
[](double component) { return !std::isfinite(component); })) {
return Result<GeneralBeamSection>::Failure(InvalidBeamSection(
"invalid-beam-property", source_id, location,
"A, I11, I22, J, and first-axis components must be finite; section "
"magnitudes must be positive."));
}
if (std::any_of(section_points.begin(), section_points.end(),
[](const auto& point) { return !IsFinitePoint(point); })) {
return Result<GeneralBeamSection>::Failure(
InvalidBeamSection("invalid-section-point", source_id, location,
"Section-point coordinates must be finite."));
}
return Result<GeneralBeamSection>::Success(
GeneralBeamSection{std::move(source_id), std::move(name), area, i11, i12,
i22, torsional_constant, first_axis,
std::move(section_points), std::move(location)});
}
GeneralBeamSection::GeneralBeamSection(
std::string name_value, double area_value, double i11_value,
double i12_value, double i22_value, double torsional_constant_value,
std::array<double, 3> first_axis_value,
std::vector<std::array<double, 2>> section_points_value,
SourceLocation location_value)
: name{std::move(name_value)},
area{area_value},
i11{i11_value},
i12{i12_value},
i22{i22_value},
torsional_constant{torsional_constant_value},
first_axis{first_axis_value},
section_points{std::move(section_points_value)},
location{std::move(location_value)},
source_id_{"", 0, name} {}
ElementPropertyKind GeneralBeamSection::Kind() const noexcept {
return ElementPropertyKind::kGeneralBeamSection;
}
const SourceEntityId& GeneralBeamSection::SourceId() const noexcept {
return source_id_;
}
const SourceLocation& GeneralBeamSection::Location() const noexcept {
return location;
}
const std::string& GeneralBeamSection::Name() const noexcept { return name; }
double GeneralBeamSection::Area() const noexcept { return area; }
double GeneralBeamSection::I11() const noexcept { return i11; }
double GeneralBeamSection::I12() const noexcept { return i12; }
double GeneralBeamSection::I22() const noexcept { return i22; }
double GeneralBeamSection::TorsionalConstant() const noexcept {
return torsional_constant;
}
const std::array<double, 3>& GeneralBeamSection::FirstAxis() const noexcept {
return first_axis;
}
const std::vector<std::array<double, 2>>& GeneralBeamSection::SectionPoints()
const noexcept {
return section_points;
}
GeneralBeamSection::GeneralBeamSection(
SourceEntityId source_id, std::string name_value, double area_value,
double i11_value, double i12_value, double i22_value,
double torsional_constant_value, std::array<double, 3> first_axis_value,
std::vector<std::array<double, 2>> section_points_value,
SourceLocation location_value)
: name{std::move(name_value)},
area{area_value},
i11{i11_value},
i12{i12_value},
i22{i22_value},
torsional_constant{torsional_constant_value},
first_axis{first_axis_value},
section_points{std::move(section_points_value)},
location{std::move(location_value)},
source_id_{std::move(source_id)} {}
} // namespace fesa
+78
View File
@@ -0,0 +1,78 @@
#include "fesa/properties/shell_section.h"
#include <cmath>
#include <string>
#include <utility>
namespace fesa {
namespace {
Status InvalidShellSection(const SourceEntityId& source_id,
const SourceLocation& location,
const std::string& message) {
return Status::Failure(
FailureCategory::kModel,
{{Severity::kError, "invalid-shell-thickness", location, "*SHELL SECTION",
source_id.source_label_text, message}});
}
} // namespace
Result<ShellSection> ShellSection::Create(SourceEntityId source_id,
std::string name, double thickness,
EntityIndex material_index,
SourceLocation location) {
if (name.empty() || source_id.source_label_text.empty()) {
return Result<ShellSection>::Failure(InvalidShellSection(
source_id, location,
"Shell section source identity must not be empty."));
}
if (!std::isfinite(thickness) || !(thickness > 0.0)) {
return Result<ShellSection>::Failure(InvalidShellSection(
source_id, location, "Shell thickness must be finite and positive."));
}
return Result<ShellSection>::Success(
ShellSection{std::move(source_id), std::move(name), thickness,
material_index, std::move(location)});
}
ShellSection::ShellSection(std::string name_value, double thickness_value,
EntityIndex material_index_value,
SourceLocation location_value)
: name{std::move(name_value)},
thickness{thickness_value},
material_index{material_index_value},
location{std::move(location_value)},
source_id_{"", 0, name} {}
ElementPropertyKind ShellSection::Kind() const noexcept {
return ElementPropertyKind::kShellSection;
}
const SourceEntityId& ShellSection::SourceId() const noexcept {
return source_id_;
}
const SourceLocation& ShellSection::Location() const noexcept {
return location;
}
const std::string& ShellSection::Name() const noexcept { return name; }
double ShellSection::Thickness() const noexcept { return thickness; }
EntityIndex ShellSection::MaterialIndex() const noexcept {
return material_index;
}
ShellSection::ShellSection(SourceEntityId source_id, std::string name_value,
double thickness_value,
EntityIndex material_index_value,
SourceLocation location_value)
: name{std::move(name_value)},
thickness{thickness_value},
material_index{material_index_value},
location{std::move(location_value)},
source_id_{std::move(source_id)} {}
} // namespace fesa