#include "fesa/analysis/analysis_state.hpp" #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< T, std::void_t().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.sourcePath = "models/analysis-state.inp"; definition.sourceContentIdentity = "fnv1a64:0123456789abcdef"; definition.nodes = { {{"Beam-1", 1, "1"}, {0.0, 0.0, 0.0}, {definition.sourcePath, 10U}}, {{"Beam-1", 2, "2"}, {1.0, 0.0, 0.0}, {definition.sourcePath, 11U}}}; definition.steps = {{ "Step-1", {{"1", 1, 6, 0.0, {definition.sourcePath, 20U}}}, {}, 0.1, 1.0, 0.01, 1.0, {definition.sourcePath, 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& constState = state; const fesa::Vector* const vectors[] = { &constState.displacement(), &constState.externalForce(), &constState.internalForce(), &constState.residual(), &constState.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].endAction[0] = 20.0; EXPECT_DOUBLE_EQ(original.displacement()[0], 3.0); EXPECT_DOUBLE_EQ(original.endpointResults()[0].endAction[0], 1.0); auto moved = std::move(copied); EXPECT_EQ(moved.identity().stepName, "Step-1"); EXPECT_DOUBLE_EQ(moved.displacement()[0], 30.0); EXPECT_DOUBLE_EQ(moved.endpointResults()[0].endAction[0], 20.0); EXPECT_NE(moved.displacement().data(), original.displacement().data()); EXPECT_NE(moved.endpointResults().data(), original.endpointResults().data()); auto copyAssigned = fesa::AnalysisState::create(dofs, {"Other", 3U}); copyAssigned = original; copyAssigned.reaction()[11] = -20.0; EXPECT_DOUBLE_EQ(original.reaction()[11], -2.0); EXPECT_EQ(copyAssigned.identity().stepName, "Step-1"); auto moveAssigned = fesa::AnalysisState::create(dofs, {"Other", 4U}); moveAssigned = std::move(copyAssigned); EXPECT_EQ(moveAssigned.identity().stepName, "Step-1"); EXPECT_DOUBLE_EQ(moveAssigned.reaction()[11], -20.0); EXPECT_NE(moveAssigned.reaction().data(), original.reaction().data()); }