#include "fesa/analysis/analysis_state.h" #include #include #include #include #include namespace { template struct HasVelocity : std::false_type {}; template struct HasVelocity().Velocity())>> : std::true_type {}; template struct HasAcceleration : std::false_type {}; template struct HasAcceleration().Acceleration())>> : std::true_type {}; template struct HasTemperature : std::false_type {}; template struct HasTemperature().Temperature())>> : std::true_type {}; template struct HasIterationHistory : std::false_type {}; template struct HasIterationHistory< T, std::void_t().IterationHistory())>> : std::true_type {}; template struct HasNonlinearState : std::false_type {}; template struct HasNonlinearState< T, std::void_t().NonlinearState())>> : std::true_type {}; fesa::DofManager MakeDofs() { fesa::ModelDefinition definition{}; definition.source_path = "models/analysis-state.inp"; definition.source_content_identity = "fnv1a64:0123456789abcdef"; definition.nodes = { {{"Beam-1", 1, "1"}, {0.0, 0.0, 0.0}, {definition.source_path, 10U}}, {{"Beam-1", 2, "2"}, {1.0, 0.0, 0.0}, {definition.source_path, 11U}}}; definition.steps = {{"Step-1", {{"1", 1, 6, 0.0, {definition.source_path, 20U}}}, {}, 0.1, 1.0, 0.01, 1.0, {definition.source_path, 19U}}}; auto domain = fesa::Domain::Create(std::move(definition)); EXPECT_TRUE(domain.HasValue()); auto model = fesa::AnalysisModel::Create(domain.Value()); EXPECT_TRUE(model.HasValue()); auto dofs = fesa::DofManager::Create(model.Value()); EXPECT_TRUE(dofs.HasValue()); return std::move(dofs.Value()); } void ExpectAllZero(const fesa::Vector& vector) { for (std::size_t index = 0U; index < vector.Size(); ++index) { EXPECT_DOUBLE_EQ(vector[index], 0.0); } } } // namespace TEST(AnalysisState, AllocatesOnlyV0FullVectors) { const auto dofs = MakeDofs(); ASSERT_EQ(dofs.FullDofCount(), 12U); ASSERT_EQ(dofs.ConstrainedDofCount(), 6U); auto state = fesa::AnalysisState::Create(dofs, {"Step-1", 0U}); const fesa::AnalysisState& const_state = state; const fesa::Vector* const vectors[] = { &const_state.Displacement(), &const_state.ExternalForce(), &const_state.InternalForce(), &const_state.Residual(), &const_state.Reaction()}; for (const auto* vector : vectors) { EXPECT_EQ(vector->Size(), dofs.FullDofCount()); ExpectAllZero(*vector); } for (std::size_t left = 0U; left < std::size(vectors); ++left) { for (std::size_t right = left + 1U; right < std::size(vectors); ++right) { EXPECT_NE(vectors[left]->Data(), vectors[right]->Data()); } } state.Displacement()[0] = 4.0; state.Reaction()[11] = -9.0; EXPECT_DOUBLE_EQ(state.Displacement()[0], 4.0); EXPECT_DOUBLE_EQ(state.Reaction()[11], -9.0); EXPECT_DOUBLE_EQ(state.ExternalForce()[0], 0.0); EXPECT_DOUBLE_EQ(state.InternalForce()[0], 0.0); EXPECT_DOUBLE_EQ(state.Residual()[0], 0.0); EXPECT_FALSE(HasVelocity::value); EXPECT_FALSE(HasAcceleration::value); EXPECT_FALSE(HasTemperature::value); EXPECT_FALSE(HasIterationHistory::value); EXPECT_FALSE(HasNonlinearState::value); } TEST(AnalysisState, CopiesOrMovesWithoutAliasing) { static_assert(std::is_copy_constructible_v); static_assert(std::is_copy_assignable_v); static_assert(std::is_move_constructible_v); static_assert(std::is_move_assignable_v); const auto dofs = MakeDofs(); auto original = fesa::AnalysisState::Create(dofs, {"Step-1", 0U}); original.Displacement()[0] = 3.0; original.Reaction()[11] = -2.0; original.EndpointResults().push_back({0U, -1, {"Beam-1", 1, "1"}, {1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.0, 0.0, 0.0, 0.0}}); original.GaussResults().push_back( {0U, 1, {0.1, 0.0, 0.0, 0.0}, {10.0, 0.0, 0.0, 0.0}}); original.StressResults().push_back( {0U, 1, 0U, 0.0, 0.0, 10.0, "fesa-default"}); auto copied = original; EXPECT_NE(copied.Displacement().Data(), original.Displacement().Data()); EXPECT_NE(copied.Reaction().Data(), original.Reaction().Data()); EXPECT_NE(copied.EndpointResults().data(), original.EndpointResults().data()); EXPECT_NE(copied.GaussResults().data(), original.GaussResults().data()); EXPECT_NE(copied.StressResults().data(), original.StressResults().data()); copied.Displacement()[0] = 30.0; copied.EndpointResults()[0].end_action[0] = 20.0; EXPECT_DOUBLE_EQ(original.Displacement()[0], 3.0); EXPECT_DOUBLE_EQ(original.EndpointResults()[0].end_action[0], 1.0); auto moved = std::move(copied); EXPECT_EQ(moved.Identity().step_name, "Step-1"); EXPECT_DOUBLE_EQ(moved.Displacement()[0], 30.0); EXPECT_DOUBLE_EQ(moved.EndpointResults()[0].end_action[0], 20.0); EXPECT_NE(moved.Displacement().Data(), original.Displacement().Data()); EXPECT_NE(moved.EndpointResults().data(), original.EndpointResults().data()); auto copy_assigned = fesa::AnalysisState::Create(dofs, {"Other", 3U}); copy_assigned = original; copy_assigned.Reaction()[11] = -20.0; EXPECT_DOUBLE_EQ(original.Reaction()[11], -2.0); EXPECT_EQ(copy_assigned.Identity().step_name, "Step-1"); auto move_assigned = fesa::AnalysisState::Create(dofs, {"Other", 4U}); move_assigned = std::move(copy_assigned); EXPECT_EQ(move_assigned.Identity().step_name, "Step-1"); EXPECT_DOUBLE_EQ(move_assigned.Reaction()[11], -20.0); EXPECT_NE(move_assigned.Reaction().Data(), original.Reaction().Data()); }