22c9d4435c
Implement MITC4 mass, constrained whitening, MKL FEAST, modal HDF5, and deterministic Value comparison. MSVC Debug builds; 394 of 395 tests pass. Original-model all-c residual and the documented S3 static contract conflict remain unresolved; this is an implementation checkpoint, not feature acceptance.
112 lines
2.9 KiB
C++
112 lines
2.9 KiB
C++
#include <gtest/gtest.h>
|
|
#include <hdf5.h>
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iterator>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#include "fesa/app/fesa_application.h"
|
|
|
|
namespace {
|
|
|
|
class EigenApplicationTest : public ::testing::Test {
|
|
protected:
|
|
void SetUp() override {
|
|
static std::atomic<unsigned long long> sequence{0U};
|
|
folder_ =
|
|
std::filesystem::temp_directory_path() /
|
|
("fesa-eigen-app-" +
|
|
std::to_string(
|
|
std::chrono::steady_clock::now().time_since_epoch().count()) +
|
|
"-" + std::to_string(sequence.fetch_add(1U)));
|
|
ASSERT_TRUE(std::filesystem::create_directory(folder_));
|
|
input_ = folder_ / "Panel.Modes.inp";
|
|
output_ = folder_ / "Panel.Modes_results.h5";
|
|
log_ = folder_ / "Panel.Modes_log.txt";
|
|
}
|
|
|
|
void TearDown() override {
|
|
std::error_code ignored;
|
|
std::filesystem::remove_all(folder_, ignored);
|
|
}
|
|
|
|
void WriteDeck(const bool empty = false) {
|
|
std::ofstream file{input_};
|
|
file << R"inp(*Part, name=Panel
|
|
*Node
|
|
11,0,0,0
|
|
22,1,0,0
|
|
33,1,1,0
|
|
44,0,1,0
|
|
*Element,type=S4
|
|
71,11,22,33,44
|
|
*Elset,elset=Shell
|
|
71
|
|
*Shell Section,elset=Shell,material=Steel
|
|
0.5
|
|
*End Part
|
|
*Assembly,name=Assembly
|
|
*Instance,name=Panel-1,part=Panel
|
|
*End Instance
|
|
*Nset,nset=Fixed,instance=Panel-1
|
|
11,22,33
|
|
*Nset,nset=Tip,instance=Panel-1
|
|
44
|
|
*End Assembly
|
|
*Material,name=Steel
|
|
*Density
|
|
1.
|
|
*Elastic
|
|
12.,0.
|
|
*Boundary
|
|
Fixed,1,6
|
|
Tip,1,2
|
|
Tip,4,6
|
|
)inp";
|
|
if (empty) file << "Tip,3,3\n";
|
|
file << R"inp(*Step,name=Step-2,nlgeom=NO,perturbation
|
|
*Frequency,eigensolver=Lanczos,normalization=mass
|
|
1
|
|
*End Step
|
|
)inp";
|
|
ASSERT_TRUE(file.good());
|
|
}
|
|
|
|
std::filesystem::path folder_, input_, output_, log_;
|
|
};
|
|
|
|
TEST_F(EigenApplicationTest, DispatchesFrequencyAndWritesModalSibling) {
|
|
WriteDeck();
|
|
ASSERT_EQ(fesa::FesaApplication{}.Run({input_.string()}), 0);
|
|
ASSERT_TRUE(std::filesystem::exists(output_));
|
|
ASSERT_TRUE(std::filesystem::exists(log_));
|
|
EXPECT_EQ(std::filesystem::file_size(log_), 0U);
|
|
const hid_t file =
|
|
H5Fopen(output_.string().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
|
|
ASSERT_GE(file, 0);
|
|
EXPECT_GT(H5Lexists(file, "/steps/Step-1/eigen/modes", H5P_DEFAULT), 0);
|
|
EXPECT_GT(H5Lexists(file, "/steps/Step-1/eigen/vectors", H5P_DEFAULT), 0);
|
|
EXPECT_EQ(H5Lexists(file, "/steps/Step-1/frames", H5P_DEFAULT), 0);
|
|
EXPECT_GE(H5Fclose(file), 0);
|
|
}
|
|
|
|
TEST_F(EigenApplicationTest, EmptyPencilPreservesPreviousFinalAndEmptyLog) {
|
|
WriteDeck(true);
|
|
const std::string original = "previous authoritative file";
|
|
{
|
|
std::ofstream previous{output_, std::ios::binary};
|
|
previous << original;
|
|
}
|
|
EXPECT_EQ(fesa::FesaApplication{}.Run({input_.string()}), 4);
|
|
std::ifstream previous{output_, std::ios::binary};
|
|
EXPECT_TRUE(std::string(std::istreambuf_iterator<char>{previous}, {}) ==
|
|
original);
|
|
EXPECT_EQ(std::filesystem::file_size(log_), 0U);
|
|
}
|
|
|
|
} // namespace
|