feat: map thermal DS4 Abaqus input

This commit is contained in:
KOKO\Mimi
2026-09-29 20:09:54 +09:00
parent 85b5daac89
commit a21c11a825
2 changed files with 661 additions and 67 deletions
@@ -0,0 +1,136 @@
#include <gtest/gtest.h>
#include <filesystem>
#include <fstream>
#include <stdexcept>
#include <string>
#include "fesa/io/abaqus/domain_mapper.h"
#include "fesa/io/abaqus/input_reader.h"
namespace {
class TemporaryInput final {
public:
explicit TemporaryInput(const std::string& content)
: path_{std::filesystem::temp_directory_path() /
"fesa-thermal-domain.inp"} {
std::ofstream output{path_, std::ios::binary | std::ios::trunc};
output << content;
if (!output) throw std::runtime_error{"Unable to write thermal fixture."};
}
~TemporaryInput() {
std::error_code error;
std::filesystem::remove(path_, error);
}
const std::filesystem::path& Path() const noexcept { return path_; }
private:
std::filesystem::path path_;
};
fesa::Result<fesa::Domain> MapText(const std::string& text) {
const TemporaryInput input{text};
const auto parsed = fesa::AbaqusInputReader{}.Read(input.Path());
if (!parsed.HasValue())
return fesa::Result<fesa::Domain>::Failure(parsed.GetStatus());
return fesa::AbaqusDomainMapper{}.Map(parsed.Value());
}
std::string ThermalDeck() {
return R"inp(*Part, name=P
*Node
1, 0., 0., 0.
2, 1., 0., 0.
3, 1., 1., 0.
4, 0., 1., 0.
*Element, type=DS4
1, 1, 2, 3, 4
*Elset, elset=E
1
*Shell Section, elset=E, material=M
.5, 5
*End Part
*Assembly, name=A
*Instance, name=I, part=P
*End Instance
*Nset, nset=Bottom, instance=I
1
2
*End Assembly
*Material, name=M
*Density
7850.,
*Conductivity
54.,
*Specific Heat
460.,
*Initial Conditions, type=TEMPERATURE
Bottom, 20.
*Boundary
Bottom, 11, 11
*Step, name=Heat, inc=100
*Heat Transfer
1., 100.
*Boundary
Bottom, 15, 15, 30.
*Cflux
Bottom, 11, -2.
*Cflux
Bottom, 11, -3.
*End Step
)inp";
}
TEST(ThermalDomainMapping, MapsDs4MaterialsTargetsAndAdditiveFluxes) {
const auto result = MapText(ThermalDeck());
ASSERT_TRUE(result.HasValue())
<< (result.HasValue() ? ""
: result.GetStatus().Diagnostics().front().message);
const auto& domain = result.Value();
ASSERT_EQ(domain.ThermalElements().Size(), 1U);
ASSERT_EQ(domain.ThermalMaterials().Size(), 1U);
EXPECT_DOUBLE_EQ(domain.ThermalMaterials()[0U].Conductivity(), 54.0);
ASSERT_NE(domain.ThermalStep(), nullptr);
EXPECT_EQ(domain.ThermalStep()->name, "Heat");
EXPECT_EQ(domain.ThermalStep()->maximum_increments, 100U);
EXPECT_EQ(domain.ThermalModelBoundaries().size(), 2U);
EXPECT_EQ(domain.ThermalStep()->Boundaries().size(), 2U);
ASSERT_EQ(domain.ThermalStep()->Loads().size(), 4U);
EXPECT_DOUBLE_EQ(domain.ThermalStep()->Loads()[0U].power, -2.0);
EXPECT_DOUBLE_EQ(domain.ThermalStep()->Loads()[3U].power, -3.0);
}
TEST(ThermalDomainMapping, RejectsInteriorAndConflictingThermalBoundaries) {
auto interior = ThermalDeck();
interior.replace(interior.find("Bottom, 11, 11\n"), 14U, "Bottom, 12, 12\n");
const auto invalid_dof = MapText(interior);
ASSERT_FALSE(invalid_dof.HasValue());
EXPECT_EQ(invalid_dof.GetStatus().Diagnostics()[0U].code, "invalid-dof");
auto conflicting = ThermalDeck();
conflicting.replace(conflicting.find("*Cflux"), 0U,
"*Boundary\nBottom, 15, 15, 99.\n");
const auto invalid_conflict = MapText(conflicting);
ASSERT_FALSE(invalid_conflict.HasValue());
EXPECT_EQ(invalid_conflict.GetStatus().Diagnostics()[0U].code,
"conflicting-boundary-condition");
}
TEST(ThermalDomainMapping, MapsApprovedShellThermalReference) {
auto path = std::filesystem::path{__FILE__}.parent_path();
for (int index = 0; index < 4; ++index) path = path.parent_path();
path /= "reference/shell-thermal/shell-thermal.inp";
const auto parsed = fesa::AbaqusInputReader{}.Read(path);
ASSERT_TRUE(parsed.HasValue());
const auto result = fesa::AbaqusDomainMapper{}.Map(parsed.Value());
ASSERT_TRUE(result.HasValue())
<< (result.HasValue() ? ""
: result.GetStatus().Diagnostics().front().message);
EXPECT_EQ(result.Value().Nodes().size(), 729U);
EXPECT_EQ(result.Value().ThermalElements().Size(), 676U);
ASSERT_NE(result.Value().ThermalStep(), nullptr);
EXPECT_EQ(result.Value().ThermalStep()->maximum_increments, 100000U);
}
} // namespace