From 1e72653a855a91f6a70d688c4c66b2bfcdd2a2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 2 Dec 2018 18:22:33 +0100 Subject: [PATCH 01/31] WIP general gradient process --- .../compute_nodal_gradient_process.cpp | 368 ++++-------------- .../compute_nodal_gradient_process.h | 6 +- kratos/python/add_processes_to_python.cpp | 36 +- .../test_compute_nodal_gradient_process.cpp | 4 +- 4 files changed, 94 insertions(+), 320 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 6b7590ceb59c..6e2851c8cb17 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -26,42 +26,72 @@ namespace Kratos { -template< int TDim, class TVarType, HistoricalValues THist> -void ComputeNodalGradientProcess::Execute() +template +void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; // Set to zero ClearGradient(); - BoundedMatrix DN_DX; - array_1d N; - double Volume; + const auto& it_element_begin = mrModelPart.ElementsBegin(); + const auto& r_first_element_geometry = it_element_begin->GetGeometry(); + const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); + const std::size_t number_of_nodes = r_first_element_geometry.size(); - #pragma omp parallel for private(DN_DX, N, Volume) + // The integration points + const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); + const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); + const std::size_t number_of_integration_points = integration_points.size(); + + Matrix DN_DX(number_of_nodes, dimension); + Vector N(number_of_nodes); + Matrix Ncontainer(number_of_integration_points, number_of_nodes); + Matrix J0(dimension, local_space_dimension); + + #pragma omp parallel for private(DN_DX, N, Ncontainer, J0) for(int i=0; i(mrModelPart.Elements().size()); ++i) { - auto it_elem = mrModelPart.ElementsBegin()+i; - Element::GeometryType& geom = it_elem->GetGeometry(); - GeometryUtils::CalculateGeometryData(geom, DN_DX, N, Volume); + auto it_elem = it_element_begin + i; + auto& r_geometry = it_elem->GetGeometry(); + + Vector values(number_of_nodes); + for(std::size_t i=0; i values; - for(std::size_t i=0; i grad = prod(trans(DN_DX), values); + for ( IndexType point_number = 0; point_number < number_of_integration_points; ++point_number ) { - for(std::size_t i=0; i::InvertMatrix(J0, InvJ0, detJ0); + const Matrix& rDN_De = rDN_DeContainer[point_number]; + GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); + + const Vector grad = prod(trans(DN_DX), values); + const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; + + for(std::size_t i=0; i::Execute() /***********************************************************************************/ template<> -ComputeNodalGradientProcess<2, Variable, Historical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess, Historical>::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, @@ -94,7 +124,7 @@ ComputeNodalGradientProcess<2, Variable, Historical>::ComputeNodalGradie /***********************************************************************************/ template<> -ComputeNodalGradientProcess<2, Variable, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess, NonHistorical>::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, @@ -114,87 +144,7 @@ ComputeNodalGradientProcess<2, Variable, NonHistorical>::ComputeNodalGra /***********************************************************************************/ template<> -ComputeNodalGradientProcess<3, Variable, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY - - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<3, Variable, NonHistorical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY - - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<2, component_type, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - component_type& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY - - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<2, component_type, NonHistorical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - component_type& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY - - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<3, component_type, Historical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, @@ -214,7 +164,7 @@ ComputeNodalGradientProcess<3, component_type, Historical>::ComputeNodalGradient /***********************************************************************************/ template<> -ComputeNodalGradientProcess<3, component_type, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, @@ -234,7 +184,7 @@ ComputeNodalGradientProcess<3, component_type, NonHistorical>::ComputeNodalGradi /***********************************************************************************/ template<> -void ComputeNodalGradientProcess<2, Variable, Historical>::ClearGradient() +void ComputeNodalGradientProcess, Historical>::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -248,32 +198,7 @@ void ComputeNodalGradientProcess<2, Variable, Historical>::ClearGradient /***********************************************************************************/ template<> -void ComputeNodalGradientProcess<3, Variable, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -template<> -void ComputeNodalGradientProcess<2, component_type, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -void ComputeNodalGradientProcess<3, component_type, Historical>::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -287,7 +212,7 @@ void ComputeNodalGradientProcess<3, component_type, Historical>::ClearGradient() /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, Variable, NonHistorical>::ClearGradient() +void ComputeNodalGradientProcess, NonHistorical>::ClearGradient() { const array_1d AuxZeroVector = ZeroVector(3); @@ -303,7 +228,7 @@ void ComputeNodalGradientProcess<2, Variable, NonHistorical>::ClearGradi /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<3, Variable, NonHistorical>::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { const array_1d AuxZeroVector = ZeroVector(3); @@ -319,39 +244,7 @@ void ComputeNodalGradientProcess<3, Variable, NonHistorical>::ClearGradi /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, component_type, NonHistorical>::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, NonHistorical>::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, Variable, Historical>::GetGradient( +double& ComputeNodalGradientProcess, Historical>::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -366,7 +259,7 @@ double& ComputeNodalGradientProcess<2, Variable, Historical>::GetGradien /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess<3, Variable, Historical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -381,37 +274,7 @@ double& ComputeNodalGradientProcess<3, Variable, Historical>::GetGradien /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess<2, component_type, Historical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<3, component_type, Historical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, Variable, NonHistorical>::GetGradient( +double& ComputeNodalGradientProcess, NonHistorical>::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -426,7 +289,7 @@ double& ComputeNodalGradientProcess<2, Variable, NonHistorical>::GetGrad /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess<3, Variable, NonHistorical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -441,50 +304,7 @@ double& ComputeNodalGradientProcess<3, Variable, NonHistorical>::GetGrad /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess<2, component_type, NonHistorical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<3, component_type, NonHistorical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<2, Variable, Historical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node = mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, Variable, Historical>::PonderateGradient() +void ComputeNodalGradientProcess, Historical>::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -497,21 +317,7 @@ void ComputeNodalGradientProcess<3, Variable, Historical>::PonderateGrad /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, component_type, Historical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) - { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, Historical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) @@ -525,7 +331,7 @@ void ComputeNodalGradientProcess<3, component_type, Historical>::PonderateGradie /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, Variable, NonHistorical>::PonderateGradient() +void ComputeNodalGradientProcess, NonHistorical>::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) @@ -539,33 +345,7 @@ void ComputeNodalGradientProcess<2, Variable, NonHistorical>::PonderateG /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<3, Variable, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<2, component_type, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, NonHistorical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -577,13 +357,9 @@ void ComputeNodalGradientProcess<3, component_type, NonHistorical>::PonderateGra /***********************************************************************************/ /***********************************************************************************/ -template class ComputeNodalGradientProcess<2, Variable, Historical>; -template class ComputeNodalGradientProcess<2, Variable, NonHistorical>; -template class ComputeNodalGradientProcess<3, Variable, Historical>; -template class ComputeNodalGradientProcess<3, Variable, NonHistorical>; -template class ComputeNodalGradientProcess<2, component_type, Historical>; -template class ComputeNodalGradientProcess<2, component_type, NonHistorical>; -template class ComputeNodalGradientProcess<3, component_type, Historical>; -template class ComputeNodalGradientProcess<3, component_type, NonHistorical>; +template class ComputeNodalGradientProcess, Historical>; +template class ComputeNodalGradientProcess, NonHistorical>; +template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; } /* namespace Kratos.*/ diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index d0f966f1f645..be6eb820a6f5 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -55,18 +55,16 @@ namespace Kratos * @details This process computes the gradient of a certain variable stored in the nodes * @author Riccardo Rossi * @author Vicente Mataix Ferrandiz - * @tparam TDim The dimension of the problem - * @tparam TVarType The variable type * @tparam THist If the variable is historical or not */ -template< int TDim, class TVarType, HistoricalValues THist> +template class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess : public Process { public: ///@name Type Definitions ///@{ - + /// Pointer definition of ComputeNodalGradientProcess KRATOS_CLASS_POINTER_DEFINITION(ComputeNodalGradientProcess); diff --git a/kratos/python/add_processes_to_python.cpp b/kratos/python/add_processes_to_python.cpp index 3dde22f50133..175da3dccbc7 100644 --- a/kratos/python/add_processes_to_python.cpp +++ b/kratos/python/add_processes_to_python.cpp @@ -267,40 +267,40 @@ void AddProcessesToPython(pybind11::module& m) /* Historical */ // DOUBLE - py::class_, Historical>, ComputeNodalGradientProcess<2, Variable, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess2D") - .def(py::init&, Variable >& , Variable& >()) + py::class_, Historical>, ComputeNodalGradientProcess, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess2D") + .def(py::init&, Variable >& , Variable& >()) ; - py::class_, Historical>, ComputeNodalGradientProcess<3, Variable, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess3D") - .def(py::init&, Variable >& , Variable& >()) + py::class_, Historical>, ComputeNodalGradientProcess, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess3D") + .def(py::init&, Variable >& , Variable& >()) ; // COMPONENT - py::class_, ComputeNodalGradientProcess<2, component_type, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcessComp2D") - .def(py::init >& , Variable& >()) + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcessComp2D") + .def(py::init >& , Variable& >()) ; - py::class_, ComputeNodalGradientProcess<3, component_type, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcessComp3D") - .def(py::init >& , Variable& >()) + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcessComp3D") + .def(py::init >& , Variable& >()) ; /* Non-Historical */ // DOUBLE - py::class_, NonHistorical>, ComputeNodalGradientProcess<2, Variable, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess2D") - .def(py::init&, Variable >& , Variable& >()) - ; + py::class_, NonHistorical>, ComputeNodalGradientProcess, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess2D") + .def(py::init&, Variable >& , Variable& >()) + ; - py::class_, NonHistorical>, ComputeNodalGradientProcess<3, Variable, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess3D") - .def(py::init&, Variable >& , Variable& >()) - ; + py::class_, NonHistorical>, ComputeNodalGradientProcess, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess3D") + .def(py::init&, Variable >& , Variable& >()) + ; // COMPONENT - py::class_, ComputeNodalGradientProcess<2, component_type, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp2D") - .def(py::init >& , Variable& >()) + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp2D") + .def(py::init >& , Variable& >()) ; - py::class_, ComputeNodalGradientProcess<3, component_type, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp3D") - .def(py::init >& , Variable& >()) + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp3D") + .def(py::init >& , Variable& >()) ; // Discontinuous distance computation methods diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index 24154ccbbfaa..46a8dc9991a7 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -111,7 +111,7 @@ namespace Kratos it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; } - typedef ComputeNodalGradientProcess<2, Variable, Historical> GradientType; + typedef ComputeNodalGradientProcess, Historical> GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); @@ -267,7 +267,7 @@ namespace Kratos } // Compute gradient - typedef ComputeNodalGradientProcess<3, Variable, Historical> GradientType; + typedef ComputeNodalGradientProcess, Historical> GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); From d094746519c2e0237ad614093dbe0f9cd6831960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 2 Dec 2018 20:06:07 +0100 Subject: [PATCH 02/31] Corrections --- .../compute_nodal_gradient_process.cpp | 18 ++++++++---------- .../test_compute_nodal_gradient_process.cpp | 10 ++++++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 6e2851c8cb17..20c66ea0e98e 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -38,19 +38,18 @@ void ComputeNodalGradientProcess::Execute() const auto& r_first_element_geometry = it_element_begin->GetGeometry(); const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); - const std::size_t number_of_nodes = r_first_element_geometry.size(); + const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); // The integration points const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); const std::size_t number_of_integration_points = integration_points.size(); - Matrix DN_DX(number_of_nodes, dimension); - Vector N(number_of_nodes); - Matrix Ncontainer(number_of_integration_points, number_of_nodes); - Matrix J0(dimension, local_space_dimension); - - #pragma omp parallel for private(DN_DX, N, Ncontainer, J0) + Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); + Vector N = ZeroVector(number_of_nodes); + Matrix J0 = ZeroMatrix(dimension, local_space_dimension); + + #pragma omp parallel for firstprivate(DN_DX, N, J0) for(int i=0; i(mrModelPart.Elements().size()); ++i) { auto it_elem = it_element_begin + i; auto& r_geometry = it_elem->GetGeometry(); @@ -60,13 +59,12 @@ void ComputeNodalGradientProcess::Execute() values[i] = r_geometry[i].FastGetSolutionStepValue(mrOriginVariable); // The containers of the shape functions and the local gradients - noalias(Ncontainer) = r_geometry.ShapeFunctionsValues(integration_method); + const auto& rNcontainer = r_geometry.ShapeFunctionsValues(integration_method); const auto& rDN_DeContainer = r_geometry.ShapeFunctionsLocalGradients(integration_method); for ( IndexType point_number = 0; point_number < number_of_integration_points; ++point_number ) { - // Getting the shape functions - noalias(N) = row(Ncontainer,point_number); + noalias(N) = row(rNcontainer, point_number); // Getting the jacobians and local gradients GeometryUtils::JacobianOnInitialConfiguration(r_geometry, integration_points[point_number], J0); diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index 46a8dc9991a7..66ef656b02a0 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -59,7 +59,6 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - this_model_part.AddNodalSolutionStepVariable(NODAL_AREA); Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); @@ -75,6 +74,10 @@ namespace Kratos NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + // Now we create the "conditions" std::vector element_nodes_0 (3); element_nodes_0[0] = p_node_1; @@ -139,7 +142,6 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - this_model_part.AddNodalSolutionStepVariable(NODAL_AREA); Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); @@ -162,6 +164,10 @@ namespace Kratos NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + // Now we create the "conditions" std::vector element_nodes_0 (4); element_nodes_0[0] = p_node_12; From c2be8305d29ff7f2eb87beaec47e64635d367858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 00:38:52 +0100 Subject: [PATCH 03/31] Solving problem --- kratos/python/add_processes_to_python.cpp | 24 ++++++++--------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/kratos/python/add_processes_to_python.cpp b/kratos/python/add_processes_to_python.cpp index 175da3dccbc7..8d196090670f 100644 --- a/kratos/python/add_processes_to_python.cpp +++ b/kratos/python/add_processes_to_python.cpp @@ -270,38 +270,30 @@ void AddProcessesToPython(pybind11::module& m) py::class_, Historical>, ComputeNodalGradientProcess, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess2D") .def(py::init&, Variable >& , Variable& >()) ; - - py::class_, Historical>, ComputeNodalGradientProcess, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess3D") - .def(py::init&, Variable >& , Variable& >()) - ; + + m.attr("ComputeNodalGradientProcess3D") = m.attr("ComputeNodalGradientProcess2D"); // COMPONENT py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcessComp2D") .def(py::init >& , Variable& >()) ; - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcessComp3D") - .def(py::init >& , Variable& >()) - ; - + m.attr("ComputeNodalGradientProcessComp3D") = m.attr("ComputeNodalGradientProcessComp2D"); + /* Non-Historical */ // DOUBLE py::class_, NonHistorical>, ComputeNodalGradientProcess, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess2D") .def(py::init&, Variable >& , Variable& >()) ; - py::class_, NonHistorical>, ComputeNodalGradientProcess, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess3D") - .def(py::init&, Variable >& , Variable& >()) - ; - + m.attr("ComputeNonHistoricalNodalGradientProcess3D") = m.attr("ComputeNonHistoricalNodalGradientProcess2D"); + // COMPONENT py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp2D") .def(py::init >& , Variable& >()) ; - - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp3D") - .def(py::init >& , Variable& >()) - ; + + m.attr("ComputeNonHistoricalNodalGradientProcessComp3D") = m.attr("ComputeNonHistoricalNodalGradientProcessComp2D"); // Discontinuous distance computation methods py::class_, CalculateDiscontinuousDistanceToSkinProcess<2>::Pointer, Process>(m,"CalculateDiscontinuousDistanceToSkinProcess2D") From 125b74c968aad401d536098420c783fdde37117b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 01:07:41 +0100 Subject: [PATCH 04/31] Reducing one more level the templates --- .../compute_nodal_gradient_process.cpp | 151 +++++------------- .../compute_nodal_gradient_process.h | 30 ++-- kratos/python/add_processes_to_python.cpp | 32 ++-- .../test_compute_nodal_gradient_process.cpp | 4 +- 4 files changed, 70 insertions(+), 147 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 20c66ea0e98e..628734e98bcf 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -26,8 +26,8 @@ namespace Kratos { -template -void ComputeNodalGradientProcess::Execute() +template +void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; @@ -55,8 +55,13 @@ void ComputeNodalGradientProcess::Execute() auto& r_geometry = it_elem->GetGeometry(); Vector values(number_of_nodes); - for(std::size_t i=0; i 0) { + for(std::size_t i=0; i::Execute() /***********************************************************************************/ template<> -ComputeNodalGradientProcess, Historical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY + // We push the list of double variables + mrOriginVariableDoubleList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; @@ -122,15 +130,18 @@ ComputeNodalGradientProcess, Historical>::ComputeNodalGradientP /***********************************************************************************/ template<> -ComputeNodalGradientProcess, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY + // We push the list of double variables + mrOriginVariableDoubleList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; @@ -142,15 +153,18 @@ ComputeNodalGradientProcess, NonHistorical>::ComputeNodalGradie /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY + // We push the components list + mrOriginVariableComponentsList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; @@ -162,15 +176,18 @@ ComputeNodalGradientProcess::ComputeNodalGradientPro /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY + // We push the components list + mrOriginVariableComponentsList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; @@ -182,21 +199,7 @@ ComputeNodalGradientProcess::ComputeNodalGradient /***********************************************************************************/ template<> -void ComputeNodalGradientProcess, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -void ComputeNodalGradientProcess::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -210,15 +213,15 @@ void ComputeNodalGradientProcess::ClearGradient() /***********************************************************************************/ template <> -void ComputeNodalGradientProcess, NonHistorical>::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { - const array_1d AuxZeroVector = ZeroVector(3); + const array_1d aux_zero_vector = ZeroVector(3); #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); + it_node->SetValue(mrGradientVariable, aux_zero_vector); } } @@ -226,23 +229,7 @@ void ComputeNodalGradientProcess, NonHistorical>::ClearGradient /***********************************************************************************/ template <> -void ComputeNodalGradientProcess::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess, Historical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -257,22 +244,7 @@ double& ComputeNodalGradientProcess, Historical>::GetGradient( /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess, NonHistorical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -287,22 +259,7 @@ double& ComputeNodalGradientProcess, NonHistorical>::GetGradien /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess, Historical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -315,21 +272,7 @@ void ComputeNodalGradientProcess, Historical>::PonderateGradien /***********************************************************************************/ template <> -void ComputeNodalGradientProcess::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) - { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess, NonHistorical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) @@ -338,26 +281,10 @@ void ComputeNodalGradientProcess, NonHistorical>::PonderateGrad it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); } } - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - /***********************************************************************************/ /***********************************************************************************/ -template class ComputeNodalGradientProcess, Historical>; -template class ComputeNodalGradientProcess, NonHistorical>; -template class ComputeNodalGradientProcess; -template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; } /* namespace Kratos.*/ diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index be6eb820a6f5..a26a7dc57a7e 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -57,7 +57,7 @@ namespace Kratos * @author Vicente Mataix Ferrandiz * @tparam THist If the variable is historical or not */ -template +template class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess : public Process { @@ -72,18 +72,21 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ///@name Life Cycle ///@{ - /// Default constructor. + /// Default constructor. (double) ComputeNodalGradientProcess( ModelPart& rModelPart, - TVarType& rOriginVariable, + Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable = NODAL_AREA - ) :mrModelPart(rModelPart), - mrOriginVariable(rOriginVariable), - mrGradientVariable(rGradientVariable), - mrAreaVariable(rAreaVariable) - { - } + ); + + /// Default constructor. (component) + ComputeNodalGradientProcess( + ModelPart& rModelPart, + component_type& rOriginVariable, + Variable >& rGradientVariable, + Variable& rAreaVariable = NODAL_AREA + ); /// Destructor. ~ComputeNodalGradientProcess() override @@ -197,10 +200,11 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ///@name Member Variables ///@{ - ModelPart& mrModelPart; // The main model part - TVarType& mrOriginVariable; // The scalar variable to compute - Variable >& mrGradientVariable; // The resultant gradient variable - Variable& mrAreaVariable; // The auxiliar area variable + ModelPart& mrModelPart; // The main model part + std::vector> mrOriginVariableDoubleList; // The scalar variable list to compute + std::vector mrOriginVariableComponentsList; // The scalar variable list to compute (components) + Variable >& mrGradientVariable; // The resultant gradient variable + Variable& mrAreaVariable; // The auxiliar area variable ///@} ///@name Private Operators diff --git a/kratos/python/add_processes_to_python.cpp b/kratos/python/add_processes_to_python.cpp index 8d196090670f..07cfbd632222 100644 --- a/kratos/python/add_processes_to_python.cpp +++ b/kratos/python/add_processes_to_python.cpp @@ -266,34 +266,26 @@ void AddProcessesToPython(pybind11::module& m) ; /* Historical */ - // DOUBLE - py::class_, Historical>, ComputeNodalGradientProcess, Historical>::Pointer, Process>(m,"ComputeNodalGradientProcess2D") + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcess") + .def(py::init >& , Variable& >()) .def(py::init&, Variable >& , Variable& >()) ; - m.attr("ComputeNodalGradientProcess3D") = m.attr("ComputeNodalGradientProcess2D"); - - // COMPONENT - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcessComp2D") - .def(py::init >& , Variable& >()) - ; - - m.attr("ComputeNodalGradientProcessComp3D") = m.attr("ComputeNodalGradientProcessComp2D"); + m.attr("ComputeNodalGradientProcess2D") = m.attr("ComputeNodalGradientProcess"); + m.attr("ComputeNodalGradientProcess3D") = m.attr("ComputeNodalGradientProcess"); + m.attr("ComputeNodalGradientProcessComp2D") = m.attr("ComputeNodalGradientProcess"); + m.attr("ComputeNodalGradientProcessComp3D") = m.attr("ComputeNodalGradientProcess"); /* Non-Historical */ - // DOUBLE - py::class_, NonHistorical>, ComputeNodalGradientProcess, NonHistorical>::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess2D") + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess") + .def(py::init >& , Variable& >()) .def(py::init&, Variable >& , Variable& >()) ; - m.attr("ComputeNonHistoricalNodalGradientProcess3D") = m.attr("ComputeNonHistoricalNodalGradientProcess2D"); - - // COMPONENT - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcessComp2D") - .def(py::init >& , Variable& >()) - ; - - m.attr("ComputeNonHistoricalNodalGradientProcessComp3D") = m.attr("ComputeNonHistoricalNodalGradientProcessComp2D"); + m.attr("ComputeNonHistoricalNodalGradientProcess2D") = m.attr("ComputeNonHistoricalNodalGradientProcess"); + m.attr("ComputeNonHistoricalNodalGradientProcess3D") = m.attr("ComputeNonHistoricalNodalGradientProcess"); + m.attr("ComputeNonHistoricalNodalGradientProcessComp2D") = m.attr("ComputeNonHistoricalNodalGradientProcess"); + m.attr("ComputeNonHistoricalNodalGradientProcessComp3D") = m.attr("ComputeNonHistoricalNodalGradientProcess"); // Discontinuous distance computation methods py::class_, CalculateDiscontinuousDistanceToSkinProcess<2>::Pointer, Process>(m,"CalculateDiscontinuousDistanceToSkinProcess2D") diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index 66ef656b02a0..0c65b9758188 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -114,7 +114,7 @@ namespace Kratos it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; } - typedef ComputeNodalGradientProcess, Historical> GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); @@ -273,7 +273,7 @@ namespace Kratos } // Compute gradient - typedef ComputeNodalGradientProcess, Historical> GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); From aa0bc33de04e3f5d2cbc1067427d209e294c23a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 01:21:05 +0100 Subject: [PATCH 05/31] Using bool --- .../compute_nodal_gradient_process.cpp | 28 +++++++++---------- .../compute_nodal_gradient_process.h | 15 ++++++++-- kratos/python/add_processes_to_python.cpp | 4 +-- .../test_compute_nodal_gradient_process.cpp | 4 +-- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 628734e98bcf..6fe1027f1021 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -26,8 +26,8 @@ namespace Kratos { -template -void ComputeNodalGradientProcess::Execute() +template +void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; @@ -107,7 +107,7 @@ void ComputeNodalGradientProcess::Execute() /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, @@ -130,7 +130,7 @@ ComputeNodalGradientProcess::ComputeNodalGradientProcess( /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, @@ -153,7 +153,7 @@ ComputeNodalGradientProcess::ComputeNodalGradientProcess( /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, @@ -176,7 +176,7 @@ ComputeNodalGradientProcess::ComputeNodalGradientProcess( /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, component_type& rOriginVariable, Variable >& rGradientVariable, @@ -199,7 +199,7 @@ ComputeNodalGradientProcess::ComputeNodalGradientProcess( /***********************************************************************************/ template<> -void ComputeNodalGradientProcess::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -213,7 +213,7 @@ void ComputeNodalGradientProcess::ClearGradient() /***********************************************************************************/ template <> -void ComputeNodalGradientProcess::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { const array_1d aux_zero_vector = ZeroVector(3); @@ -229,7 +229,7 @@ void ComputeNodalGradientProcess::ClearGradient() /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -244,7 +244,7 @@ double& ComputeNodalGradientProcess::GetGradient( /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -259,7 +259,7 @@ double& ComputeNodalGradientProcess::GetGradient( /***********************************************************************************/ template <> -void ComputeNodalGradientProcess::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -272,7 +272,7 @@ void ComputeNodalGradientProcess::PonderateGradient() /***********************************************************************************/ template <> -void ComputeNodalGradientProcess::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) @@ -284,7 +284,7 @@ void ComputeNodalGradientProcess::PonderateGradient() /***********************************************************************************/ /***********************************************************************************/ -template class ComputeNodalGradientProcess; -template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; } /* namespace Kratos.*/ diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index a26a7dc57a7e..62d0ca3ee4aa 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -20,7 +20,6 @@ // Project includes #include "includes/define.h" -#include "includes/enums.h" #include "processes/process.h" #include "includes/model_part.h" @@ -48,6 +47,16 @@ namespace Kratos ///@name Kratos Classes ///@{ +/** + * @brief This struct is used in order to identify when using the hitorical and non historical variables + */ +struct ComputeNodalGradientProcessSettings +{ + // Defining clearer options + constexpr static bool SaveAsHistoricalVariable = true; + constexpr static bool SaveAsNonHistoricalVariable = false; +}; + /** * @class ComputeNodalGradientProcess * @ingroup KratosCore @@ -55,9 +64,9 @@ namespace Kratos * @details This process computes the gradient of a certain variable stored in the nodes * @author Riccardo Rossi * @author Vicente Mataix Ferrandiz - * @tparam THist If the variable is historical or not + * @tparam THistorical If the variable is historical or not */ -template +template class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess : public Process { diff --git a/kratos/python/add_processes_to_python.cpp b/kratos/python/add_processes_to_python.cpp index 07cfbd632222..68049748fbaa 100644 --- a/kratos/python/add_processes_to_python.cpp +++ b/kratos/python/add_processes_to_python.cpp @@ -266,7 +266,7 @@ void AddProcessesToPython(pybind11::module& m) ; /* Historical */ - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcess") + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNodalGradientProcess") .def(py::init >& , Variable& >()) .def(py::init&, Variable >& , Variable& >()) ; @@ -277,7 +277,7 @@ void AddProcessesToPython(pybind11::module& m) m.attr("ComputeNodalGradientProcessComp3D") = m.attr("ComputeNodalGradientProcess"); /* Non-Historical */ - py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess") + py::class_, ComputeNodalGradientProcess::Pointer, Process>(m,"ComputeNonHistoricalNodalGradientProcess") .def(py::init >& , Variable& >()) .def(py::init&, Variable >& , Variable& >()) ; diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index 0c65b9758188..45b1e6b341a6 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -114,7 +114,7 @@ namespace Kratos it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; } - typedef ComputeNodalGradientProcess GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); @@ -273,7 +273,7 @@ namespace Kratos } // Compute gradient - typedef ComputeNodalGradientProcess GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); From f33da25ce27f46c4d9a54663bb7832b67fef9a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 11:43:55 +0100 Subject: [PATCH 06/31] Removing unused includes --- kratos/processes/compute_nodal_gradient_process.cpp | 9 +++------ kratos/processes/compute_nodal_gradient_process.h | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 6fe1027f1021..b9fc1922546e 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -13,9 +13,6 @@ // /* System includes */ -#include -#include -#include /* External includes */ @@ -155,7 +152,7 @@ ComputeNodalGradientProcess ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, - component_type& rOriginVariable, + ComponentType& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) @@ -178,7 +175,7 @@ ComputeNodalGradientProcess ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, - component_type& rOriginVariable, + ComponentType& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) @@ -187,7 +184,7 @@ ComputeNodalGradientProcessHas( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index 62d0ca3ee4aa..9321e5ac9285 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -33,7 +33,7 @@ namespace Kratos ///@name Type Definitions ///@{ - typedef VariableComponent< VectorComponentAdaptor > > component_type; + typedef VariableComponent< VectorComponentAdaptor > > ComponentType; ///@} ///@name Enum's @@ -92,7 +92,7 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess /// Default constructor. (component) ComputeNodalGradientProcess( ModelPart& rModelPart, - component_type& rOriginVariable, + ComponentType& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable = NODAL_AREA ); @@ -211,7 +211,7 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ModelPart& mrModelPart; // The main model part std::vector> mrOriginVariableDoubleList; // The scalar variable list to compute - std::vector mrOriginVariableComponentsList; // The scalar variable list to compute (components) + std::vector mrOriginVariableComponentsList; // The scalar variable list to compute (components) Variable >& mrGradientVariable; // The resultant gradient variable Variable& mrAreaVariable; // The auxiliar area variable From c0552c2683e213925bd07d82a2deab0c5bde25d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 11:44:14 +0100 Subject: [PATCH 07/31] Adapting --- .../metrics_hessian_process.cpp | 17 ++++++++++++----- .../tests/cpp_tests/test_metric_process.cpp | 6 ++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index 2c27d7400da2..233ca7cb7836 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -224,17 +224,24 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() { // Iterate in the nodes NodesArrayType& nodes_array = mThisModelPart.Nodes(); - const int num_nodes = nodes_array.end() - nodes_array.begin(); + const int num_nodes = static_cast(nodes_array.size()); // Declaring auxiliar vector - const TensorArrayType aux_zero_vector = ZeroVector(3 * (TDim - 1)); + const TensorArrayType aux_zero_array = ZeroVector(3 * (TDim - 1)); + const array_1d aux_zero_vector = ZeroVector(3); + // Initialize auxiliar variables + const auto& it_nodes_begin = nodes_array.begin(); #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) - (nodes_array.begin() + i)->SetValue(AUXILIAR_HESSIAN, aux_zero_vector); + for(int i = 0; i < num_nodes; ++i) { + auto it_node = it_nodes_begin + i; + it_node->SetValue(NODAL_AREA, 0.0); + it_node->SetValue(AUXILIAR_HESSIAN, aux_zero_array); + it_node->SetValue(AUXILIAR_GRADIENT, aux_zero_vector); + } // Compute auxiliar gradient - ComputeNodalGradientProcess gradient_process = ComputeNodalGradientProcess(mThisModelPart, mVariable, AUXILIAR_GRADIENT, NODAL_AREA); + auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mVariable, AUXILIAR_GRADIENT, NODAL_AREA); gradient_process.Execute(); // Iterate in the conditions diff --git a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp index 6a7886146fdc..baf4347fd371 100644 --- a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp +++ b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp @@ -254,10 +254,11 @@ namespace Kratos auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_H, 1.0); + it_node->SetValue(NODAL_AREA, 0.0); it_node->SetValue(METRIC_TENSOR_2D, ZeroVector(3)); } - typedef ComputeNodalGradientProcess<2, Variable, Historical> GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType gradient_process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT, NODAL_AREA); gradient_process.Execute(); @@ -303,11 +304,12 @@ namespace Kratos auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_H, 1.0); + it_node->SetValue(NODAL_AREA, 0.0); it_node->SetValue(METRIC_TENSOR_3D, ZeroVector(6)); } // Compute gradient - typedef ComputeNodalGradientProcess<3, Variable, Historical> GradientType; + typedef ComputeNodalGradientProcess GradientType; GradientType gradient_process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT, NODAL_AREA); gradient_process.Execute(); From f5703c658d90ebff712cd770d6b871ace84b6ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 12:55:29 +0100 Subject: [PATCH 08/31] Update sol files --- .../beam2D_line_load_test_result.sol | 42 +-- .../beam2D_test_result.sol | 138 ++++----- .../beam3D_test_result.sol | 280 +++++++++--------- 3 files changed, 230 insertions(+), 230 deletions(-) diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol index 52f10242c6e4..daad472a1f39 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol @@ -21,33 +21,33 @@ SolAtVertices 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 1973.83483408483 0 1973.83483408483 + 2239.55190816785 0 2239.55190816785 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 1783.02450156543 0 1783.02450156543 - 2233.44222914806 0 2233.44222914806 + 1939.56114223364 0 1939.56114223364 + 2438.9855715349 0 2438.9855715349 + 1697.88406875709 0 1697.88406875709 1596.1682065273 0 1596.1682065273 - 1596.1682065273 0 1596.1682065273 - 2830.0529672361 0 2830.0529672361 - 2333.06689841094 0 2333.06689841094 - 2754.22625279034 0 2754.22625279034 - 3085.06572970157 0 3085.06572970157 - 2033.03549117724 0 2033.03549117724 - 3648.33349336322 0 3648.33349336322 - 3387.53606158952 0 3387.53606158952 - 3054.17230013612 0 3054.17230013612 - 3919.07288195414 0 3919.07288195414 - 4359.98062035213 0 4359.98062035213 - 4580.1152299552 0 4580.1152299552 - 4193.9182665218 0 4193.9182665218 - 4564.40173273184 0 4564.40173273184 - 5444.9092312109 0 5444.9092312109 - 6157.29896814932 0 6157.29896814932 + 3274.24585263818 0 3274.24585263818 + 2554.56707778872 0 2554.56707778872 + 2844.51057414303 0 2844.51057414303 + 3549.14057974895 0 3549.14057974895 + 1965.17855255292 0 1965.17855255292 + 4249.672620598 0 4249.672620598 + 3548.28899887462 0 3548.28899887462 + 2900.91505366977 0 2900.91505366977 + 4053.92761436963 0 4053.92761436963 + 4522.84459146374 0 4522.84459146374 + 5332.77651426404 0 5332.77651426404 + 3957.30289321615 0 3957.30289321615 + 4875.3926507737 0 4875.3926507737 + 5367.03504165936 0 5367.03504165936 + 6025.20946187374 0 6025.20946187374 6384.67282610918 0 6384.67282610918 - 5509.26950609488 0 5509.26950609488 - 5817.25316009115 0 5817.25316009115 + 5178.09614105904 0 5178.09614105904 + 6323.08024706008 0 6323.08024706008 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol index ff352c6eec42..fd088704f3d0 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol @@ -7,77 +7,77 @@ Dimension SolAtVertices 205 1 3 - 35.9101637379947 0 35.9101637379947 - 37.4367319907306 0 37.4367319907306 - 26.2566573854866 0 26.2566573854866 - 33.410918127346 0 33.410918127346 + 35.9140018842354 0 35.9140018842354 + 37.4397284135075 0 37.4397284135075 + 26.2583588730124 0 26.2583588730124 + 33.4131182686942 0 33.4131182686942 30.2668616137121 0 30.2668616137121 - 39.4995524908847 0 39.4995524908847 - 21.7518979323714 0 21.7518979323714 + 39.5033684796239 0 39.5033684796239 + 21.7521188387394 0 21.7521188387394 30.2668616137121 0 30.2668616137121 - 34.7899307544646 0 34.7899307544646 - 37.2336861625557 0 37.2336861625557 - 36.0263728933714 0 36.0263728933714 - 25.0209084013989 0 25.0209084013989 - 33.2528253574337 0 33.2528253574337 - 32.7410519353801 0 32.7410519353801 - 32.3652989726995 0 32.3652989726995 - 34.6480898721677 0 34.6480898721677 - 30.4481389105709 0 30.4481389105709 - 35.7736766879115 0 35.7736766879115 - 34.5222528912967 0 34.5222528912967 - 38.5869366910055 0 38.5869366910055 - 31.8229556412735 0 31.8229556412735 - 28.8360160894753 0 28.8360160894753 - 32.8305343431724 0 32.8305343431724 - 35.2779086996321 0 35.2779086996321 - 27.5604426825636 0 27.5604426825636 - 31.369834994686 0 31.369834994686 - 29.7131102638918 0 29.7131102638918 - 27.2120608961529 0 27.2120608961529 - 32.3129342013113 0 32.3129342013113 - 27.0409428791352 0 27.0409428791352 - 28.3068155213527 0 28.3068155213527 - 27.879208923983 0 27.879208923983 - 29.6339719883714 0 29.6339719883714 - 26.3374102967325 0 26.3374102967325 - 25.084751519167 0 25.084751519167 - 27.7256981050374 0 27.7256981050374 - 25.9932252275203 0 25.9932252275203 - 25.5242330886323 0 25.5242330886323 - 24.3569152890673 0 24.3569152890673 - 23.5078082385583 0 23.5078082385583 - 25.5003560190692 0 25.5003560190692 - 24.6357056743481 0 24.6357056743481 - 24.2516297234798 0 24.2516297234798 - 23.2508413731498 0 23.2508413731498 - 23.9496149419695 0 23.9496149419695 - 22.695867515866 0 22.695867515866 - 22.868593567692 0 22.868593567692 - 22.4404691219244 0 22.4404691219244 - 21.8135888475102 0 21.8135888475102 - 22.2702038034889 0 22.2702038034889 - 21.3863489488884 0 21.3863489488884 - 21.3263847639816 0 21.3263847639816 - 20.7023246411292 0 20.7023246411292 - 19.9829308632535 0 19.9829308632535 - 20.6919954413751 0 20.6919954413751 - 20.1100772583546 0 20.1100772583546 - 19.3895747360983 0 19.3895747360983 - 19.3479987996405 0 19.3479987996405 - 19.1049270364835 0 19.1049270364835 - 19.2993646488359 0 19.2993646488359 - 18.7602306557437 0 18.7602306557437 - 19.4308765674892 0 19.4308765674892 - 17.8599794183255 0 17.8599794183255 - 17.9198645601064 0 17.9198645601064 - 17.9608749777344 0 17.9608749777344 - 17.4075287793985 0 17.4075287793985 - 17.8079007695172 0 17.8079007695172 - 16.657995600629 0 16.657995600629 - 16.6834949119661 0 16.6834949119661 - 16.9050455076346 0 16.9050455076346 - 16.5444845098659 0 16.5444845098659 + 34.7907840772552 0 34.7907840772552 + 37.2337481488278 0 37.2337481488278 + 36.0308766576983 0 36.0308766576983 + 25.0193355233973 0 25.0193355233973 + 33.2506017597463 0 33.2506017597463 + 32.7389817288463 0 32.7389817288463 + 32.3638339058948 0 32.3638339058948 + 34.6444870591263 0 34.6444870591263 + 30.4526775711213 0 30.4526775711213 + 35.7726381150214 0 35.7726381150214 + 34.5194786258534 0 34.5194786258534 + 38.5829285575872 0 38.5829285575872 + 31.8203037467802 0 31.8203037467802 + 28.8340591256521 0 28.8340591256521 + 32.831735144249 0 32.831735144249 + 35.2781955379513 0 35.2781955379513 + 27.5587311214965 0 27.5587311214965 + 31.3715104402689 0 31.3715104402689 + 29.7158865764926 0 29.7158865764926 + 27.2119874541355 0 27.2119874541355 + 32.313977702091 0 32.313977702091 + 27.0387600275092 0 27.0387600275092 + 28.308992404692 0 28.308992404692 + 27.8822524088032 0 27.8822524088032 + 29.6289378246923 0 29.6289378246923 + 26.3347055267636 0 26.3347055267636 + 25.0899015839709 0 25.0899015839709 + 27.7206399435361 0 27.7206399435361 + 25.9957424765933 0 25.9957424765933 + 25.5275119357513 0 25.5275119357513 + 24.3539695392516 0 24.3539695392516 + 23.5129099906319 0 23.5129099906319 + 25.4952181353372 0 25.4952181353372 + 24.6384741984057 0 24.6384741984057 + 24.2550590469 0 24.2550590469 + 23.2553571583674 0 23.2553571583674 + 23.9444429458136 0 23.9444429458136 + 22.7010033263282 0 22.7010033263282 + 22.8715692339873 0 22.8715692339873 + 22.4440239475518 0 22.4440239475518 + 21.818145354373 0 21.818145354373 + 22.2650362132523 0 22.2650362132523 + 21.3913943803489 0 21.3913943803489 + 21.3294780605533 0 21.3294780605533 + 20.6985502651528 0 20.6985502651528 + 19.9874155232717 0 19.9874155232717 + 20.695033636421 0 20.695033636421 + 20.1132218224946 0 20.1132218224946 + 19.3943965334395 0 19.3943965334395 + 19.3516405294764 0 19.3516405294764 + 19.1093155299435 0 19.1093155299435 + 19.2942910399988 0 19.2942910399988 + 18.7634198651674 0 18.7634198651674 + 19.4357707933614 0 19.4357707933614 + 17.8636087889326 0 17.8636087889326 + 17.9165850207371 0 17.9165850207371 + 17.9639968324299 0 17.9639968324299 + 17.4106302371692 0 17.4106302371692 + 17.8048364572601 0 17.8048364572601 + 16.6544076033481 0 16.6544076033481 + 16.6804800592124 0 16.6804800592124 + 16.9081523865639 0 16.9081523865639 + 16.5475094343016 0 16.5475094343016 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam3D_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam3D_test_result.sol index 493d92a0bd65..31e3e0c64943 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam3D_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam3D_test_result.sol @@ -7,138 +7,138 @@ Dimension SolAtVertices 224 1 3 -27.7035626161233 0 27.7035626161233 0 0 27.7035626161233 -17.022367691514 0 17.022367691514 0 0 17.022367691514 -25.355481664933 0 25.355481664933 0 0 25.355481664933 -20.0288569979345 0 20.0288569979345 0 0 20.0288569979345 -21.89484350378 0 21.89484350378 0 0 21.89484350378 -22.5371603355171 0 22.5371603355171 0 0 22.5371603355171 -25.2328942120125 0 25.2328942120125 0 0 25.2328942120125 -24.6906878741862 0 24.6906878741862 0 0 24.6906878741862 -23.5209851368877 0 23.5209851368877 0 0 23.5209851368877 -27.2051885688751 0 27.2051885688751 0 0 27.2051885688751 -23.7038914066742 0 23.7038914066742 0 0 23.7038914066742 -26.8232916744992 0 26.8232916744992 0 0 26.8232916744992 -20.5420941066609 0 20.5420941066609 0 0 20.5420941066609 -20.9751300360015 0 20.9751300360015 0 0 20.9751300360015 -30.0155679986682 0 30.0155679986682 0 0 30.0155679986682 -23.4678846419606 0 23.4678846419606 0 0 23.4678846419606 -15.2378861117701 0 15.2378861117701 0 0 15.2378861117701 -24.4602537914722 0 24.4602537914722 0 0 24.4602537914722 -26.0312536439935 0 26.0312536439935 0 0 26.0312536439935 -26.3754649289435 0 26.3754649289435 0 0 26.3754649289435 -25.3588617914023 0 25.3588617914023 0 0 25.3588617914023 -25.8562007727243 0 25.8562007727243 0 0 25.8562007727243 -25.9820866445989 0 25.9820866445989 0 0 25.9820866445989 -28.0485555161631 0 28.0485555161631 0 0 28.0485555161631 -28.2067151374578 0 28.2067151374578 0 0 28.2067151374578 -28.0943518256723 0 28.0943518256723 0 0 28.0943518256723 -24.6232520628818 0 24.6232520628818 0 0 24.6232520628818 -23.1627548939625 0 23.1627548939625 0 0 23.1627548939625 -25.0746783214843 0 25.0746783214843 0 0 25.0746783214843 -27.0514757048651 0 27.0514757048651 0 0 27.0514757048651 -28.5184631116839 0 28.5184631116839 0 0 28.5184631116839 -21.5808089749154 0 21.5808089749154 0 0 21.5808089749154 -22.3410583905441 0 22.3410583905441 0 0 22.3410583905441 -22.0333439029875 0 22.0333439029875 0 0 22.0333439029875 -21.7450316639833 0 21.7450316639833 0 0 21.7450316639833 -23.1482758220858 0 23.1482758220858 0 0 23.1482758220858 -20.5911061371322 0 20.5911061371322 0 0 20.5911061371322 -19.3067696885139 0 19.3067696885139 0 0 19.3067696885139 -20.0891252144247 0 20.0891252144247 0 0 20.0891252144247 -21.5935804930098 0 21.5935804930098 0 0 21.5935804930098 -21.3806124773869 0 21.3806124773869 0 0 21.3806124773869 -22.9581844181729 0 22.9581844181729 0 0 22.9581844181729 -20.8562612449711 0 20.8562612449711 0 0 20.8562612449711 -19.5486594086639 0 19.5486594086639 0 0 19.5486594086639 -18.2028063118509 0 18.2028063118509 0 0 18.2028063118509 -20.2619604911674 0 20.2619604911674 0 0 20.2619604911674 -18.7699614525379 0 18.7699614525379 0 0 18.7699614525379 -18.2346814216115 0 18.2346814216115 0 0 18.2346814216115 -19.2139607699384 0 19.2139607699384 0 0 19.2139607699384 -16.6312785781068 0 16.6312785781068 0 0 16.6312785781068 -20.7226895955545 0 20.7226895955545 0 0 20.7226895955545 -19.7766515181522 0 19.7766515181522 0 0 19.7766515181522 -17.1565673048547 0 17.1565673048547 0 0 17.1565673048547 -17.6439367464756 0 17.6439367464756 0 0 17.6439367464756 -16.1116279129533 0 16.1116279129533 0 0 16.1116279129533 -19.2843584261176 0 19.2843584261176 0 0 19.2843584261176 -16.967474634563 0 16.967474634563 0 0 16.967474634563 -16.9902676810897 0 16.9902676810897 0 0 16.9902676810897 -17.5921558562483 0 17.5921558562483 0 0 17.5921558562483 -14.8276810794386 0 14.8276810794386 0 0 14.8276810794386 -18.2855785011589 0 18.2855785011589 0 0 18.2855785011589 -14.8661717707709 0 14.8661717707709 0 0 14.8661717707709 -14.7686109193122 0 14.7686109193122 0 0 14.7686109193122 -16.9554609692555 0 16.9554609692555 0 0 16.9554609692555 -13.455540017933 0 13.455540017933 0 0 13.455540017933 -14.185483630148 0 14.185483630148 0 0 14.185483630148 -15.8277064200399 0 15.8277064200399 0 0 15.8277064200399 -14.1849599388393 0 14.1849599388393 0 0 14.1849599388393 -14.1018061112717 0 14.1018061112717 0 0 14.1018061112717 -13.4442013135134 0 13.4442013135134 0 0 13.4442013135134 -13.5999714770016 0 13.5999714770016 0 0 13.5999714770016 -14.5481936084951 0 14.5481936084951 0 0 14.5481936084951 -14.5479848494158 0 14.5479848494158 0 0 14.5479848494158 -12.9909304345219 0 12.9909304345219 0 0 12.9909304345219 -12.8092665161218 0 12.8092665161218 0 0 12.8092665161218 -11.3983751171588 0 11.3983751171588 0 0 11.3983751171588 -11.6144472344102 0 11.6144472344102 0 0 11.6144472344102 -12.9055162943599 0 12.9055162943599 0 0 12.9055162943599 -11.9333785334854 0 11.9333785334854 0 0 11.9333785334854 -12.1137609258182 0 12.1137609258182 0 0 12.1137609258182 -12.5696566494541 0 12.5696566494541 0 0 12.5696566494541 -11.3550189726419 0 11.3550189726419 0 0 11.3550189726419 -10.3677942410406 0 10.3677942410406 0 0 10.3677942410406 -10.1398620246949 0 10.1398620246949 0 0 10.1398620246949 -10.760157630112 0 10.760157630112 0 0 10.760157630112 -10.259438150323 0 10.259438150323 0 0 10.259438150323 -9.65921823604312 0 9.65921823604312 0 0 9.65921823604312 -9.1418657201665 0 9.1418657201665 0 0 9.1418657201665 -9.39233794545191 0 9.39233794545191 0 0 9.39233794545191 -9.02694252618019 0 9.02694252618019 0 0 9.02694252618019 -9.72916342998384 0 9.72916342998384 0 0 9.72916342998384 -9.58652539038531 0 9.58652539038531 0 0 9.58652539038531 -8.32678915384327 0 8.32678915384327 0 0 8.32678915384327 -9.27454215520464 0 9.27454215520464 0 0 9.27454215520464 -9.53277137698498 0 9.53277137698498 0 0 9.53277137698498 -8.89894818733828 0 8.89894818733828 0 0 8.89894818733828 -8.51660823683054 0 8.51660823683054 0 0 8.51660823683054 -8.22609130240348 0 8.22609130240348 0 0 8.22609130240348 -7.87642627781283 0 7.87642627781283 0 0 7.87642627781283 -8.33949942560789 0 8.33949942560789 0 0 8.33949942560789 -8.5807679085591 0 8.5807679085591 0 0 8.5807679085591 -7.85107300473627 0 7.85107300473627 0 0 7.85107300473627 -8.42153377613511 0 8.42153377613511 0 0 8.42153377613511 -6.91498232488896 0 6.91498232488896 0 0 6.91498232488896 -8.02491969678893 0 8.02491969678893 0 0 8.02491969678893 -7.40582739573172 0 7.40582739573172 0 0 7.40582739573172 -7.15130340264934 0 7.15130340264934 0 0 7.15130340264934 +27.7057416888572 0 27.7057416888572 0 0 27.7057416888572 +17.0223617137705 0 17.0223617137705 0 0 17.0223617137705 +25.3568602712687 0 25.3568602712687 0 0 25.3568602712687 +20.0283499660681 0 20.0283499660681 0 0 20.0283499660681 +21.8959336459052 0 21.8959336459052 0 0 21.8959336459052 +22.5376651387608 0 22.5376651387608 0 0 22.5376651387608 +25.2348849289845 0 25.2348849289845 0 0 25.2348849289845 +24.6906579607744 0 24.6906579607744 0 0 24.6906579607744 +23.521905668729 0 23.521905668729 0 0 23.521905668729 +27.2028032365598 0 27.2028032365598 0 0 27.2028032365598 +23.7054976030952 0 23.7054976030952 0 0 23.7054976030952 +26.8243396718601 0 26.8243396718601 0 0 26.8243396718601 +20.5413014388128 0 20.5413014388128 0 0 20.5413014388128 +20.9738129236526 0 20.9738129236526 0 0 20.9738129236526 +30.0139579495844 0 30.0139579495844 0 0 30.0139579495844 +23.4691868016015 0 23.4691868016015 0 0 23.4691868016015 +15.237420818953 0 15.237420818953 0 0 15.237420818953 +24.4591378882655 0 24.4591378882655 0 0 24.4591378882655 +26.0316962124953 0 26.0316962124953 0 0 26.0316962124953 +26.3766673195715 0 26.3766673195715 0 0 26.3766673195715 +25.3604866056377 0 25.3604866056377 0 0 25.3604866056377 +25.8577215644443 0 25.8577215644443 0 0 25.8577215644443 +25.981061888996 0 25.981061888996 0 0 25.981061888996 +28.0462801370087 0 28.0462801370087 0 0 28.0462801370087 +28.2077696756407 0 28.2077696756407 0 0 28.2077696756407 +28.0932587116364 0 28.0932587116364 0 0 28.0932587116364 +24.621674048973 0 24.621674048973 0 0 24.621674048973 +23.1612958766903 0 23.1612958766903 0 0 23.1612958766903 +25.076709398064 0 25.076709398064 0 0 25.076709398064 +27.0524684691216 0 27.0524684691216 0 0 27.0524684691216 +28.5193560954211 0 28.5193560954211 0 0 28.5193560954211 +21.5825402240725 0 21.5825402240725 0 0 21.5825402240725 +22.3433381659784 0 22.3433381659784 0 0 22.3433381659784 +22.0344961916228 0 22.0344961916228 0 0 22.0344961916228 +21.7435600014087 0 21.7435600014087 0 0 21.7435600014087 +23.1466536412384 0 23.1466536412384 0 0 23.1466536412384 +20.5931898199178 0 20.5931898199178 0 0 20.5931898199178 +19.3092821821558 0 19.3092821821558 0 0 19.3092821821558 +20.0869812521228 0 20.0869812521228 0 0 20.0869812521228 +21.5948417598932 0 21.5948417598932 0 0 21.5948417598932 +21.3821103133146 0 21.3821103133146 0 0 21.3821103133146 +22.9607448032594 0 22.9607448032594 0 0 22.9607448032594 +20.8536951624291 0 20.8536951624291 0 0 20.8536951624291 +19.5487537117075 0 19.5487537117075 0 0 19.5487537117075 +18.2031009644258 0 18.2031009644258 0 0 18.2031009644258 +20.2648693637971 0 20.2648693637971 0 0 20.2648693637971 +18.7672124285481 0 18.7672124285481 0 0 18.7672124285481 +18.2374163066341 0 18.2374163066341 0 0 18.2374163066341 +19.2112877416363 0 19.2112877416363 0 0 19.2112877416363 +16.6338551874949 0 16.6338551874949 0 0 16.6338551874949 +20.7195954174141 0 20.7195954174141 0 0 20.7195954174141 +19.7739110349597 0 19.7739110349597 0 0 19.7739110349597 +17.154178028332 0 17.154178028332 0 0 17.154178028332 +17.6463152926316 0 17.6463152926316 0 0 17.6463152926316 +16.1089946721111 0 16.1089946721111 0 0 16.1089946721111 +19.2868107746792 0 19.2868107746792 0 0 19.2868107746792 +16.9649846850946 0 16.9649846850946 0 0 16.9649846850946 +16.9927382086824 0 16.9927382086824 0 0 16.9927382086824 +17.5944569502259 0 17.5944569502259 0 0 17.5944569502259 +14.8299139455351 0 14.8299139455351 0 0 14.8299139455351 +18.2829290757951 0 18.2829290757951 0 0 18.2829290757951 +14.8636697773977 0 14.8636697773977 0 0 14.8636697773977 +14.7707289214118 0 14.7707289214118 0 0 14.7707289214118 +16.9581109949642 0 16.9581109949642 0 0 16.9581109949642 +13.4534439547323 0 13.4534439547323 0 0 13.4534439547323 +14.1832885653418 0 14.1832885653418 0 0 14.1832885653418 +15.8298718306675 0 15.8298718306675 0 0 15.8298718306675 +14.1868526744314 0 14.1868526744314 0 0 14.1868526744314 +14.1039576683544 0 14.1039576683544 0 0 14.1039576683544 +13.4464138623935 0 13.4464138623935 0 0 13.4464138623935 +13.59766283544 0 13.59766283544 0 0 13.59766283544 +14.5457976841306 0 14.5457976841306 0 0 14.5457976841306 +14.5454286035634 0 14.5454286035634 0 0 14.5454286035634 +12.9888387133305 0 12.9888387133305 0 0 12.9888387133305 +12.8115209520957 0 12.8115209520957 0 0 12.8115209520957 +11.4004674578534 0 11.4004674578534 0 0 11.4004674578534 +11.6164851666254 0 11.6164851666254 0 0 11.6164851666254 +12.9031208486348 0 12.9031208486348 0 0 12.9031208486348 +11.9356126768213 0 11.9356126768213 0 0 11.9356126768213 +12.1115039293692 0 12.1115039293692 0 0 12.1115039293692 +12.5672877919797 0 12.5672877919797 0 0 12.5672877919797 +11.3571498489514 0 11.3571498489514 0 0 11.3571498489514 +10.3658906660789 0 10.3658906660789 0 0 10.3658906660789 +10.1377788249695 0 10.1377788249695 0 0 10.1377788249695 +10.7620991175534 0 10.7620991175534 0 0 10.7620991175534 +10.2613172442114 0 10.2613172442114 0 0 10.2613172442114 +9.65746213268743 0 9.65746213268743 0 0 9.65746213268743 +9.14200957455898 0 9.14200957455898 0 0 9.14200957455898 +9.39404070277063 0 9.39404070277063 0 0 9.39404070277063 +9.02493721337671 0 9.02493721337671 0 0 9.02493721337671 +9.73107079638935 0 9.73107079638935 0 0 9.73107079638935 +9.58463971047051 0 9.58463971047051 0 0 9.58463971047051 +8.32532694867183 0 8.32532694867183 0 0 8.32532694867183 +9.27274720466372 0 9.27274720466372 0 0 9.27274720466372 +9.53087104007251 0 9.53087104007251 0 0 9.53087104007251 +8.89728994493967 0 8.89728994493967 0 0 8.89728994493967 +8.51814956619836 0 8.51814956619836 0 0 8.51814956619836 +8.2277167139307 0 8.2277167139307 0 0 8.2277167139307 +7.87801847229764 0 7.87801847229764 0 0 7.87801847229764 +8.3377890067277 0 8.3377890067277 0 0 8.3377890067277 +8.57897370257185 0 8.57897370257185 0 0 8.57897370257185 +7.85272438427157 0 7.85272438427157 0 0 7.85272438427157 +8.41978512232926 0 8.41978512232926 0 0 8.41978512232926 +6.91637815456035 0 6.91637815456035 0 0 6.91637815456035 +8.02629418003215 0 8.02629418003215 0 0 8.02629418003215 +7.40436757626627 0 7.40436757626627 0 0 7.40436757626627 +7.15278252449708 0 7.15278252449708 0 0 7.15278252449708 7.21509701078706 0 7.21509701078706 0 0 7.21509701078706 -6.96124373392133 0 6.96124373392133 0 0 6.96124373392133 -6.77481781258337 0 6.77481781258337 0 0 6.77481781258337 -6.41416375479511 0 6.41416375479511 0 0 6.41416375479511 -7.4135495366291 0 7.4135495366291 0 0 7.4135495366291 -6.40460849965883 0 6.40460849965883 0 0 6.40460849965883 +6.96249910773807 0 6.96249910773807 0 0 6.96249910773807 +6.77365040868535 0 6.77365040868535 0 0 6.77365040868535 +6.41549949953902 0 6.41549949953902 0 0 6.41549949953902 +7.41354953662909 0 7.41354953662909 0 0 7.41354953662909 +6.40341568349489 0 6.40341568349489 0 0 6.40341568349489 7.21509701078706 0 7.21509701078706 0 0 7.21509701078706 -6.0844104143319 0 6.0844104143319 0 0 6.0844104143319 -8.81187620865784 0 8.81187620865784 0 0 8.81187620865784 -7.4135495366291 0 7.4135495366291 0 0 7.4135495366291 -6.67848542327411 0 6.67848542327411 0 0 6.67848542327411 +6.08441041433191 0 6.08441041433191 0 0 6.08441041433191 +8.81187620865783 0 8.81187620865783 0 0 8.81187620865783 +7.41354953662909 0 7.41354953662909 0 0 7.41354953662909 +6.67848542327412 0 6.67848542327412 0 0 6.67848542327412 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -9.3422758815462 0 9.3422758815462 0 0 9.3422758815462 -7.53158400810561 0 7.53158400810561 0 0 7.53158400810561 +9.34227588154621 0 9.34227588154621 0 0 9.34227588154621 +7.5315840081056 0 7.5315840081056 0 0 7.5315840081056 8.82872300048485 0 8.82872300048485 0 0 8.82872300048485 7.2232577301389 0 7.2232577301389 0 0 7.2232577301389 -9.3422758815462 0 9.3422758815462 0 0 9.3422758815462 +9.34227588154621 0 9.34227588154621 0 0 9.34227588154621 8.82872300048485 0 8.82872300048485 0 0 8.82872300048485 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -6.0844285066826 0 6.0844285066826 0 0 6.0844285066826 -6.59887122782258 0 6.59887122782258 0 0 6.59887122782258 +6.08442850668259 0 6.08442850668259 0 0 6.08442850668259 +6.59887122782256 0 6.59887122782256 0 0 6.59887122782256 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 6.67849296286621 0 6.67849296286621 0 0 6.67849296286621 -7.22330841065305 0 7.22330841065305 0 0 7.22330841065305 -7.22330841065305 0 7.22330841065305 0 0 7.22330841065305 +7.22330841065306 0 7.22330841065306 0 0 7.22330841065306 +7.22330841065306 0 7.22330841065306 0 0 7.22330841065306 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.64528686853841 0 5.64528686853841 0 0 5.64528686853841 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 @@ -146,34 +146,34 @@ SolAtVertices 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -6.6054973151869 0 6.6054973151869 0 0 6.6054973151869 +6.60549731518692 0 6.60549731518692 0 0 6.60549731518692 5.64528686853841 0 5.64528686853841 0 0 5.64528686853841 -6.67848266745382 0 6.67848266745382 0 0 6.67848266745382 +6.67848266745381 0 6.67848266745381 0 0 6.67848266745381 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -6.67848970352474 0 6.67848970352474 0 0 6.67848970352474 +6.67848970352473 0 6.67848970352473 0 0 6.67848970352473 6.92865943359195 0 6.92865943359195 0 0 6.92865943359195 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 7.1109948746102 0 7.1109948746102 0 0 7.1109948746102 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 7.1109948746102 0 7.1109948746102 0 0 7.1109948746102 8.77818372511676 0 8.77818372511676 0 0 8.77818372511676 -7.28428182558793 0 7.28428182558793 0 0 7.28428182558793 +7.28428182558795 0 7.28428182558795 0 0 7.28428182558795 5.54924766849245 0 5.54924766849245 0 0 5.54924766849245 -6.67848970352474 0 6.67848970352474 0 0 6.67848970352474 +6.67848970352473 0 6.67848970352473 0 0 6.67848970352473 9.52636417462794 0 9.52636417462794 0 0 9.52636417462794 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -9.99760121892725 0 9.99760121892725 0 0 9.99760121892725 -8.88188464672214 0 8.88188464672214 0 0 8.88188464672214 -9.99760121892725 0 9.99760121892725 0 0 9.99760121892725 +9.99760121892726 0 9.99760121892726 0 0 9.99760121892726 +8.88188464672215 0 8.88188464672215 0 0 8.88188464672215 +9.99760121892726 0 9.99760121892726 0 0 9.99760121892726 9.52636417462794 0 9.52636417462794 0 0 9.52636417462794 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -8.88188464672214 0 8.88188464672214 0 0 8.88188464672214 -6.26500647448228 0 6.26500647448228 0 0 6.26500647448228 +8.88188464672215 0 8.88188464672215 0 0 8.88188464672215 +6.26500647448227 0 6.26500647448227 0 0 6.26500647448227 6.36214889882061 0 6.36214889882061 0 0 6.36214889882061 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 6.67848696393902 0 6.67848696393902 0 0 6.67848696393902 -7.22328702528642 0 7.22328702528642 0 0 7.22328702528642 -7.22328702528642 0 7.22328702528642 0 0 7.22328702528642 +7.22328702528641 0 7.22328702528641 0 0 7.22328702528641 +7.22328702528641 0 7.22328702528641 0 0 7.22328702528641 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.64528459952134 0 5.64528459952134 0 0 5.64528459952134 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 @@ -188,9 +188,9 @@ SolAtVertices 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -7.66265550765843 0 7.66265550765843 0 0 7.66265550765843 +7.66265550765842 0 7.66265550765842 0 0 7.66265550765842 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -7.66265550765843 0 7.66265550765843 0 0 7.66265550765843 +7.66265550765842 0 7.66265550765842 0 0 7.66265550765842 6.67848759034891 0 6.67848759034891 0 0 6.67848759034891 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 @@ -207,15 +207,15 @@ SolAtVertices 5.61685517643149 0 5.61685517643149 0 0 5.61685517643149 11.3215991787032 0 11.3215991787032 0 0 11.3215991787032 11.3215991787032 0 11.3215991787032 0 0 11.3215991787032 -5.64971940375446 0 5.64971940375446 0 0 5.64971940375446 -5.64971940375446 0 5.64971940375446 0 0 5.64971940375446 +5.64971940375447 0 5.64971940375447 0 0 5.64971940375447 +5.64971940375447 0 5.64971940375447 0 0 5.64971940375447 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 5.81843413180583 0 5.81843413180583 0 0 5.81843413180583 5.56752500708012 0 5.56752500708012 0 0 5.56752500708012 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 -6.20162000898058 0 6.20162000898058 0 0 6.20162000898058 +6.20162000898057 0 6.20162000898057 0 0 6.20162000898057 5.6922563024583 0 5.6922563024583 0 0 5.6922563024583 5.66174406534089 0 5.66174406534089 0 0 5.66174406534089 5.53505395873405 0 5.53505395873405 0 0 5.53505395873405 From 3f99995565600f1bbd7d03c920ba5e9febb05c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 3 Dec 2018 13:13:39 +0100 Subject: [PATCH 09/31] Minor clean up --- kratos/processes/compute_nodal_gradient_process.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index 9321e5ac9285..7acd8889cbff 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -209,11 +209,11 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ///@name Member Variables ///@{ - ModelPart& mrModelPart; // The main model part - std::vector> mrOriginVariableDoubleList; // The scalar variable list to compute - std::vector mrOriginVariableComponentsList; // The scalar variable list to compute (components) - Variable >& mrGradientVariable; // The resultant gradient variable - Variable& mrAreaVariable; // The auxiliar area variable + ModelPart& mrModelPart; /// The main model part + std::vector> mrOriginVariableDoubleList; /// The scalar variable list to compute + std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) + Variable >& mrGradientVariable; /// The resultant gradient variable + Variable& mrAreaVariable; /// The auxiliar area variable ///@} ///@name Private Operators From ca7c2a7202b8a9f1541cba0fd3bb53b8569381e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 4 Dec 2018 01:24:04 +0100 Subject: [PATCH 10/31] Extend hessian process --- .../metrics_hessian_process.cpp | 460 +++++++++++------- .../metrics_hessian_process.h | 72 ++- .../custom_python/add_processes_to_python.cpp | 21 +- .../tests/cpp_tests/test_metric_process.cpp | 4 +- 4 files changed, 336 insertions(+), 221 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index 233ca7cb7836..cb1063c61813 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -20,148 +20,84 @@ namespace Kratos { -template -ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( - ModelPart& rThisModelPart, - TVarType& rVariable, - Parameters ThisParameters - ):mThisModelPart(rThisModelPart), - mVariable(rVariable) +ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( + ModelPart& rThisModelPart, + Variable& rVariable, + Parameters ThisParameters + ):mThisModelPart(rThisModelPart) { - Parameters default_parameters = Parameters(R"( - { - "minimal_size" : 0.1, - "maximal_size" : 10.0, - "enforce_current" : true, - "hessian_strategy_parameters": - { - "metric_variable" : ["DISTANCE"], - "estimate_interpolation_error" : false, - "interpolation_error" : 1.0e-6, - "mesh_dependent_constant" : 0.28125 - }, - "anisotropy_remeshing" : true, - "anisotropy_parameters": - { - "reference_variable_name" : "DISTANCE", - "hmin_over_hmax_anisotropic_ratio" : 1.0, - "boundary_layer_max_distance" : 1.0, - "interpolation" : "Linear" - } - })" ); + // We push the list of double variables + mrOriginVariableDoubleList.push_back(rVariable); + // We check the parameters + Parameters default_parameters = GetDefaultParameters(); ThisParameters.RecursivelyValidateAndAssignDefaults(default_parameters); + InitializeVariables(ThisParameters); +} - mMinSize = ThisParameters["minimal_size"].GetDouble(); - mMaxSize = ThisParameters["maximal_size"].GetDouble(); - mEnforceCurrent = ThisParameters["enforce_current"].GetBool(); +/***********************************************************************************/ +/***********************************************************************************/ - // In case we have isotropic remeshing (default values) - if (ThisParameters["anisotropy_remeshing"].GetBool() == false) { - mEstimateInterpError = default_parameters["hessian_strategy_parameters"]["estimate_interpolation_error"].GetBool(); - mInterpError = default_parameters["hessian_strategy_parameters"]["interpolation_error"].GetDouble(); - mMeshConstant = default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].GetDouble(); - mRatioReferenceVariable = default_parameters["anisotropy_parameters"]["reference_variable_name"].GetString(); - mAnisotropicRatio = default_parameters["anisotropy_parameters"]["hmin_over_hmax_anisotropic_ratio"].GetDouble(); - mBoundLayer = default_parameters["anisotropy_parameters"]["boundary_layer_max_distance"].GetDouble(); - mInterpolation = ConvertInter(default_parameters["anisotropy_parameters"]["interpolation"].GetString()); - } else { - mEstimateInterpError = ThisParameters["hessian_strategy_parameters"]["estimate_interpolation_error"].GetBool(); - mInterpError = ThisParameters["hessian_strategy_parameters"]["interpolation_error"].GetDouble(); - mMeshConstant = ThisParameters["hessian_strategy_parameters"]["mesh_dependent_constant"].GetDouble(); - mRatioReferenceVariable = ThisParameters["anisotropy_parameters"]["reference_variable_name"].GetString(); - mAnisotropicRatio = ThisParameters["anisotropy_parameters"]["hmin_over_hmax_anisotropic_ratio"].GetDouble(); - mBoundLayer = ThisParameters["anisotropy_parameters"]["boundary_layer_max_distance"].GetDouble(); - mInterpolation = ConvertInter(ThisParameters["anisotropy_parameters"]["interpolation"].GetString()); - } +ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( + ModelPart& rThisModelPart, + ComponentType& rVariable, + Parameters ThisParameters + ):mThisModelPart(rThisModelPart) +{ + // We push the components list + mrOriginVariableComponentsList.push_back(rVariable); + + // We check the parameters + Parameters default_parameters = GetDefaultParameters(); + ThisParameters.RecursivelyValidateAndAssignDefaults(default_parameters); + InitializeVariables(ThisParameters); } /***********************************************************************************/ /***********************************************************************************/ -template -void ComputeHessianSolMetricProcess::Execute() +void ComputeHessianSolMetricProcess::Execute() { - // Iterate in the nodes - NodesArrayType& nodes_array = mThisModelPart.Nodes(); - const int num_nodes = nodes_array.end() - nodes_array.begin(); - CalculateAuxiliarHessian(); // Some checks - VariableUtils().CheckVariableExists(mVariable, nodes_array); + NodesArrayType& nodes_array = mThisModelPart.Nodes(); + if (mrOriginVariableDoubleList.size() > 0) { + VariableUtils().CheckVariableExists(mrOriginVariableDoubleList[0], nodes_array); + } else { + VariableUtils().CheckVariableExists(mrOriginVariableComponentsList[0], nodes_array); + } for (auto& i_node : nodes_array) KRATOS_ERROR_IF_NOT(i_node.Has(NODAL_H)) << "NODAL_H must be computed" << std::endl; - // Ratio reference variable - KRATOS_ERROR_IF_NOT(KratosComponents>::Has(mRatioReferenceVariable)) << "Variable " << mRatioReferenceVariable << " is not a double variable" << std::endl; - const auto& reference_var = KratosComponents>::Get(mRatioReferenceVariable); - - // Tensor variable definition - const Variable& tensor_variable = KratosComponents>::Get("METRIC_TENSOR_"+std::to_string(TDim)+"D"); + const auto& it_element_begin = mThisModelPart.ElementsBegin(); + const auto& r_first_element_geometry = it_element_begin->GetGeometry(); + const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); - // Setting metric in case not defined - if (!nodes_array.begin()->Has(tensor_variable)) { - // Declaring auxiliar vector - const TensorArrayType aux_zero_vector = ZeroVector(3 * (TDim - 1)); - #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) { - auto it_node = nodes_array.begin() + i; - it_node->SetValue(tensor_variable, aux_zero_vector); - } - } - - #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) { - auto it_node = nodes_array.begin() + i; - - const Vector& hessian = it_node->GetValue(AUXILIAR_HESSIAN); - - const double nodal_h = it_node->GetValue(NODAL_H); - - double element_min_size = mMinSize; - if ((element_min_size > nodal_h) && mEnforceCurrent) element_min_size = nodal_h; - double element_max_size = mMaxSize; - if ((element_max_size > nodal_h) && mEnforceCurrent) element_max_size = nodal_h; - - // Isotropic by default - double ratio = 1.0; - - if (it_node->SolutionStepsDataHas(reference_var)) { - const double ratio_reference = it_node->FastGetSolutionStepValue(reference_var); - ratio = CalculateAnisotropicRatio(ratio_reference, mAnisotropicRatio, mBoundLayer, mInterpolation); - } - - // For postprocess pourposes - it_node->SetValue(ANISOTROPIC_RATIO, ratio); - - // We compute the metric - KRATOS_DEBUG_ERROR_IF_NOT(it_node->Has(tensor_variable)) << "METRIC_TENSOR_" + std::to_string(TDim) + "D not defined for node " << it_node->Id() << std::endl; - TensorArrayType& metric = it_node->GetValue(tensor_variable); - - const double norm_metric = norm_2(metric); - if (norm_metric > 0.0) {// NOTE: This means we combine differents metrics, at the same time means that the metric should be reseted each time - const TensorArrayType& old_metric = it_node->GetValue(tensor_variable); - const TensorArrayType& new_metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); - - metric = MetricsMathUtils::IntersectMetrics(old_metric, new_metric); - } else { - metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); - } + if (dimension == 2) { + CalculateMetric<2>(); + } else { + CalculateMetric<3>(); } } /***********************************************************************************/ /***********************************************************************************/ -template -array_1d ComputeHessianSolMetricProcess::ComputeHessianMetricTensor( +template +array_1d ComputeHessianSolMetricProcess::ComputeHessianMetricTensor( const Vector& rHessian, const double AnisotropicRatio, const double ElementMinSize, // This way we can impose as minimum as the previous size if we desire const double ElementMaxSize // This way we can impose as maximum as the previous size if we desire ) { + /// The type of array considered for the tensor + typedef typename std::conditional, array_1d>::type TensorArrayType; + + /// Matrix type definition + typedef BoundedMatrix MatrixType; + // We first transform the Hessian into a matrix const MatrixType hessian_matrix = MathUtils::VectorToSymmetricTensor(rHessian); @@ -219,96 +155,137 @@ array_1d ComputeHessianSolMetricProcess: /***********************************************************************************/ /***********************************************************************************/ -template -void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() +void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() { - // Iterate in the nodes - NodesArrayType& nodes_array = mThisModelPart.Nodes(); - const int num_nodes = static_cast(nodes_array.size()); + // Iterate in the elements + ElementsArrayType& elements_array = mThisModelPart.Elements(); + const int num_elements = static_cast(elements_array.size()); + const auto& it_element_begin = elements_array.begin(); + + // Geometry information + const auto& r_first_element_geometry = it_element_begin->GetGeometry(); + const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); + const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); // Declaring auxiliar vector - const TensorArrayType aux_zero_array = ZeroVector(3 * (TDim - 1)); + const Vector aux_zero_hessian = ZeroVector(3 * (dimension - 1)); const array_1d aux_zero_vector = ZeroVector(3); + // Iterate in the nodes + NodesArrayType& nodes_array = mThisModelPart.Nodes(); + const int num_nodes = static_cast(nodes_array.size()); + // Initialize auxiliar variables const auto& it_nodes_begin = nodes_array.begin(); #pragma omp parallel for for(int i = 0; i < num_nodes; ++i) { auto it_node = it_nodes_begin + i; it_node->SetValue(NODAL_AREA, 0.0); - it_node->SetValue(AUXILIAR_HESSIAN, aux_zero_array); + it_node->SetValue(AUXILIAR_HESSIAN, aux_zero_hessian); it_node->SetValue(AUXILIAR_GRADIENT, aux_zero_vector); } // Compute auxiliar gradient - auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mVariable, AUXILIAR_GRADIENT, NODAL_AREA); - gradient_process.Execute(); - - // Iterate in the conditions - ElementsArrayType& elements_array = mThisModelPart.Elements(); - const int num_elements = elements_array.end() - elements_array.begin(); - - #pragma omp parallel for - for(int i = 0; i < num_elements; ++i) { - - Element::GeometryType& geom = (elements_array.begin() + i)->GetGeometry(); + if (mrOriginVariableDoubleList.size() > 0) { + auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mrOriginVariableDoubleList[0], AUXILIAR_GRADIENT, NODAL_AREA); + gradient_process.Execute(); + } else { + auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mrOriginVariableComponentsList[0], AUXILIAR_GRADIENT, NODAL_AREA); + gradient_process.Execute(); + } - double volume; - if (geom.GetGeometryType() == GeometryData::KratosGeometryType::Kratos_Triangle2D3) { - BoundedMatrix DN_DX; - array_1d N; + // The integration points + const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); + const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); + const std::size_t number_of_integration_points = integration_points.size(); - GeometryUtils::CalculateGeometryData(geom, DN_DX, N, volume); + Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); + Vector N = ZeroVector(number_of_nodes); + Matrix J0 = ZeroMatrix(dimension, local_space_dimension); - BoundedMatrix values; - for(IndexType i_node = 0; i_node < 3; ++i_node) { - const array_1d& aux_grad = geom[i_node].GetValue(AUXILIAR_GRADIENT); - values(i_node, 0) = aux_grad[0]; - values(i_node, 1) = aux_grad[1]; - } + #pragma omp parallel for firstprivate(DN_DX, N, J0) + for(int i = 0; i < num_elements; ++i) { + auto it_elem = it_element_begin + i; + auto& r_geometry = it_elem->GetGeometry(); + + // The containers of the shape functions and the local gradients + const auto& rNcontainer = r_geometry.ShapeFunctionsValues(integration_method); + const auto& rDN_DeContainer = r_geometry.ShapeFunctionsLocalGradients(integration_method); + + // 2D case + if (dimension == 2) { + for ( IndexType point_number = 0; point_number < number_of_integration_points; ++point_number ) { + // Getting the shape functions + noalias(N) = row(rNcontainer, point_number); + + // Getting the jacobians and local gradients + GeometryUtils::JacobianOnInitialConfiguration(r_geometry, integration_points[point_number], J0); + double detJ0; + Matrix InvJ0; + MathUtils::InvertMatrix(J0, InvJ0, detJ0); + const Matrix& rDN_De = rDN_DeContainer[point_number]; + GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); + + const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; + + Matrix values(number_of_nodes, 2); + for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { + const array_1d& aux_grad = r_geometry[i_node].GetValue(AUXILIAR_GRADIENT); + values(i_node, 0) = aux_grad[0]; + values(i_node, 1) = aux_grad[1]; + } - const BoundedMatrix& hessian = prod(trans(DN_DX), values); - const array_1d& hessian_cond = MathUtils::StressTensorToVector, array_1d>(hessian); + const BoundedMatrix& hessian = prod(trans(DN_DX), values); + const array_1d& hessian_cond = MathUtils::StressTensorToVector, array_1d>(hessian); - for(IndexType i_node = 0; i_node < geom.size(); ++i_node) { - auto& aux_hessian = geom[i_node].GetValue(AUXILIAR_HESSIAN); - for(IndexType k = 0; k < 3; ++k) { - double& val = aux_hessian[k]; + for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { + auto& aux_hessian = r_geometry[i_node].GetValue(AUXILIAR_HESSIAN); + for(IndexType k = 0; k < 3; ++k) { + double& val = aux_hessian[k]; - #pragma omp atomic - val += N[i_node] * volume * hessian_cond[k]; + #pragma omp atomic + val += N[i_node] * gauss_point_volume * hessian_cond[k]; + } } } - } - else if (geom.GetGeometryType() == GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4) { - BoundedMatrix DN_DX; - array_1d N; - - GeometryUtils::CalculateGeometryData(geom, DN_DX, N, volume); - - BoundedMatrix values; - for(IndexType i_node = 0; i_node < 4; ++i_node) { - const array_1d& aux_grad = geom[i_node].GetValue(AUXILIAR_GRADIENT); - values(i_node, 0) = aux_grad[0]; - values(i_node, 1) = aux_grad[1]; - values(i_node, 2) = aux_grad[2]; - } + } else { // 3D case + for ( IndexType point_number = 0; point_number < number_of_integration_points; ++point_number ) { + // Getting the shape functions + noalias(N) = row(rNcontainer, point_number); + + // Getting the jacobians and local gradients + GeometryUtils::JacobianOnInitialConfiguration(r_geometry, integration_points[point_number], J0); + double detJ0; + Matrix InvJ0; + MathUtils::InvertMatrix(J0, InvJ0, detJ0); + const Matrix& rDN_De = rDN_DeContainer[point_number]; + GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); + + const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; + + Matrix values(number_of_nodes, 3); + for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { + const array_1d& aux_grad = r_geometry[i_node].GetValue(AUXILIAR_GRADIENT); + values(i_node, 0) = aux_grad[0]; + values(i_node, 1) = aux_grad[1]; + values(i_node, 2) = aux_grad[2]; + } - const BoundedMatrix hessian = prod(trans(DN_DX), values); - const array_1d& hessian_cond = MathUtils::StressTensorToVector, array_1d>(hessian); + const BoundedMatrix hessian = prod(trans(DN_DX), values); + const array_1d& hessian_cond = MathUtils::StressTensorToVector, array_1d>(hessian); - for(IndexType i_node = 0; i_node < geom.size(); ++i_node) { - auto& aux_hessian = geom[i_node].GetValue(AUXILIAR_HESSIAN); - for(IndexType k = 0; k < 6; ++k) { - double& val = aux_hessian[k]; + for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { + auto& aux_hessian = r_geometry[i_node].GetValue(AUXILIAR_HESSIAN); + for(IndexType k = 0; k < 6; ++k) { + double& val = aux_hessian[k]; - #pragma omp atomic - val += N[i_node] * volume * hessian_cond[k]; + #pragma omp atomic + val += N[i_node] * gauss_point_volume * hessian_cond[k]; + } } } } - else - KRATOS_ERROR << "WARNING: YOU CAN USE JUST 2D TRIANGLES OR 3D TETRAEDRA RIGHT NOW IN THE GEOMETRY UTILS: " << geom.size() << std::endl; } #pragma omp parallel for @@ -321,8 +298,7 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() /***********************************************************************************/ /***********************************************************************************/ -template -double ComputeHessianSolMetricProcess::CalculateAnisotropicRatio( +double ComputeHessianSolMetricProcess::CalculateAnisotropicRatio( const double Distance, const double AnisotropicRatio, const double BoundLayer, @@ -350,9 +326,135 @@ double ComputeHessianSolMetricProcess::CalculateAnisotropicRatio /***********************************************************************************/ /***********************************************************************************/ -template class ComputeHessianSolMetricProcess<2, Variable>; -template class ComputeHessianSolMetricProcess<3, Variable>; -template class ComputeHessianSolMetricProcess<2, ComponentType>; -template class ComputeHessianSolMetricProcess<3, ComponentType>; +template +void ComputeHessianSolMetricProcess::CalculateMetric() +{ + /// The type of array considered for the tensor + typedef typename std::conditional, array_1d>::type TensorArrayType; + + // Iterate in the nodes + NodesArrayType& nodes_array = mThisModelPart.Nodes(); + const int num_nodes = static_cast(nodes_array.size()); + + // Tensor variable definition + const Variable& tensor_variable = KratosComponents>::Get("METRIC_TENSOR_"+std::to_string(TDim)+"D"); + + // Setting metric in case not defined + if (!nodes_array.begin()->Has(tensor_variable)) { + // Declaring auxiliar vector + const TensorArrayType aux_zero_vector = ZeroVector(3 * (TDim - 1)); + #pragma omp parallel for + for(int i = 0; i < num_nodes; ++i) { + auto it_node = nodes_array.begin() + i; + it_node->SetValue(tensor_variable, aux_zero_vector); + } + } + + // Ratio reference variable + KRATOS_ERROR_IF_NOT(KratosComponents>::Has(mRatioReferenceVariable)) << "Variable " << mRatioReferenceVariable << " is not a double variable" << std::endl; + const auto& reference_var = KratosComponents>::Get(mRatioReferenceVariable); + + #pragma omp parallel for + for(int i = 0; i < num_nodes; ++i) { + auto it_node = nodes_array.begin() + i; + + const Vector& hessian = it_node->GetValue(AUXILIAR_HESSIAN); + + const double nodal_h = it_node->GetValue(NODAL_H); + + double element_min_size = mMinSize; + if ((element_min_size > nodal_h) && mEnforceCurrent) element_min_size = nodal_h; + double element_max_size = mMaxSize; + if ((element_max_size > nodal_h) && mEnforceCurrent) element_max_size = nodal_h; + + // Isotropic by default + double ratio = 1.0; + + if (it_node->SolutionStepsDataHas(reference_var)) { + const double ratio_reference = it_node->FastGetSolutionStepValue(reference_var); + ratio = CalculateAnisotropicRatio(ratio_reference, mAnisotropicRatio, mBoundLayer, mInterpolation); + } + + // For postprocess pourposes + it_node->SetValue(ANISOTROPIC_RATIO, ratio); + + // We compute the metric + KRATOS_DEBUG_ERROR_IF_NOT(it_node->Has(tensor_variable)) << "METRIC_TENSOR_" + std::to_string(TDim) + "D not defined for node " << it_node->Id() << std::endl; + TensorArrayType& metric = it_node->GetValue(tensor_variable); + + const double norm_metric = norm_2(metric); + if (norm_metric > 0.0) {// NOTE: This means we combine differents metrics, at the same time means that the metric should be reseted each time + const TensorArrayType& old_metric = it_node->GetValue(tensor_variable); + const TensorArrayType& new_metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); + + metric = MetricsMathUtils::IntersectMetrics(old_metric, new_metric); + } else { + metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); + } + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +Parameters ComputeHessianSolMetricProcess::GetDefaultParameters() +{ + Parameters default_parameters = Parameters(R"( + { + "minimal_size" : 0.1, + "maximal_size" : 10.0, + "enforce_current" : true, + "hessian_strategy_parameters": + { + "metric_variable" : ["DISTANCE"], + "estimate_interpolation_error" : false, + "interpolation_error" : 1.0e-6, + "mesh_dependent_constant" : 0.28125 + }, + "anisotropy_remeshing" : true, + "anisotropy_parameters": + { + "reference_variable_name" : "DISTANCE", + "hmin_over_hmax_anisotropic_ratio" : 1.0, + "boundary_layer_max_distance" : 1.0, + "interpolation" : "Linear" + } + })" ); + + return default_parameters; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +void ComputeHessianSolMetricProcess::InitializeVariables(Parameters ThisParameters) +{ + // Get default variables + Parameters default_parameters = GetDefaultParameters(); + + // Set variables + mMinSize = ThisParameters["minimal_size"].GetDouble(); + mMaxSize = ThisParameters["maximal_size"].GetDouble(); + mEnforceCurrent = ThisParameters["enforce_current"].GetBool(); + + // In case we have isotropic remeshing (default values) + if (ThisParameters["anisotropy_remeshing"].GetBool() == false) { + mEstimateInterpError = default_parameters["hessian_strategy_parameters"]["estimate_interpolation_error"].GetBool(); + mInterpError = default_parameters["hessian_strategy_parameters"]["interpolation_error"].GetDouble(); + mMeshConstant = default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].GetDouble(); + mRatioReferenceVariable = default_parameters["anisotropy_parameters"]["reference_variable_name"].GetString(); + mAnisotropicRatio = default_parameters["anisotropy_parameters"]["hmin_over_hmax_anisotropic_ratio"].GetDouble(); + mBoundLayer = default_parameters["anisotropy_parameters"]["boundary_layer_max_distance"].GetDouble(); + mInterpolation = ConvertInter(default_parameters["anisotropy_parameters"]["interpolation"].GetString()); + } else { + mEstimateInterpError = ThisParameters["hessian_strategy_parameters"]["estimate_interpolation_error"].GetBool(); + mInterpError = ThisParameters["hessian_strategy_parameters"]["interpolation_error"].GetDouble(); + mMeshConstant = ThisParameters["hessian_strategy_parameters"]["mesh_dependent_constant"].GetDouble(); + mRatioReferenceVariable = ThisParameters["anisotropy_parameters"]["reference_variable_name"].GetString(); + mAnisotropicRatio = ThisParameters["anisotropy_parameters"]["hmin_over_hmax_anisotropic_ratio"].GetDouble(); + mBoundLayer = ThisParameters["anisotropy_parameters"]["boundary_layer_max_distance"].GetDouble(); + mInterpolation = ConvertInter(ThisParameters["anisotropy_parameters"]["interpolation"].GetString()); + } +} };// namespace Kratos. diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h index 019a2b6fd1b8..7e43c8d5d8d0 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h @@ -53,7 +53,6 @@ namespace Kratos * @brief This class is can be used to compute the metrics of the model part with an Hessian approach * @author Vicente Mataix Ferrandiz */ -template class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess : public Process { @@ -73,12 +72,6 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess /// The index type definition typedef std::size_t IndexType; - /// The type of array considered for the tensor - typedef typename std::conditional, array_1d>::type TensorArrayType; - - /// Matrix type definition - typedef BoundedMatrix MatrixType; - /// Pointer definition of ComputeHessianSolMetricProcess KRATOS_CLASS_POINTER_DEFINITION(ComputeHessianSolMetricProcess); @@ -98,15 +91,26 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess // Constructor /** - * @brief This is the default constructor + * @brief This is the default constructor (double) * @param rThisModelPart The model part to be computed * @param rVariable The variable to compute * @param ThisParameters The input parameters */ + ComputeHessianSolMetricProcess( + ModelPart& rThisModelPart, + Variable& rVariable, + Parameters ThisParameters = Parameters(R"({})") + ); + /** + * @brief This is the default constructor (component) + * @param rThisModelPart The model part to be computed + * @param rVariable The variable to compute + * @param ThisParameters The input parameters + */ ComputeHessianSolMetricProcess( ModelPart& rThisModelPart, - TVarType& rVariable, + ComponentType& rVariable, Parameters ThisParameters = Parameters(R"({})") ); @@ -208,18 +212,21 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess ///@name Private member Variables ///@{ - ModelPart& mThisModelPart; /// The model part to compute - TVarType& mVariable; /// The variable to calculate the hessian - std::string mRatioReferenceVariable = "DISTANCE"; /// Variable used to compute the anisotropic ratio - double mMinSize; /// The minimal size of the elements - double mMaxSize; /// The maximal size of the elements - bool mEnforceCurrent; /// With this we choose if we inforce the current nodal size (NODAL_H) - bool mEstimateInterpError; /// If the error of interpolation will be estimated - double mInterpError; /// The error of interpolation allowed - double mMeshConstant; /// The mesh constant to remesh (depends of the element type) - double mAnisotropicRatio; /// The minimal anisotropic ratio (0 < ratio < 1) - double mBoundLayer; /// The boundary layer limit distance - Interpolation mInterpolation; /// The interpolation type + ModelPart& mThisModelPart; /// The model part to compute + std::vector> mrOriginVariableDoubleList; /// The scalar variable list to compute + std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) + + // TODO: Replace for Parameters + std::string mRatioReferenceVariable = "DISTANCE"; /// Variable used to compute the anisotropic ratio + double mMinSize; /// The minimal size of the elements + double mMaxSize; /// The maximal size of the elements + bool mEnforceCurrent; /// With this we choose if we inforce the current nodal size (NODAL_H) + bool mEstimateInterpError; /// If the error of interpolation will be estimated + double mInterpError; /// The error of interpolation allowed + double mMeshConstant; /// The mesh constant to remesh (depends of the element type) + double mAnisotropicRatio; /// The minimal anisotropic ratio (0 < ratio < 1) + double mBoundLayer; /// The boundary layer limit distance + Interpolation mInterpolation; /// The interpolation type ///@} ///@name Private Operators @@ -237,6 +244,7 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess * @param ElementMinSize The min size of element * @param ElementMaxSize The maximal size of the elements */ + template array_1d ComputeHessianMetricTensor( const Vector& rHessian, const double AnisotropicRatio, @@ -280,6 +288,22 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess const Interpolation rInterpolation ); + /** + * @brief This method is the responsible to compute the metric of the problem + */ + template + void CalculateMetric(); + + /** + * @brief This method provides the defaults parameters to avoid conflicts between the different constructors + */ + Parameters GetDefaultParameters(); + + /** + * @brief This method provides the defaults parameters to avoid conflicts between the different constructors + */ + void InitializeVariables(Parameters ThisParameters); + ///@} ///@name Private Access ///@{ @@ -316,14 +340,12 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess ///@{ /// input stream function -template inline std::istream& operator >> (std::istream& rIStream, - ComputeHessianSolMetricProcess& rThis); + ComputeHessianSolMetricProcess& rThis); /// output stream function -template inline std::ostream& operator << (std::ostream& rOStream, - const ComputeHessianSolMetricProcess& rThis) + const ComputeHessianSolMetricProcess& rThis) { rThis.PrintInfo(rOStream); rOStream << std::endl; diff --git a/applications/MeshingApplication/custom_python/add_processes_to_python.cpp b/applications/MeshingApplication/custom_python/add_processes_to_python.cpp index d17d5c2dc593..2f82a9f4b33f 100644 --- a/applications/MeshingApplication/custom_python/add_processes_to_python.cpp +++ b/applications/MeshingApplication/custom_python/add_processes_to_python.cpp @@ -89,27 +89,18 @@ void AddProcessesToPython(pybind11::module& m) .def(py::init>, Parameters>()) ; - // HESSIAN DOUBLE - py::class_>, ComputeHessianSolMetricProcess<2, Variable>::Pointer, Process>(m, "ComputeHessianSolMetricProcess2D") + // HESSIAN PROCESS + py::class_(m, "ComputeHessianSolMetricProcess") .def(py::init&>()) .def(py::init&, Parameters>()) - ; - - py::class_>, ComputeHessianSolMetricProcess<3, Variable>::Pointer, Process>(m, "ComputeHessianSolMetricProcess3D") - .def(py::init&>()) - .def(py::init&, Parameters>()) - ; - - // HESSIAN ARRAY 1D - py::class_, ComputeHessianSolMetricProcess<2, ComponentType>::Pointer, Process>(m, "ComputeHessianSolMetricProcessComp2D") .def(py::init()) .def(py::init()) ; - py::class_, ComputeHessianSolMetricProcess<3, ComponentType>::Pointer, Process>(m, "ComputeHessianSolMetricProcessComp3D") - .def(py::init()) - .def(py::init()) - ; + m.attr("ComputeHessianSolMetricProcess2D") = m.attr("ComputeHessianSolMetricProcess"); + m.attr("ComputeHessianSolMetricProcess3D") = m.attr("ComputeHessianSolMetricProcess"); + m.attr("ComputeHessianSolMetricProcessComp2D") = m.attr("ComputeHessianSolMetricProcess"); + m.attr("ComputeHessianSolMetricProcessComp3D") = m.attr("ComputeHessianSolMetricProcess"); // ERROR py::class_, MetricErrorProcess<2>::Pointer, Process>(m, "MetricErrorProcess2D") diff --git a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp index baf4347fd371..fd42acf729b9 100644 --- a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp +++ b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp @@ -363,7 +363,7 @@ namespace Kratos } // Compute metric - ComputeHessianSolMetricProcess<2, Variable> hessian_process = ComputeHessianSolMetricProcess<2, Variable>(this_model_part, DISTANCE); + auto hessian_process = ComputeHessianSolMetricProcess(this_model_part, DISTANCE); hessian_process.Execute(); // // DEBUG @@ -408,7 +408,7 @@ namespace Kratos } // Compute metric - ComputeHessianSolMetricProcess<3, Variable> hessian_process = ComputeHessianSolMetricProcess<3, Variable>(this_model_part, DISTANCE); + auto hessian_process = ComputeHessianSolMetricProcess(this_model_part, DISTANCE); hessian_process.Execute(); // // DEBUG From b83f5dfa25536ebf2bb33d8888057f72a561a653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 4 Dec 2018 01:28:18 +0100 Subject: [PATCH 11/31] Update tests --- .../beam2D_line_load_test_parameters.json | 10 -- .../beam2D_line_load_test_result.sol | 42 +++--- .../beam2D_test_parameters.json | 10 -- .../beam2D_test_result.sol | 138 +++++++++--------- 4 files changed, 90 insertions(+), 110 deletions(-) diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_parameters.json b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_parameters.json index e2a763f92225..2458860d740d 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_parameters.json +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_parameters.json @@ -87,16 +87,6 @@ }, "point_data_configuration" : [] }, - "restart_options" : { - "SaveRestart" : false, - "RestartFrequency" : 0, - "LoadRestart" : false, - "Restart_Step" : 0 - }, - "constraints_data" : { - "incremental_load" : false, - "incremental_displacement" : false - }, "recursive_remeshing_process" :[ { "python_module" : "mmg_process", diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol index daad472a1f39..2f3b6542c614 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol @@ -21,33 +21,33 @@ SolAtVertices 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 2239.55190816785 0 2239.55190816785 + 2203.81475518259 0 2203.81475518259 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 1939.56114223364 0 1939.56114223364 - 2438.9855715349 0 2438.9855715349 - 1697.88406875709 0 1697.88406875709 + 1937.36282929371 0 1937.36282929371 + 2390.02732073372 0 2390.02732073372 + 1694.57412015215 0 1694.57412015215 1596.1682065273 0 1596.1682065273 - 3274.24585263818 0 3274.24585263818 - 2554.56707778872 0 2554.56707778872 - 2844.51057414303 0 2844.51057414303 - 3549.14057974895 0 3549.14057974895 - 1965.17855255292 0 1965.17855255292 - 4249.672620598 0 4249.672620598 - 3548.28899887462 0 3548.28899887462 - 2900.91505366977 0 2900.91505366977 - 4053.92761436963 0 4053.92761436963 - 4522.84459146374 0 4522.84459146374 - 5332.77651426404 0 5332.77651426404 - 3957.30289321615 0 3957.30289321615 - 4875.3926507737 0 4875.3926507737 - 5367.03504165936 0 5367.03504165936 - 6025.20946187374 0 6025.20946187374 + 3211.5413239035 0 3211.5413239035 + 2544.19608405931 0 2544.19608405931 + 2832.82832148862 0 2832.82832148862 + 3497.44690606323 0 3497.44690606323 + 1987.67504725415 0 1987.67504725415 + 4176.49189592067 0 4176.49189592067 + 3522.07756928224 0 3522.07756928224 + 2941.860926844 0 2941.860926844 + 4052.02609761579 0 4052.02609761579 + 4430.41381078589 0 4430.41381078589 + 5180.34409800205 0 5180.34409800205 + 4016.81056973862 0 4016.81056973862 + 4840.25254877213 0 4840.25254877213 + 5345.96584549973 0 5345.96584549973 + 6017.97906558297 0 6017.97906558297 6384.67282610918 0 6384.67282610918 - 5178.09614105904 0 5178.09614105904 - 6323.08024706008 0 6323.08024706008 + 5260.70110314265 0 5260.70110314265 + 6289.51969324357 0 6289.51969324357 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_parameters.json b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_parameters.json index 187c3394ffd0..430c1f67a432 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_parameters.json +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_parameters.json @@ -86,16 +86,6 @@ }, "point_data_configuration" : [] }, - "restart_options" : { - "SaveRestart" : false, - "RestartFrequency" : 0, - "LoadRestart" : false, - "Restart_Step" : 0 - }, - "constraints_data" : { - "incremental_load" : false, - "incremental_displacement" : false - }, "recursive_remeshing_process" :[ { "python_module" : "mmg_process", diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol index fd088704f3d0..ace1ea16c17c 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol @@ -7,77 +7,77 @@ Dimension SolAtVertices 205 1 3 - 35.9140018842354 0 35.9140018842354 - 37.4397284135075 0 37.4397284135075 - 26.2583588730124 0 26.2583588730124 - 33.4131182686942 0 33.4131182686942 + 35.9143759191543 0 35.9143759191543 + 37.4400098128027 0 37.4400098128027 + 26.2586649981814 0 26.2586649981814 + 33.413444384322 0 33.413444384322 30.2668616137121 0 30.2668616137121 - 39.5033684796239 0 39.5033684796239 - 21.7521188387394 0 21.7521188387394 + 39.5038146087083 0 39.5038146087083 + 21.7522982463049 0 21.7522982463049 30.2668616137121 0 30.2668616137121 - 34.7907840772552 0 34.7907840772552 - 37.2337481488278 0 37.2337481488278 - 36.0308766576983 0 36.0308766576983 - 25.0193355233973 0 25.0193355233973 - 33.2506017597463 0 33.2506017597463 - 32.7389817288463 0 32.7389817288463 - 32.3638339058948 0 32.3638339058948 - 34.6444870591263 0 34.6444870591263 - 30.4526775711213 0 30.4526775711213 - 35.7726381150214 0 35.7726381150214 - 34.5194786258534 0 34.5194786258534 - 38.5829285575872 0 38.5829285575872 - 31.8203037467802 0 31.8203037467802 - 28.8340591256521 0 28.8340591256521 - 32.831735144249 0 32.831735144249 - 35.2781955379513 0 35.2781955379513 - 27.5587311214965 0 27.5587311214965 - 31.3715104402689 0 31.3715104402689 - 29.7158865764926 0 29.7158865764926 - 27.2119874541355 0 27.2119874541355 - 32.313977702091 0 32.313977702091 - 27.0387600275092 0 27.0387600275092 - 28.308992404692 0 28.308992404692 - 27.8822524088032 0 27.8822524088032 - 29.6289378246923 0 29.6289378246923 - 26.3347055267636 0 26.3347055267636 - 25.0899015839709 0 25.0899015839709 - 27.7206399435361 0 27.7206399435361 - 25.9957424765933 0 25.9957424765933 - 25.5275119357513 0 25.5275119357513 - 24.3539695392516 0 24.3539695392516 - 23.5129099906319 0 23.5129099906319 - 25.4952181353372 0 25.4952181353372 - 24.6384741984057 0 24.6384741984057 - 24.2550590469 0 24.2550590469 - 23.2553571583674 0 23.2553571583674 - 23.9444429458136 0 23.9444429458136 - 22.7010033263282 0 22.7010033263282 - 22.8715692339873 0 22.8715692339873 - 22.4440239475518 0 22.4440239475518 - 21.818145354373 0 21.818145354373 - 22.2650362132523 0 22.2650362132523 - 21.3913943803489 0 21.3913943803489 - 21.3294780605533 0 21.3294780605533 - 20.6985502651528 0 20.6985502651528 - 19.9874155232717 0 19.9874155232717 - 20.695033636421 0 20.695033636421 - 20.1132218224946 0 20.1132218224946 - 19.3943965334395 0 19.3943965334395 - 19.3516405294764 0 19.3516405294764 - 19.1093155299435 0 19.1093155299435 - 19.2942910399988 0 19.2942910399988 - 18.7634198651674 0 18.7634198651674 - 19.4357707933614 0 19.4357707933614 - 17.8636087889326 0 17.8636087889326 - 17.9165850207371 0 17.9165850207371 - 17.9639968324299 0 17.9639968324299 - 17.4106302371692 0 17.4106302371692 - 17.8048364572601 0 17.8048364572601 - 16.6544076033481 0 16.6544076033481 - 16.6804800592124 0 16.6804800592124 - 16.9081523865639 0 16.9081523865639 - 16.5475094343016 0 16.5475094343016 + 34.7912241547683 0 34.7912241547683 + 37.2336442240363 0 37.2336442240363 + 36.031221403295 0 36.031221403295 + 25.0190046788027 0 25.0190046788027 + 33.2502322505889 0 33.2502322505889 + 32.7387665731833 0 32.7387665731833 + 32.3642617399157 0 32.3642617399157 + 34.6441261821053 0 34.6441261821053 + 30.4527623066976 0 30.4527623066976 + 35.7721819262914 0 35.7721819262914 + 34.5191770987428 0 34.5191770987428 + 38.5824193988693 0 38.5824193988693 + 31.8200258225015 0 31.8200258225015 + 28.8344978294523 0 28.8344978294523 + 32.831409905737 0 32.831409905737 + 35.2775147501514 0 35.2775147501514 + 27.5595729207846 0 27.5595729207846 + 31.371208273239 0 31.371208273239 + 29.7161133275109 0 29.7161133275109 + 27.2124194366223 0 27.2124194366223 + 32.3131692241774 0 32.3131692241774 + 27.0396775965852 0 27.0396775965852 + 28.3085946349283 0 28.3085946349283 + 27.8824779541497 0 27.8824779541497 + 29.6289246620822 0 29.6289246620822 + 26.3351778770106 0 26.3351778770106 + 25.0894963199882 0 25.0894963199882 + 27.7206677923888 0 27.7206677923888 + 25.995321563843 0 25.995321563843 + 25.5276047877789 0 25.5276047877789 + 24.354462501175 0 24.354462501175 + 23.5124637362395 0 23.5124637362395 + 25.4954183637171 0 25.4954183637171 + 24.6380724373713 0 24.6380724373713 + 24.2551913147001 0 24.2551913147001 + 23.2552504847589 0 23.2552504847589 + 23.9446765343999 0 23.9446765343999 + 22.7005417609784 0 22.7005417609784 + 22.8711404352926 0 22.8711404352926 + 22.4440885928833 0 22.4440885928833 + 21.8179849340975 0 21.8179849340975 + 22.2653333934246 0 22.2653333934246 + 21.3909586451322 0 21.3909586451322 + 21.3290644564547 0 21.3290644564547 + 20.6985501936326 0 20.6985501936326 + 19.9871802434071 0 19.9871802434071 + 20.6942778113269 0 20.6942778113269 + 20.1128494721444 0 20.1128494721444 + 19.3939342093955 0 19.3939342093955 + 19.3516002844571 0 19.3516002844571 + 19.1092008484915 0 19.1092008484915 + 19.294741544997 0 19.294741544997 + 18.7630484521628 0 18.7630484521628 + 19.4354254403624 0 19.4354254403624 + 17.8635483593958 0 17.8635483593958 + 17.9169890265432 0 17.9169890265432 + 17.9633064984183 0 17.9633064984183 + 17.4103345211041 0 17.4103345211041 + 17.8054353019448 0 17.8054353019448 + 16.6544544211057 0 16.6544544211057 + 16.6806735919392 0 16.6806735919392 + 16.9075081806209 0 16.9075081806209 + 16.5472820847962 0 16.5472820847962 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 From 5d738fb6c1b108405b73b66632bf535ed485b010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Wed, 5 Dec 2018 00:20:21 +0100 Subject: [PATCH 12/31] Some fixes --- .../metrics_hessian_process.cpp | 17 ++++++++------ .../compute_nodal_gradient_process.cpp | 22 +++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index cb1063c61813..7dd36f1c7339 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -179,8 +179,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() // Initialize auxiliar variables const auto& it_nodes_begin = nodes_array.begin(); #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) { - auto it_node = it_nodes_begin + i; + for(int i_node = 0; i_node < num_nodes; ++i_node) { + auto it_node = it_nodes_begin + i_node; it_node->SetValue(NODAL_AREA, 0.0); it_node->SetValue(AUXILIAR_HESSIAN, aux_zero_hessian); it_node->SetValue(AUXILIAR_GRADIENT, aux_zero_vector); @@ -205,8 +205,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() Matrix J0 = ZeroMatrix(dimension, local_space_dimension); #pragma omp parallel for firstprivate(DN_DX, N, J0) - for(int i = 0; i < num_elements; ++i) { - auto it_elem = it_element_begin + i; + for(int i_elem = 0; i_elem < num_elements; ++i_elem) { + auto it_elem = it_element_begin + i_elem; auto& r_geometry = it_elem->GetGeometry(); // The containers of the shape functions and the local gradients @@ -289,9 +289,12 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() } #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) { - auto it_node = nodes_array.begin() + i; - it_node->GetValue(AUXILIAR_HESSIAN) /= it_node->GetValue(NODAL_AREA); + for(int i_node = 0; i_node < num_nodes; ++i_node) { + auto it_node = nodes_array.begin() + i_node; + const double nodal_area = it_node->GetValue(NODAL_AREA); + if (nodal_area > std::numeric_limits::epsilon()) { + it_node->GetValue(AUXILIAR_HESSIAN) /= nodal_area; + } } } diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index b9fc1922546e..1dc239975279 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -47,17 +47,17 @@ void ComputeNodalGradientProcess::Execute() Matrix J0 = ZeroMatrix(dimension, local_space_dimension); #pragma omp parallel for firstprivate(DN_DX, N, J0) - for(int i=0; i(mrModelPart.Elements().size()); ++i) { - auto it_elem = it_element_begin + i; + for(int i_elem=0; i_elem(mrModelPart.Elements().size()); ++i_elem) { + auto it_elem = it_element_begin + i_elem; auto& r_geometry = it_elem->GetGeometry(); Vector values(number_of_nodes); if (mrOriginVariableDoubleList.size() > 0) { - for(std::size_t i=0; i::Execute() const Vector grad = prod(trans(DN_DX), values); const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; - for(std::size_t i=0; i Date: Sun, 9 Dec 2018 19:26:26 +0100 Subject: [PATCH 13/31] Avoid conflict --- .../compute_nodal_gradient_process.cpp | 532 +++++++++++++++--- 1 file changed, 439 insertions(+), 93 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 1dc239975279..6ab097fa28f6 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -13,6 +13,9 @@ // /* System includes */ +#include +#include +#include /* External includes */ @@ -23,75 +26,42 @@ namespace Kratos { -template -void ComputeNodalGradientProcess::Execute() +template< int TDim, class TVarType, HistoricalValues THist> +void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; // Set to zero ClearGradient(); - const auto& it_element_begin = mrModelPart.ElementsBegin(); - const auto& r_first_element_geometry = it_element_begin->GetGeometry(); - const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); - const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); - const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); - - // The integration points - const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); - const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); - const std::size_t number_of_integration_points = integration_points.size(); - - Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); - Vector N = ZeroVector(number_of_nodes); - Matrix J0 = ZeroMatrix(dimension, local_space_dimension); - - #pragma omp parallel for firstprivate(DN_DX, N, J0) - for(int i_elem=0; i_elem(mrModelPart.Elements().size()); ++i_elem) { - auto it_elem = it_element_begin + i_elem; - auto& r_geometry = it_elem->GetGeometry(); - - Vector values(number_of_nodes); - if (mrOriginVariableDoubleList.size() > 0) { - for(std::size_t i_node=0; i_node DN_DX; + array_1d N; + double Volume; + + #pragma omp parallel for private(DN_DX, N, Volume) + for(int i=0; i(mrModelPart.Elements().size()); ++i) { + auto it_elem = mrModelPart.ElementsBegin()+i; + Element::GeometryType& geom = it_elem->GetGeometry(); + GeometryUtils::CalculateGeometryData(geom, DN_DX, N, Volume); - // The containers of the shape functions and the local gradients - const auto& rNcontainer = r_geometry.ShapeFunctionsValues(integration_method); - const auto& rDN_DeContainer = r_geometry.ShapeFunctionsLocalGradients(integration_method); + array_1d values; + for(std::size_t i=0; i::InvertMatrix(J0, InvJ0, detJ0); - const Matrix& rDN_De = rDN_DeContainer[point_number]; - GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); - - const Vector grad = prod(trans(DN_DX), values); - const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; - - for(std::size_t i_node=0; i_node grad = prod(trans(DN_DX), values); + + for(std::size_t i=0; i::Execute() /***********************************************************************************/ template<> -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess<2, Variable, Historical>::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - // We push the list of double variables - mrOriginVariableDoubleList.push_back(rOriginVariable); - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -127,21 +98,49 @@ ComputeNodalGradientProcess -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess<2, Variable, NonHistorical>::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - // We push the list of double variables - mrOriginVariableDoubleList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } + + KRATOS_CATCH("") +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template<> +ComputeNodalGradientProcess<3, Variable, Historical>::ComputeNodalGradientProcess( + ModelPart& rModelPart, + Variable& rOriginVariable, + Variable >& rGradientVariable, + Variable& rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) +{ + KRATOS_TRY VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); + // In case the area variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -150,21 +149,49 @@ ComputeNodalGradientProcess -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess<3, Variable, NonHistorical>::ComputeNodalGradientProcess( ModelPart& rModelPart, - ComponentType& rOriginVariable, + Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - // We push the components list - mrOriginVariableComponentsList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } + + KRATOS_CATCH("") +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template<> +ComputeNodalGradientProcess<2, component_type, Historical>::ComputeNodalGradientProcess( + ModelPart& rModelPart, + component_type& rOriginVariable, + Variable >& rGradientVariable, + Variable& rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) +{ + KRATOS_TRY VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -173,21 +200,49 @@ ComputeNodalGradientProcess -ComputeNodalGradientProcess::ComputeNodalGradientProcess( +ComputeNodalGradientProcess<2, component_type, NonHistorical>::ComputeNodalGradientProcess( ModelPart& rModelPart, - ComponentType& rOriginVariable, + component_type& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - // We push the components list - mrOriginVariableComponentsList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } + + KRATOS_CATCH("") +} + +/***********************************************************************************/ +/***********************************************************************************/ +template<> +ComputeNodalGradientProcess<3, component_type, Historical>::ComputeNodalGradientProcess( + ModelPart& rModelPart, + component_type& rOriginVariable, + Variable >& rGradientVariable, + Variable& rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) +{ + KRATOS_TRY + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); + // In case the area variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -196,7 +251,73 @@ ComputeNodalGradientProcess -void ComputeNodalGradientProcess::ClearGradient() +ComputeNodalGradientProcess<3, component_type, NonHistorical>::ComputeNodalGradientProcess( + ModelPart& rModelPart, + component_type& rOriginVariable, + Variable >& rGradientVariable, + Variable& rAreaVariable) + :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) +{ + KRATOS_TRY + + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } + + KRATOS_CATCH("") +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template<> +void ComputeNodalGradientProcess<2, Variable, Historical>::ClearGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template<> +void ComputeNodalGradientProcess<3, Variable, Historical>::ClearGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); + } +} + +template<> +void ComputeNodalGradientProcess<2, component_type, Historical>::ClearGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template<> +void ComputeNodalGradientProcess<3, component_type, Historical>::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -210,15 +331,15 @@ void ComputeNodalGradientProcess -void ComputeNodalGradientProcess::ClearGradient() +void ComputeNodalGradientProcess<2, Variable, NonHistorical>::ClearGradient() { - const array_1d aux_zero_vector = ZeroVector(3); + const array_1d AuxZeroVector = ZeroVector(3); #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, aux_zero_vector); + it_node->SetValue(mrGradientVariable, AuxZeroVector); } } @@ -226,7 +347,55 @@ void ComputeNodalGradientProcess -double& ComputeNodalGradientProcess::GetGradient( +void ComputeNodalGradientProcess<3, Variable, NonHistorical>::ClearGradient() +{ + const array_1d AuxZeroVector = ZeroVector(3); + + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->SetValue(mrGradientVariable, AuxZeroVector); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<2, component_type, NonHistorical>::ClearGradient() +{ + const array_1d AuxZeroVector = ZeroVector(3); + + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->SetValue(mrGradientVariable, AuxZeroVector); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<3, component_type, NonHistorical>::ClearGradient() +{ + const array_1d AuxZeroVector = ZeroVector(3); + + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->SetValue(mrAreaVariable, 0.0); + it_node->SetValue(mrGradientVariable, AuxZeroVector); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<2, Variable, Historical>::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -241,7 +410,97 @@ double& ComputeNodalGradientProcess -double& ComputeNodalGradientProcess::GetGradient( +double& ComputeNodalGradientProcess<3, Variable, Historical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<2, component_type, Historical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<3, component_type, Historical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<2, Variable, NonHistorical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<3, Variable, NonHistorical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<2, component_type, NonHistorical>::GetGradient( + Element::GeometryType& rThisGeometry, + unsigned int i, + unsigned int k + ) +{ + double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; + + return val; +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +double& ComputeNodalGradientProcess<3, component_type, NonHistorical>::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -256,7 +515,20 @@ double& ComputeNodalGradientProcess -void ComputeNodalGradientProcess::PonderateGradient() +void ComputeNodalGradientProcess<2, Variable, Historical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node = mrModelPart.NodesBegin()+i; + it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<3, Variable, Historical>::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -269,19 +541,93 @@ void ComputeNodalGradientProcess -void ComputeNodalGradientProcess::PonderateGradient() +void ComputeNodalGradientProcess<2, component_type, Historical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) + { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<3, component_type, Historical>::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<2, Variable, NonHistorical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) + { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<3, Variable, NonHistorical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); } } + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<2, component_type, NonHistorical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + +/***********************************************************************************/ +/***********************************************************************************/ + +template <> +void ComputeNodalGradientProcess<3, component_type, NonHistorical>::PonderateGradient() +{ + #pragma omp parallel for + for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { + auto it_node=mrModelPart.NodesBegin()+i; + it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); + } +} + /***********************************************************************************/ /***********************************************************************************/ -template class ComputeNodalGradientProcess; -template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess<2, Variable, Historical>; +template class ComputeNodalGradientProcess<2, Variable, NonHistorical>; +template class ComputeNodalGradientProcess<3, Variable, Historical>; +template class ComputeNodalGradientProcess<3, Variable, NonHistorical>; +template class ComputeNodalGradientProcess<2, component_type, Historical>; +template class ComputeNodalGradientProcess<2, component_type, NonHistorical>; +template class ComputeNodalGradientProcess<3, component_type, Historical>; +template class ComputeNodalGradientProcess<3, component_type, NonHistorical>; } /* namespace Kratos.*/ From 3535733b52698847c5116fdaf319615287829c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 9 Dec 2018 19:27:14 +0100 Subject: [PATCH 14/31] Revert conflict --- .../compute_nodal_gradient_process.cpp | 532 +++--------------- 1 file changed, 93 insertions(+), 439 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 6ab097fa28f6..1dc239975279 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -13,9 +13,6 @@ // /* System includes */ -#include -#include -#include /* External includes */ @@ -26,42 +23,75 @@ namespace Kratos { -template< int TDim, class TVarType, HistoricalValues THist> -void ComputeNodalGradientProcess::Execute() +template +void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; // Set to zero ClearGradient(); - BoundedMatrix DN_DX; - array_1d N; - double Volume; - - #pragma omp parallel for private(DN_DX, N, Volume) - for(int i=0; i(mrModelPart.Elements().size()); ++i) { - auto it_elem = mrModelPart.ElementsBegin()+i; - Element::GeometryType& geom = it_elem->GetGeometry(); - GeometryUtils::CalculateGeometryData(geom, DN_DX, N, Volume); - - array_1d values; - for(std::size_t i=0; iGetGeometry(); + const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); + const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); + + // The integration points + const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); + const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); + const std::size_t number_of_integration_points = integration_points.size(); + + Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); + Vector N = ZeroVector(number_of_nodes); + Matrix J0 = ZeroMatrix(dimension, local_space_dimension); + + #pragma omp parallel for firstprivate(DN_DX, N, J0) + for(int i_elem=0; i_elem(mrModelPart.Elements().size()); ++i_elem) { + auto it_elem = it_element_begin + i_elem; + auto& r_geometry = it_elem->GetGeometry(); + + Vector values(number_of_nodes); + if (mrOriginVariableDoubleList.size() > 0) { + for(std::size_t i_node=0; i_node grad = prod(trans(DN_DX), values); + // The containers of the shape functions and the local gradients + const auto& rNcontainer = r_geometry.ShapeFunctionsValues(integration_method); + const auto& rDN_DeContainer = r_geometry.ShapeFunctionsLocalGradients(integration_method); - for(std::size_t i=0; i::InvertMatrix(J0, InvJ0, detJ0); + const Matrix& rDN_De = rDN_DeContainer[point_number]; + GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); + + const Vector grad = prod(trans(DN_DX), values); + const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; + + for(std::size_t i_node=0; i_node::Execute() /***********************************************************************************/ template<> -ComputeNodalGradientProcess<2, Variable, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY - - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - // In case the area variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<2, Variable, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - // In case the area or gradient variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rGradientVariable )) { - const array_1d zero_vector = ZeroVector(3); - VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); - } - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<3, Variable, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY + // We push the list of double variables + mrOriginVariableDoubleList.push_back(rOriginVariable); VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - // In case the area variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; KRATOS_CATCH("") } @@ -149,49 +127,21 @@ ComputeNodalGradientProcess<3, Variable, Historical>::ComputeNodalGradie /***********************************************************************************/ template<> -ComputeNodalGradientProcess<3, Variable, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, Variable& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - // In case the area or gradient variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rGradientVariable )) { - const array_1d zero_vector = ZeroVector(3); - VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); - } - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<2, component_type, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - component_type& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY + // We push the list of double variables + mrOriginVariableDoubleList.push_back(rOriginVariable); VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - // In case the area variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; KRATOS_CATCH("") } @@ -200,49 +150,21 @@ ComputeNodalGradientProcess<2, component_type, Historical>::ComputeNodalGradient /***********************************************************************************/ template<> -ComputeNodalGradientProcess<2, component_type, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, - component_type& rOriginVariable, + ComponentType& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - // In case the area or gradient variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rGradientVariable )) { - const array_1d zero_vector = ZeroVector(3); - VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); - } - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } - - KRATOS_CATCH("") -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -ComputeNodalGradientProcess<3, component_type, Historical>::ComputeNodalGradientProcess( - ModelPart& rModelPart, - component_type& rOriginVariable, - Variable >& rGradientVariable, - Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) -{ - KRATOS_TRY + // We push the components list + mrOriginVariableComponentsList.push_back(rOriginVariable); VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); - // In case the area variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; KRATOS_CATCH("") } @@ -251,25 +173,21 @@ ComputeNodalGradientProcess<3, component_type, Historical>::ComputeNodalGradient /***********************************************************************************/ template<> -ComputeNodalGradientProcess<3, component_type, NonHistorical>::ComputeNodalGradientProcess( +ComputeNodalGradientProcess::ComputeNodalGradientProcess( ModelPart& rModelPart, - component_type& rOriginVariable, + ComponentType& rOriginVariable, Variable >& rGradientVariable, Variable& rAreaVariable) - :mrModelPart(rModelPart), mrOriginVariable(rOriginVariable), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) + :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY + // We push the components list + mrOriginVariableComponentsList.push_back(rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); - // In case the area or gradient variable is not initialized we initialize it - auto& r_nodes = rModelPart.Nodes(); - if (!r_nodes.begin()->Has( rGradientVariable )) { - const array_1d zero_vector = ZeroVector(3); - VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); - } - if (!r_nodes.begin()->Has( rAreaVariable )) { - VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); - } + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; + KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; KRATOS_CATCH("") } @@ -278,46 +196,7 @@ ComputeNodalGradientProcess<3, component_type, NonHistorical>::ComputeNodalGradi /***********************************************************************************/ template<> -void ComputeNodalGradientProcess<2, Variable, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -void ComputeNodalGradientProcess<3, Variable, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -template<> -void ComputeNodalGradientProcess<2, component_type, Historical>::ClearGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->FastGetSolutionStepValue(mrGradientVariable).clear(); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template<> -void ComputeNodalGradientProcess<3, component_type, Historical>::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -331,15 +210,15 @@ void ComputeNodalGradientProcess<3, component_type, Historical>::ClearGradient() /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, Variable, NonHistorical>::ClearGradient() +void ComputeNodalGradientProcess::ClearGradient() { - const array_1d AuxZeroVector = ZeroVector(3); + const array_1d aux_zero_vector = ZeroVector(3); #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); + it_node->SetValue(mrGradientVariable, aux_zero_vector); } } @@ -347,55 +226,7 @@ void ComputeNodalGradientProcess<2, Variable, NonHistorical>::ClearGradi /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<3, Variable, NonHistorical>::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<2, component_type, NonHistorical>::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, NonHistorical>::ClearGradient() -{ - const array_1d AuxZeroVector = ZeroVector(3); - - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->SetValue(mrAreaVariable, 0.0); - it_node->SetValue(mrGradientVariable, AuxZeroVector); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, Variable, Historical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -410,97 +241,7 @@ double& ComputeNodalGradientProcess<2, Variable, Historical>::GetGradien /***********************************************************************************/ template <> -double& ComputeNodalGradientProcess<3, Variable, Historical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, component_type, Historical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<3, component_type, Historical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, Variable, NonHistorical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<3, Variable, NonHistorical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<2, component_type, NonHistorical>::GetGradient( - Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k - ) -{ - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - - return val; -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -double& ComputeNodalGradientProcess<3, component_type, NonHistorical>::GetGradient( +double& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, unsigned int i, unsigned int k @@ -515,20 +256,7 @@ double& ComputeNodalGradientProcess<3, component_type, NonHistorical>::GetGradie /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, Variable, Historical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node = mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, Variable, Historical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { @@ -541,93 +269,19 @@ void ComputeNodalGradientProcess<3, Variable, Historical>::PonderateGrad /***********************************************************************************/ template <> -void ComputeNodalGradientProcess<2, component_type, Historical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) - { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, Historical>::PonderateGradient() +void ComputeNodalGradientProcess::PonderateGradient() { #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->FastGetSolutionStepValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<2, Variable, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) - { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, Variable, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); } } - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<2, component_type, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - -/***********************************************************************************/ -/***********************************************************************************/ - -template <> -void ComputeNodalGradientProcess<3, component_type, NonHistorical>::PonderateGradient() -{ - #pragma omp parallel for - for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { - auto it_node=mrModelPart.NodesBegin()+i; - it_node->GetValue(mrGradientVariable) /= it_node->GetValue(mrAreaVariable); - } -} - /***********************************************************************************/ /***********************************************************************************/ -template class ComputeNodalGradientProcess<2, Variable, Historical>; -template class ComputeNodalGradientProcess<2, Variable, NonHistorical>; -template class ComputeNodalGradientProcess<3, Variable, Historical>; -template class ComputeNodalGradientProcess<3, Variable, NonHistorical>; -template class ComputeNodalGradientProcess<2, component_type, Historical>; -template class ComputeNodalGradientProcess<2, component_type, NonHistorical>; -template class ComputeNodalGradientProcess<3, component_type, Historical>; -template class ComputeNodalGradientProcess<3, component_type, NonHistorical>; +template class ComputeNodalGradientProcess; +template class ComputeNodalGradientProcess; } /* namespace Kratos.*/ From 586a4813a3a006c77581693244df829fe2c74420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 9 Dec 2018 21:56:34 +0100 Subject: [PATCH 15/31] Missing --- .../compute_nodal_gradient_process.cpp | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 1dc239975279..61c26108591e 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -118,7 +118,11 @@ ComputeNodalGradientProcessHas( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -140,8 +144,15 @@ ComputeNodalGradientProcessHas( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -164,7 +175,11 @@ ComputeNodalGradientProcessHas( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } @@ -186,8 +201,15 @@ ComputeNodalGradientProcessHas( rGradientVariable )) << "Missing variable " << rGradientVariable << std::endl; - KRATOS_ERROR_IF_NOT(rModelPart.Nodes().begin()->Has( rAreaVariable )) << "Missing variable " << rAreaVariable << std::endl; + // In case the area or gradient variable is not initialized we initialize it + auto& r_nodes = rModelPart.Nodes(); + if (!r_nodes.begin()->Has( rGradientVariable )) { + const array_1d zero_vector = ZeroVector(3); + VariableUtils().SetNonHistoricalVariable(rGradientVariable, zero_vector, r_nodes); + } + if (!r_nodes.begin()->Has( rAreaVariable )) { + VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); + } KRATOS_CATCH("") } From 3c54ceb111159422472e82b670dd74488e9bb952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 10 Dec 2018 12:14:10 +0100 Subject: [PATCH 16/31] New tests --- .../test_compute_nodal_gradient_process.cpp | 251 +++++++++++++++--- 1 file changed, 207 insertions(+), 44 deletions(-) diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index 9e781d966613..ed51fa432184 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -17,7 +17,9 @@ // Project includes #include "containers/model.h" #include "geometries/triangle_2d_3.h" +#include "geometries/quadrilateral_2d_4.h" #include "geometries/tetrahedra_3d_4.h" +#include "geometries/hexahedra_3d_8.h" #include "testing/testing.h" #include "includes/kratos_flags.h" #include "includes/gid_io.h" @@ -45,130 +47,130 @@ namespace Kratos gid_io.WriteNodalResults(DISTANCE_GRADIENT, ThisModelPart.Nodes(), label, 0); } - /** + /** * Checks the correct work of the nodal gradient compute * Test triangle */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite2) { Model current_model; - + ModelPart& this_model_part = current_model.CreateModelPart("Main"); this_model_part.SetBufferSize(2); - + this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); - + auto& process_info = this_model_part.GetProcessInfo(); process_info[STEP] = 1; process_info[NL_ITERATION_NUMBER] = 1; - - // First we create the nodes + + // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); - + // Initialize nodal area for (auto& node : this_model_part.Nodes()) node.SetValue(NODAL_AREA, 0.0); - + // Now we create the "conditions" std::vector element_nodes_0 (3); element_nodes_0[0] = p_node_1; element_nodes_0[1] = p_node_2; element_nodes_0[2] = p_node_3; Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); - + std::vector element_nodes_1 (3); element_nodes_1[0] = p_node_1; element_nodes_1[1] = p_node_3; element_nodes_1[2] = p_node_4; Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); - + std::vector element_nodes_2 (3); element_nodes_2[0] = p_node_2; element_nodes_2[1] = p_node_5; element_nodes_2[2] = p_node_3; Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); - + std::vector element_nodes_3 (3); element_nodes_3[0] = p_node_5; element_nodes_3[1] = p_node_6; element_nodes_3[2] = p_node_3; Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); - + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); - + // Set DISTANCE for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_AREA, 0.0); } - + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); - -// // DEBUG + +// // DEBUG // GiDIODebugGradient(this_model_part); - + const double tolerance = 1.0e-8; KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_6->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); } - - /** + + /** * Checks the correct work of the nodal gradient compute * Test tetrahedra */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient2, KratosCoreFastSuite) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient2, KratosCoreFastSuite2) { Model current_model; ModelPart& this_model_part = current_model.CreateModelPart("Main"); this_model_part.SetBufferSize(2); - + this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); - + auto& process_info = this_model_part.GetProcessInfo(); process_info[STEP] = 1; process_info[NL_ITERATION_NUMBER] = 1; - - // First we create the nodes + + // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); - + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); - + // Initialize nodal area for (auto& node : this_model_part.Nodes()) node.SetValue(NODAL_AREA, 0.0); - + // Now we create the "conditions" std::vector element_nodes_0 (4); element_nodes_0[0] = p_node_12; @@ -176,84 +178,84 @@ namespace Kratos element_nodes_0[2] = p_node_8; element_nodes_0[3] = p_node_9; Tetrahedra3D4 tetrahedra_0( PointerVector{element_nodes_0} ); - + std::vector element_nodes_1 (4); element_nodes_1[0] = p_node_4; element_nodes_1[1] = p_node_6; element_nodes_1[2] = p_node_9; element_nodes_1[3] = p_node_7; Tetrahedra3D4 tetrahedra_1( PointerVector{element_nodes_1} ); - + std::vector element_nodes_2 (4); element_nodes_2[0] = p_node_11; element_nodes_2[1] = p_node_7; element_nodes_2[2] = p_node_9; element_nodes_2[3] = p_node_8; Tetrahedra3D4 tetrahedra_2( PointerVector{element_nodes_2} ); - + std::vector element_nodes_3 (4); element_nodes_3[0] = p_node_5; element_nodes_3[1] = p_node_3; element_nodes_3[2] = p_node_8; element_nodes_3[3] = p_node_6; Tetrahedra3D4 tetrahedra_3( PointerVector{element_nodes_3} ); - + std::vector element_nodes_4 (4); element_nodes_4[0] = p_node_4; element_nodes_4[1] = p_node_6; element_nodes_4[2] = p_node_7; element_nodes_4[3] = p_node_3; Tetrahedra3D4 tetrahedra_4( PointerVector{element_nodes_4} ); - + std::vector element_nodes_5 (4); element_nodes_5[0] = p_node_2; element_nodes_5[1] = p_node_3; element_nodes_5[2] = p_node_5; element_nodes_5[3] = p_node_6; Tetrahedra3D4 tetrahedra_5( PointerVector{element_nodes_5} ); - + std::vector element_nodes_6 (4); element_nodes_6[0] = p_node_10; element_nodes_6[1] = p_node_9; element_nodes_6[2] = p_node_6; element_nodes_6[3] = p_node_8; Tetrahedra3D4 tetrahedra_6( PointerVector{element_nodes_6} ); - + std::vector element_nodes_7 (4); element_nodes_7[0] = p_node_7; element_nodes_7[1] = p_node_8; element_nodes_7[2] = p_node_3; element_nodes_7[3] = p_node_6; Tetrahedra3D4 tetrahedra_7( PointerVector{element_nodes_7} ); - + std::vector element_nodes_8 (4); element_nodes_8[0] = p_node_7; element_nodes_8[1] = p_node_8; element_nodes_8[2] = p_node_6; element_nodes_8[3] = p_node_9; Tetrahedra3D4 tetrahedra_8( PointerVector{element_nodes_8} ); - + std::vector element_nodes_9 (4); element_nodes_9[0] = p_node_4; element_nodes_9[1] = p_node_1; element_nodes_9[2] = p_node_6; element_nodes_9[3] = p_node_3; Tetrahedra3D4 tetrahedra_9( PointerVector{element_nodes_9} ); - + std::vector element_nodes_10 (4); element_nodes_10[0] = p_node_9; element_nodes_10[1] = p_node_12; element_nodes_10[2] = p_node_11; element_nodes_10[3] = p_node_8; Tetrahedra3D4 tetrahedra_10( PointerVector{element_nodes_10} ); - + std::vector element_nodes_11 (4); element_nodes_11[0] = p_node_3; element_nodes_11[1] = p_node_2; element_nodes_11[2] = p_node_1; element_nodes_11[3] = p_node_6; Tetrahedra3D4 tetrahedra_11( PointerVector{element_nodes_11} ); - + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D4N", 1, tetrahedra_0, p_elem_prop); Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D4N", 2, tetrahedra_1, p_elem_prop); Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element3D4N", 3, tetrahedra_2, p_elem_prop); @@ -266,22 +268,183 @@ namespace Kratos Element::Pointer p_elem_9 = this_model_part.CreateNewElement("Element3D4N", 10, tetrahedra_9, p_elem_prop); Element::Pointer p_elem_10 = this_model_part.CreateNewElement("Element3D4N", 11, tetrahedra_10, p_elem_prop); Element::Pointer p_elem_11 = this_model_part.CreateNewElement("Element3D4N", 12, tetrahedra_11, p_elem_prop); - + // Set DISTANCE for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_AREA, 0.0); } - + // Compute gradient typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_9->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_10->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_11->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_12->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test quadrilateral + */ + KRATOS_TEST_CASE_IN_SUITE(NodalGradient3, KratosCoreFastSuite2) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + element_nodes_0[3] = p_node_4; + Quadrilateral2D4 quadrilateral_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_2; + element_nodes_1[1] = p_node_5; + element_nodes_1[2] = p_node_6; + element_nodes_1[3] = p_node_3; + Quadrilateral2D4 quadrilateral_1( PointerVector{element_nodes_1} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D4N", 1, quadrilateral_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D4N", 2, quadrilateral_1, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + typedef ComputeNodalGradientProcess GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); // // DEBUG // GiDIODebugGradient(this_model_part); + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_6->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test hexahedra + */ + KRATOS_TEST_CASE_IN_SUITE(NodalGradient4, KratosCoreFastSuite2) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (8); + element_nodes_0[0] = p_node_5; + element_nodes_0[1] = p_node_8; + element_nodes_0[2] = p_node_6; + element_nodes_0[3] = p_node_2; + element_nodes_0[4] = p_node_3; + element_nodes_0[5] = p_node_7; + element_nodes_0[6] = p_node_4; + element_nodes_0[7] = p_node_1; + Hexahedra3D8 hexahedra_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (8); + element_nodes_1[0] = p_node_8; + element_nodes_1[1] = p_node_12; + element_nodes_1[2] = p_node_10; + element_nodes_1[3] = p_node_6; + element_nodes_1[4] = p_node_7; + element_nodes_1[5] = p_node_11; + element_nodes_1[6] = p_node_9; + element_nodes_1[7] = p_node_4; + Hexahedra3D8 hexahedra_1( PointerVector{element_nodes_1} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D8N", 1, hexahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D8N", 2, hexahedra_1, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + // Compute gradient + typedef ComputeNodalGradientProcess GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + const double tolerance = 1.0e-8; KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); From 2e75fdf02cb0f349f06a0cafbd08b205066649a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Mon, 10 Dec 2018 12:15:43 +0100 Subject: [PATCH 17/31] Rename tests --- .../processes/test_compute_nodal_gradient_process.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp index ed51fa432184..37606adba997 100644 --- a/kratos/tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/processes/test_compute_nodal_gradient_process.cpp @@ -52,7 +52,7 @@ namespace Kratos * Test triangle */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite2) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite) { Model current_model; @@ -136,7 +136,7 @@ namespace Kratos * Test tetrahedra */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient2, KratosCoreFastSuite2) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient2, KratosCoreFastSuite) { Model current_model; @@ -299,7 +299,7 @@ namespace Kratos * Checks the correct work of the nodal gradient compute * Test quadrilateral */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient3, KratosCoreFastSuite2) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient3, KratosCoreFastSuite) { Model current_model; @@ -370,7 +370,7 @@ namespace Kratos * Checks the correct work of the nodal gradient compute * Test hexahedra */ - KRATOS_TEST_CASE_IN_SUITE(NodalGradient4, KratosCoreFastSuite2) + KRATOS_TEST_CASE_IN_SUITE(NodalGradient4, KratosCoreFastSuite) { Model current_model; From 6c0124d6426396069a72be731c3fbdd8725c0331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 11 Dec 2018 15:41:45 +0100 Subject: [PATCH 18/31] Avoid conflict --- .../auxiliar_files/test_bar_element.cpp | 365 +++++ .../auxiliar_files/test_bar_element.h | 321 ++++ .../cpp_tests/auxiliar_files/test_element.cpp | 382 +++++ .../cpp_tests/auxiliar_files/test_element.h | 331 +++++ .../test_constitutive_law.cpp | 83 ++ .../containers/test_data_value_container.cpp | 80 + .../tests/cpp_tests/containers/test_model.cpp | 128 ++ .../cpp_tests/containers/test_variables.cpp | 64 + .../cpp_tests/exceptions/test_exceptions.cpp | 89 ++ .../cross_check_shape_functions_values.h | 32 + .../cpp_tests/geometries/test_geometry.cpp | 388 +++++ .../cpp_tests/geometries/test_geometry.h | 123 ++ .../geometries/test_hexahedra_3d_8.cpp | 278 ++++ .../cpp_tests/geometries/test_line_2d_2.cpp | 143 ++ .../test_non_rectangular_jacobian.cpp | 112 ++ .../cpp_tests/geometries/test_prism_3d_6.cpp | 266 ++++ .../geometries/test_quadrilateral_2d_4.cpp | 177 +++ .../geometries/test_quadrilateral_3d_4.cpp | 378 +++++ .../test_shape_function_derivatives.h | 51 + .../geometries/test_tetrahedra_3d_10.cpp | 171 +++ .../geometries/test_tetrahedra_3d_4.cpp | 546 +++++++ .../geometries/test_triangle_2d_3.cpp | 578 ++++++++ .../geometries/test_triangle_2d_6.cpp | 158 ++ .../geometries/test_triangle_3d_3.cpp | 645 +++++++++ .../global_pointers/test_global_pointer.cpp | 195 +++ .../cpp_tests/input_output/test_logger.cpp | 297 ++++ ...ra_3d_4_ausas_modified_shape_functions.cpp | 1290 +++++++++++++++++ ...trahedra_3d_4_modified_shape_functions.cpp | 1285 ++++++++++++++++ ...le_2d_3_ausas_modified_shape_functions.cpp | 668 +++++++++ ...triangle_2d_3_modified_shape_functions.cpp | 725 +++++++++ ...discontinuous_distance_to_skin_process.cpp | 770 ++++++++++ ...est_calculate_distance_to_skin_process.cpp | 487 +++++++ .../processes/test_coarsening_process.cpp | 294 ++++ .../test_compute_nodal_gradient_process.cpp | 288 ++++ ...t_transfer_between_model_parts_process.cpp | 317 ++++ ...ntersected_geometrical_objects_process.cpp | 196 +++ .../processes/test_find_nodal_h_process.cpp | 268 ++++ .../processes/test_mortar_mapper_process.cpp | 342 +++++ ...replace_elements_and_condition_process.cpp | 259 ++++ .../processes/test_skin_detection_process.cpp | 81 ++ ...test_structured_mesh_generator_process.cpp | 128 ++ .../test_tetrahedra_edge_swapping_process.cpp | 83 ++ .../cross_check_shape_functions_values.cpp | 103 ++ .../tests/cpp_tests/sources/test_amatrix.cpp | 37 + .../cpp_tests/sources/test_amatrix_alias.cpp | 134 ++ .../tests/cpp_tests/sources/test_checks.cpp | 102 ++ kratos/tests/cpp_tests/sources/test_chunk.cpp | 164 +++ .../cpp_tests/sources/test_code_location.cpp | 63 + ...ompare_elements_and_conditions_utility.cpp | 152 ++ .../cpp_tests/sources/test_condition.cpp | 63 + kratos/tests/cpp_tests/sources/test_dof.cpp | 151 ++ .../tests/cpp_tests/sources/test_element.cpp | 62 + .../cpp_tests/sources/test_exceptions.cpp | 42 + .../test_linear_master_slave_constraint.cpp | 67 + .../cpp_tests/sources/test_memory_pool.cpp | 163 +++ .../cpp_tests/sources/test_model_part.cpp | 253 ++++ .../cpp_tests/sources/test_model_part_io.cpp | 380 +++++ .../cpp_tests/sources/test_nodal_data.cpp | 94 ++ kratos/tests/cpp_tests/sources/test_node.cpp | 79 + .../cpp_tests/sources/test_parameters.cpp | 100 ++ .../cpp_tests/sources/test_properties.cpp | 85 ++ .../cpp_tests/sources/test_serializer.cpp | 307 ++++ .../test_shape_function_derivatives.cpp | 135 ++ .../spatial_containers/test_bins_dynamic.cpp | 336 +++++ .../spatial_containers/test_bins_static.cpp | 352 +++++ .../test_builder_and_solver.cpp | 786 ++++++++++ ...t_residual_based_adjoint_bossak_scheme.cpp | 704 +++++++++ .../strategies/schemes/test_schemes.cpp | 296 ++++ .../strategies/strategies/test_strategies.cpp | 223 +++ .../tests/cpp_tests/testing/test_testing.cpp | 35 + ...ique_model_part_collection_tag_utility.cpp | 339 +++++ .../test_binbased_fast_point_locator.cpp | 356 +++++ .../utilities/test_brent_iteration.cpp | 54 + .../test_brute_force_point_locator.cpp | 212 +++ .../utilities/test_discont_utils.cpp | 330 +++++ .../utilities/test_divide_tetrahedra_3d_4.cpp | 687 +++++++++ .../utilities/test_divide_triangle_2d_3.cpp | 360 +++++ .../utilities/test_embedded_skin_utility.cpp | 106 ++ .../test_geometrical_projection_utilities.cpp | 107 ++ .../test_geometrical_sensitivity_utility.cpp | 196 +++ .../utilities/test_geometry_utils.cpp | 55 + .../utilities/test_intersection_utilities.cpp | 424 ++++++ .../cpp_tests/utilities/test_math_utils.cpp | 850 +++++++++++ .../test_plane_approximation_utility.cpp | 140 ++ .../tests/cpp_tests/utilities/test_stl_io.cpp | 47 + .../cpp_tests/utilities/test_svd_utils.cpp | 126 ++ 86 files changed, 23719 insertions(+) create mode 100644 kratos/tests/cpp_tests/auxiliar_files/test_bar_element.cpp create mode 100644 kratos/tests/cpp_tests/auxiliar_files/test_bar_element.h create mode 100644 kratos/tests/cpp_tests/auxiliar_files/test_element.cpp create mode 100644 kratos/tests/cpp_tests/auxiliar_files/test_element.h create mode 100644 kratos/tests/cpp_tests/constitutive_laws/test_constitutive_law.cpp create mode 100644 kratos/tests/cpp_tests/containers/test_data_value_container.cpp create mode 100644 kratos/tests/cpp_tests/containers/test_model.cpp create mode 100644 kratos/tests/cpp_tests/containers/test_variables.cpp create mode 100644 kratos/tests/cpp_tests/exceptions/test_exceptions.cpp create mode 100644 kratos/tests/cpp_tests/geometries/cross_check_shape_functions_values.h create mode 100644 kratos/tests/cpp_tests/geometries/test_geometry.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_geometry.h create mode 100644 kratos/tests/cpp_tests/geometries/test_hexahedra_3d_8.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_line_2d_2.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_non_rectangular_jacobian.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_prism_3d_6.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_quadrilateral_2d_4.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_quadrilateral_3d_4.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_shape_function_derivatives.h create mode 100644 kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_10.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_4.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_triangle_2d_3.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_triangle_2d_6.cpp create mode 100644 kratos/tests/cpp_tests/geometries/test_triangle_3d_3.cpp create mode 100644 kratos/tests/cpp_tests/global_pointers/test_global_pointer.cpp create mode 100644 kratos/tests/cpp_tests/input_output/test_logger.cpp create mode 100644 kratos/tests/cpp_tests/modified_shape_functions/test_tetrahedra_3d_4_ausas_modified_shape_functions.cpp create mode 100644 kratos/tests/cpp_tests/modified_shape_functions/test_tetrahedra_3d_4_modified_shape_functions.cpp create mode 100644 kratos/tests/cpp_tests/modified_shape_functions/test_triangle_2d_3_ausas_modified_shape_functions.cpp create mode 100644 kratos/tests/cpp_tests/modified_shape_functions/test_triangle_2d_3_modified_shape_functions.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_calculate_discontinuous_distance_to_skin_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_calculate_distance_to_skin_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_coarsening_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_fast_transfer_between_model_parts_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_find_intersected_geometrical_objects_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_find_nodal_h_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_mortar_mapper_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_replace_elements_and_condition_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_skin_detection_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_structured_mesh_generator_process.cpp create mode 100644 kratos/tests/cpp_tests/processes/test_tetrahedra_edge_swapping_process.cpp create mode 100644 kratos/tests/cpp_tests/sources/cross_check_shape_functions_values.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_amatrix.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_amatrix_alias.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_checks.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_chunk.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_code_location.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_compare_elements_and_conditions_utility.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_condition.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_dof.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_element.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_exceptions.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_linear_master_slave_constraint.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_memory_pool.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_model_part.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_model_part_io.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_nodal_data.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_node.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_parameters.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_properties.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_serializer.cpp create mode 100644 kratos/tests/cpp_tests/sources/test_shape_function_derivatives.cpp create mode 100644 kratos/tests/cpp_tests/spatial_containers/test_bins_dynamic.cpp create mode 100644 kratos/tests/cpp_tests/spatial_containers/test_bins_static.cpp create mode 100755 kratos/tests/cpp_tests/strategies/builder_and_solvers/test_builder_and_solver.cpp create mode 100644 kratos/tests/cpp_tests/strategies/schemes/test_residual_based_adjoint_bossak_scheme.cpp create mode 100644 kratos/tests/cpp_tests/strategies/schemes/test_schemes.cpp create mode 100755 kratos/tests/cpp_tests/strategies/strategies/test_strategies.cpp create mode 100644 kratos/tests/cpp_tests/testing/test_testing.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_assign_unique_model_part_collection_tag_utility.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_binbased_fast_point_locator.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_brent_iteration.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_brute_force_point_locator.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_discont_utils.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_divide_tetrahedra_3d_4.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_divide_triangle_2d_3.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_embedded_skin_utility.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_geometrical_projection_utilities.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_geometrical_sensitivity_utility.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_geometry_utils.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_intersection_utilities.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_math_utils.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_plane_approximation_utility.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_stl_io.cpp create mode 100644 kratos/tests/cpp_tests/utilities/test_svd_utils.cpp diff --git a/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.cpp b/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.cpp new file mode 100644 index 000000000000..cfa930473e7a --- /dev/null +++ b/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.cpp @@ -0,0 +1,365 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes + +// Project includes +#include "includes/define.h" +#include "includes/checks.h" +#include "includes/variables.h" +#include "tests/cpp_tests/auxiliar_files/test_bar_element.h" + +namespace Kratos +{ + namespace Testing + { + //***********************DEFAULT CONSTRUCTOR******************************************// + //************************************************************************************// + + TestBarElement::TestBarElement( + IndexType NewId, + GeometryType::Pointer pGeometry + ) + : Element( NewId, pGeometry ) + { + //DO NOT ADD DOFS HERE!!! + } + + + //******************************CONSTRUCTOR*******************************************// + //************************************************************************************// + + TestBarElement::TestBarElement( + IndexType NewId, GeometryType::Pointer pGeometry, + PropertiesType::Pointer pProperties + ) + : Element( NewId, pGeometry, pProperties ) + { + + } + + //******************************COPY CONSTRUCTOR**************************************// + //************************************************************************************// + + TestBarElement::TestBarElement( TestBarElement const& rOther) + :Element(rOther) + { + + } + + //*******************************ASSIGMENT OPERATOR***********************************// + //************************************************************************************// + + TestBarElement& TestBarElement::operator=(TestBarElement const& rOther) + { + //ALL MEMBER VARIABLES THAT MUST BE KEPT IN AN "=" OPERATION NEEDS TO BE COPIED HERE + + Element::operator=(rOther); + + return *this; + } + + //*********************************OPERATIONS*****************************************// + //************************************************************************************// + + Element::Pointer TestBarElement::Create( + IndexType NewId, + NodesArrayType const& rThisNodes, + PropertiesType::Pointer pProperties + ) const + { + //NEEDED TO CREATE AN ELEMENT + return Kratos::make_shared( NewId, GetGeometry().Create( rThisNodes ), pProperties ); + } + + + //************************************CLONE*******************************************// + //************************************************************************************// + + Element::Pointer TestBarElement::Clone( + IndexType NewId, + NodesArrayType const& rThisNodes + ) const + { + //YOU CREATE A NEW ELEMENT CLONING THEIR VARIABLES + //ALL MEMBER VARIABLES THAT MUST BE CLONED HAVE TO BE DEFINED HERE + + TestBarElement new_element(NewId, GetGeometry().Create( rThisNodes ), pGetProperties() ); + + return Kratos::make_shared(new_element); + } + + + //*******************************DESTRUCTOR*******************************************// + //************************************************************************************// + + TestBarElement::~TestBarElement() + { + } + + //************* GETTING METHODS + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::GetDofList( + DofsVectorType& rElementalDofList, + ProcessInfo& rCurrentProcessInfo + ) + { + //NEEDED TO DEFINE THE DOFS OF THE ELEMENT + + rElementalDofList.resize( 0 ); + + rElementalDofList.push_back( GetGeometry()[0].pGetDof( DISPLACEMENT_X ) ); + rElementalDofList.push_back( GetGeometry()[0].pGetDof( DISPLACEMENT_Y ) ); + rElementalDofList.push_back( GetGeometry()[1].pGetDof( DISPLACEMENT_X ) ); + rElementalDofList.push_back( GetGeometry()[1].pGetDof( DISPLACEMENT_Y ) ); + } + + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::EquationIdVector( + EquationIdVectorType& rResult, + ProcessInfo& rCurrentProcessInfo + ) + { + //NEEDED TO DEFINE GLOBAL IDS FOR THE CORRECT ASSEMBLY + + if ( rResult.size() != 4 ) + rResult.resize( 4, false ); + + rResult[0] = GetGeometry()[0].GetDof( DISPLACEMENT_X ).EquationId(); + rResult[1] = GetGeometry()[0].GetDof( DISPLACEMENT_Y ).EquationId(); + rResult[2] = GetGeometry()[1].GetDof( DISPLACEMENT_X ).EquationId(); + rResult[3] = GetGeometry()[1].GetDof( DISPLACEMENT_Y ).EquationId(); + } + + //*********************************DISPLACEMENT***************************************// + //************************************************************************************// + + void TestBarElement::GetValuesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT DISPLACEMENTS) + if ( rValues.size() != 4 ) + rValues.resize( 4, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( DISPLACEMENT_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( DISPLACEMENT_Y, Step ); + rValues[2] = GetGeometry()[1].GetSolutionStepValue( DISPLACEMENT_X, Step ); + rValues[3] = GetGeometry()[1].GetSolutionStepValue( DISPLACEMENT_Y, Step ); + } + + + //************************************VELOCITY****************************************// + //************************************************************************************// + + void TestBarElement::GetFirstDerivativesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE TIME DERIVATIVE OF THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT VELOCITIES) + if ( rValues.size() != 4 ) + rValues.resize( 4, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( VELOCITY_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( VELOCITY_Y, Step ); + rValues[2] = GetGeometry()[1].GetSolutionStepValue( VELOCITY_X, Step ); + rValues[3] = GetGeometry()[1].GetSolutionStepValue( VELOCITY_Y, Step ); + } + + //*********************************ACCELERATION***************************************// + //************************************************************************************// + + void TestBarElement::GetSecondDerivativesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE TIME SECOND DERIVATIVE OF THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT ACCELERATIONS) + if ( rValues.size() != 4 ) + rValues.resize( 4, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( ACCELERATION_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( ACCELERATION_Y, Step ); + rValues[2] = GetGeometry()[1].GetSolutionStepValue( ACCELERATION_X, Step ); + rValues[3] = GetGeometry()[1].GetSolutionStepValue( ACCELERATION_Y, Step ); + } + + //************* COMPUTING METHODS + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::CalculateLocalSystem( MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo ) + { + + KRATOS_TRY; + + /* Calculate elemental system */ + + // Compute RHS (RHS = rRightHandSideVector = Fext - Fint) + this->CalculateRightHandSide(rRightHandSideVector, rCurrentProcessInfo); + + // Compute LHS + this->CalculateLeftHandSide(rLeftHandSideMatrix, rCurrentProcessInfo); + + KRATOS_CATCH( "" ); + } + + //*********************************************************************************** + //*********************************************************************************** + + void TestBarElement::CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo ) + { + // Resizing as needed the RHS + const unsigned int system_size = 4; + + if ( rRightHandSideVector.size() != system_size ) + rRightHandSideVector.resize( system_size, false ); + + rRightHandSideVector = ZeroVector( system_size ); //resetting RHS + + // We don't care about filling the RHS, we are just interested in the LHS for the test + } + + //*********************************************************************************** + //*********************************************************************************** + + void TestBarElement::CalculateLeftHandSide( MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo ) + { + // Resizing as needed the LHS + const unsigned int system_size = 4; + + if ( rLeftHandSideMatrix.size1() != system_size ) + rLeftHandSideMatrix.resize( system_size, system_size, false ); + + noalias( rLeftHandSideMatrix ) = ZeroMatrix( system_size, system_size ); //resetting LHS + + const double E = this->GetProperties()[YOUNG_MODULUS]; + const double A = this->GetProperties()[NODAL_AREA]; + const double L = this->GetGeometry().Length(); + const double k = E*A/L; + + const double dx = this->GetGeometry()[1].X0() - this->GetGeometry()[0].X0(); + const double dy = this->GetGeometry()[1].Y0() - this->GetGeometry()[0].Y0(); + const double theta = std::atan2(dy, dx); + const double l = std::cos(theta); + const double m = std::sin(theta); + + rLeftHandSideMatrix(0,0) = k * l * l; + rLeftHandSideMatrix(0,1) = k * m * l; + rLeftHandSideMatrix(0,2) = -k * l * l; + rLeftHandSideMatrix(0,3) = -k * m * l; + + rLeftHandSideMatrix(1,0) = k * l * m; + rLeftHandSideMatrix(1,1) = k * m * m; + rLeftHandSideMatrix(1,2) = -k * m * l; + rLeftHandSideMatrix(1,3) = -k * m * m; + + rLeftHandSideMatrix(2,0) = -k * l * l; + rLeftHandSideMatrix(2,1) = -k * m * l; + rLeftHandSideMatrix(2,2) = k * l * l; + rLeftHandSideMatrix(2,3) = k * m * l; + + rLeftHandSideMatrix(3,0) = -k * l * m; + rLeftHandSideMatrix(3,1) = -k * m * m; + rLeftHandSideMatrix(3,2) = k * m * l; + rLeftHandSideMatrix(3,3) = k * m * m; + } + + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::CalculateMassMatrix( MatrixType& rMassMatrix, ProcessInfo& rCurrentProcessInfo ) + { + KRATOS_TRY + + //lumped + unsigned int system_size = 4; + + if ( rMassMatrix.size1() != system_size ) + rMassMatrix.resize( system_size, system_size, false ); + + rMassMatrix = ZeroMatrix( system_size, system_size ); + + KRATOS_CATCH( "" ); + } + + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::CalculateDampingMatrix( + MatrixType& rDampingMatrix, + ProcessInfo& rCurrentProcessInfo + ) + { + KRATOS_TRY; + + // Resizing as needed the LHS + const unsigned int system_size = 4; + + rDampingMatrix = ZeroMatrix( system_size, system_size ); + + KRATOS_CATCH( "" ); + } + + //************************************************************************************// + //************************************************************************************// + + int TestBarElement::Check( const ProcessInfo& rCurrentProcessInfo ) + { + KRATOS_TRY + + // Check that all required variables have been registered + KRATOS_CHECK_VARIABLE_KEY(DISPLACEMENT) + KRATOS_CHECK_VARIABLE_KEY(VELOCITY) + KRATOS_CHECK_VARIABLE_KEY(ACCELERATION) + KRATOS_CHECK_VARIABLE_KEY(NODAL_AREA) + KRATOS_CHECK_VARIABLE_KEY(YOUNG_MODULUS) + + KRATOS_ERROR_IF_NOT(GetProperties().Has(YOUNG_MODULUS)) << "YOUNG_MODULUS not defined" << std::endl; + KRATOS_ERROR_IF_NOT(GetProperties().Has(NODAL_AREA)) << "NODAL_AREA not defined" << std::endl; + + // Check that the element's nodes contain all required SolutionStepData and Degrees of freedom + for ( std::size_t i = 0; i < this->GetGeometry().size(); ++i ) { + Node<3>& rnode = this->GetGeometry()[i]; + + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(DISPLACEMENT,rnode) + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY,rnode) + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ACCELERATION,rnode) + + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_X,rnode) + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_Y,rnode) + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_Z,rnode) + } + + return 0; + + KRATOS_CATCH( "Problem in the Check in the TestBarElement" ) + } + + + //************************************************************************************// + //************************************************************************************// + + void TestBarElement::save( Serializer& rSerializer ) const + { + KRATOS_SERIALIZE_SAVE_BASE_CLASS( rSerializer, Element ) + } + + void TestBarElement::load( Serializer& rSerializer ) + { + KRATOS_SERIALIZE_LOAD_BASE_CLASS( rSerializer, Element ) + } + + } // Namespace Testing +} // Namespace Kratos + + diff --git a/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.h b/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.h new file mode 100644 index 000000000000..a4140eab6c98 --- /dev/null +++ b/kratos/tests/cpp_tests/auxiliar_files/test_bar_element.h @@ -0,0 +1,321 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +#if !defined(KRATOS_TEST_BAR_ELEMENT_H_INCLUDED ) +#define KRATOS_TEST_BAR_ELEMENT_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "includes/element.h" + +namespace Kratos +{ + namespace Testing + { + ///@name Testing Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Testing Classes + ///@{ + + /** + * @class TestBarElement + * @ingroup KratosCore + * @brief This is simple test element + * @details It is designed to create a simple LHS and RHS in order to test builder and solvers (a minimal connectivity of two nodes). This way the common interface of the elements/conditions can be used to minimize the difference between the actual implementation and the test + * @author Vicente Mataix Ferrandiz + */ + class TestBarElement + : public Element + { + public: + + ///@name Type Definitions + ///@{ + + /// Counted pointer of TestBarElement + KRATOS_CLASS_POINTER_DEFINITION( TestBarElement); + + ///@} + + ///@name Enum's + ///@{ + + ///@} + ///@name Life Cycle + ///@{ + + /** + * @brief Default constructor + * @param NewId the ID of the new element + * @param pGeometry the nodes of the new element + * @param TheResidualType The problem to be solved (linear, non-linear, arc-length ...) + */ + TestBarElement(IndexType NewId, GeometryType::Pointer pGeometry); + + /** + * @brief Default constructor + * @param NewId The ID of the new element + * @param pGeometry The nodes of the new element + * @param pProperties The properties assigned to the new element + * @param TheResidualType The problem to be solved (linear, non-linear, arc-length ...) + */ + TestBarElement(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties); + + ///Copy constructor + TestBarElement(TestBarElement const& rOther); + + /// Destructor. + ~TestBarElement() override; + + ///@} + ///@name Operators + ///@{ + + /// Assignment operator. + TestBarElement& operator=(TestBarElement const& rOther); + + ///@} + ///@name Operations + ///@{ + + /** + * @brief Creates a new total lagrangian updated element pointer + * @param NewId the ID of the new element + * @param ThisNodes the nodes of the new element + * @param pProperties the properties assigned to the new element + * @return a Pointer to the new element + */ + Element::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes, PropertiesType::Pointer pProperties) const override; + + /** + * @brief Clones the selected element variables, creating a new one + * @param NewId the ID of the new element + * @param ThisNodes the nodes of the new element + * @return a Pointer to the new element + */ + Element::Pointer Clone(IndexType NewId, NodesArrayType const& ThisNodes) const override; + + //************* GETTING METHODS + + /** + * @brief Sets on rElementalDofList the degrees of freedom of the considered element geometry + * @param rElementalDofList The vector containing the list of the DoFs + * @param rCurrentProcessInfo The current process info instance + */ + void GetDofList( + DofsVectorType& rElementalDofList, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief Sets on rResult the ID's of the element degrees of freedom + * @param rResult The vector containing the ids of the DoFs + * @param rCurrentProcessInfo The current process info instance + */ + void EquationIdVector( + EquationIdVectorType& rResult, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief Sets on rValues the nodal displacements + * @param rValues The vector containing the dofs values + * @param Step The time step computed (must be in the buffer) + */ + void GetValuesVector(Vector& rValues, int Step = 0) override; + + /** + * @brief Sets on rValues the nodal velocities + * @param rValues The vector containing the first derivatives + * @param Step The time step computed (must be in the buffer) + */ + void GetFirstDerivativesVector(Vector& rValues, int Step = 0) override; + + /** + * @brief Sets on rValues the nodal accelerations + * @param rValues The vector containing the second derivatives + * @param Step The time step computed (must be in the buffer) + */ + void GetSecondDerivativesVector(Vector& rValues, int Step = 0) override; + + //************* COMPUTING METHODS + + /** + * @brief This is called during the assembling process in order to calculate all elemental contributions to the global system matrix and the right hand side + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateLocalSystem( + MatrixType& rLeftHandSideMatrix, + VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This calculates just the RHS + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateRightHandSide( + VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This calculates just the LHS + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateLeftHandSide( + MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This is called during the assembling process in order to calculate the elemental mass matrix + * @param rMassMatrix the elemental mass matrix + * @param rCurrentProcessInfo the current process info instance + */ + void CalculateMassMatrix( + MatrixType& rMassMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This is called during the assembling process in order + * to calculate the elemental damping matrix + * @param rDampingMatrix The elemental damping matrix + * @param rCurrentProcessInfo The current process info instance + */ + void CalculateDampingMatrix( + MatrixType& rDampingMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This function provides the place to perform checks on the completeness of the input. + * @details It is designed to be called only once (or anyway, not often) typically at the beginning of the calculations, so to verify that nothing is missing from the input or that no common error is found. + * @param rCurrentProcessInfo The current process info instance + */ + int Check(const ProcessInfo& rCurrentProcessInfo) override; + + ///@} + ///@name Access + ///@{ + ///@} + ///@name Inquiry + ///@{ + ///@} + ///@name Input and output + ///@{ + ///@} + ///@name Friends + ///@{ + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + ///@} + ///@name Protected member Variables + ///@{ + ///@} + + ///@name Protected Operators + ///@{ + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + ///@} + ///@name Protected Inquiry + ///@{ + ///@} + ///@name Protected LifeCycle + ///@{ + ///@} + + private: + + ///@name Static Member Variables + ///@{ + ///@} + ///@name Member Variables + ///@{ + ///@} + ///@name Private Operators + ///@{ + ///@} + ///@name Private Operations + ///@{ + ///@} + ///@name Private Access + ///@{ + ///@} + ///@} + ///@name Serialization + ///@{ + + friend class Serializer; + + // A private default constructor necessary for serialization + + void save(Serializer& rSerializer) const override; + + void load(Serializer& rSerializer) override; + + ///@name Private Inquiry + ///@{ + ///@} + ///@name Un accessible methods + ///@{ + ///@} + + }; // Class TestBarElement + + ///@} + ///@name Type Definitions + ///@{ + ///@} + ///@name Input and output + ///@{ + ///@} + } // namespace Testing. +} // namespace Kratos. +#endif // KRATOS_TEST_BAR_ELEMENT_H_INCLUDED defined diff --git a/kratos/tests/cpp_tests/auxiliar_files/test_element.cpp b/kratos/tests/cpp_tests/auxiliar_files/test_element.cpp new file mode 100644 index 000000000000..797cd5b0bdb4 --- /dev/null +++ b/kratos/tests/cpp_tests/auxiliar_files/test_element.cpp @@ -0,0 +1,382 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "includes/define.h" +#include "includes/checks.h" +#include "includes/variables.h" +#include "tests/cpp_tests/auxiliar_files/test_element.h" + +namespace Kratos +{ + namespace Testing + { + //***********************DEFAULT CONSTRUCTOR******************************************// + //************************************************************************************// + + TestElement::TestElement( + IndexType NewId, + GeometryType::Pointer pGeometry, + const ResidualType TheResidualType + ) + : Element( NewId, pGeometry ) + , mResidualType( TheResidualType ) + { + //DO NOT ADD DOFS HERE!!! + } + + + //******************************CONSTRUCTOR*******************************************// + //************************************************************************************// + + TestElement::TestElement( + IndexType NewId, GeometryType::Pointer pGeometry, + PropertiesType::Pointer pProperties, + const ResidualType TheResidualType + ) + : Element( NewId, pGeometry, pProperties ) + , mResidualType( TheResidualType ) + { + + } + + //******************************COPY CONSTRUCTOR**************************************// + //************************************************************************************// + + TestElement::TestElement( TestElement const& rOther) + :Element(rOther) + ,mResidualType(rOther.mResidualType) + { + + } + + //*******************************ASSIGMENT OPERATOR***********************************// + //************************************************************************************// + + TestElement& TestElement::operator=(TestElement const& rOther) + { + //ALL MEMBER VARIABLES THAT MUST BE KEPT IN AN "=" OPERATION NEEDS TO BE COPIED HERE + + Element::operator=(rOther); + + return *this; + } + + //*********************************OPERATIONS*****************************************// + //************************************************************************************// + + Element::Pointer TestElement::Create( + IndexType NewId, + NodesArrayType const& rThisNodes, + PropertiesType::Pointer pProperties + ) const + { + //NEEDED TO CREATE AN ELEMENT + return Kratos::make_shared( NewId, GetGeometry().Create( rThisNodes ), pProperties, mResidualType ); + } + + + //************************************CLONE*******************************************// + //************************************************************************************// + + Element::Pointer TestElement::Clone( + IndexType NewId, + NodesArrayType const& rThisNodes + ) const + { + //YOU CREATE A NEW ELEMENT CLONING THEIR VARIABLES + //ALL MEMBER VARIABLES THAT MUST BE CLONED HAVE TO BE DEFINED HERE + + TestElement new_element(NewId, GetGeometry().Create( rThisNodes ), pGetProperties(), mResidualType ); + + return Kratos::make_shared(new_element); + } + + + //*******************************DESTRUCTOR*******************************************// + //************************************************************************************// + + TestElement::~TestElement() + { + } + + //************* GETTING METHODS + //************************************************************************************// + //************************************************************************************// + + void TestElement::GetDofList( + DofsVectorType& rElementalDofList, + ProcessInfo& rCurrentProcessInfo + ) + { + //NEEDED TO DEFINE THE DOFS OF THE ELEMENT + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + rElementalDofList.resize( 0 ); + + rElementalDofList.push_back( GetGeometry()[0].pGetDof( DISPLACEMENT_X ) ); + rElementalDofList.push_back( GetGeometry()[0].pGetDof( DISPLACEMENT_Y ) ); + if( dimension == 3 ) + rElementalDofList.push_back( GetGeometry()[0].pGetDof( DISPLACEMENT_Z ) ); + } + + //************************************************************************************// + //************************************************************************************// + + void TestElement::EquationIdVector( + EquationIdVectorType& rResult, + ProcessInfo& rCurrentProcessInfo + ) + { + //NEEDED TO DEFINE GLOBAL IDS FOR THE CORRECT ASSEMBLY + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + if ( rResult.size() != dimension ) + rResult.resize( dimension, false ); + + rResult[0] = GetGeometry()[0].GetDof( DISPLACEMENT_X ).EquationId(); + rResult[1] = GetGeometry()[0].GetDof( DISPLACEMENT_Y ).EquationId(); + if( dimension == 3) + rResult[2] = GetGeometry()[0].GetDof( DISPLACEMENT_Z ).EquationId(); + } + + //*********************************DISPLACEMENT***************************************// + //************************************************************************************// + + void TestElement::GetValuesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT DISPLACEMENTS) + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + if ( rValues.size() != dimension ) + rValues.resize( dimension, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( DISPLACEMENT_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( DISPLACEMENT_Y, Step ); + + if ( dimension == 3 ) + rValues[2] = GetGeometry()[0].GetSolutionStepValue( DISPLACEMENT_Z, Step ); + } + + + //************************************VELOCITY****************************************// + //************************************************************************************// + + void TestElement::GetFirstDerivativesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE TIME DERIVATIVE OF THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT VELOCITIES) + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + if ( rValues.size() != dimension ) + rValues.resize( dimension, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( VELOCITY_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( VELOCITY_Y, Step ); + + if ( dimension == 3 ) + rValues[2] = GetGeometry()[0].GetSolutionStepValue( VELOCITY_Z, Step ); + } + + //*********************************ACCELERATION***************************************// + //************************************************************************************// + + void TestElement::GetSecondDerivativesVector( Vector& rValues, int Step ) + { + //GIVES THE VECTOR WITH THE TIME SECOND DERIVATIVE OF THE DOFS VARIABLES OF THE ELEMENT (i.e. ELEMENT ACCELERATIONS) + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + if ( rValues.size() != dimension ) + rValues.resize( dimension, false ); + + rValues[0] = GetGeometry()[0].GetSolutionStepValue( ACCELERATION_X, Step ); + rValues[1] = GetGeometry()[0].GetSolutionStepValue( ACCELERATION_Y, Step ); + + if ( dimension == 3 ) + rValues[2] = GetGeometry()[0].GetSolutionStepValue( ACCELERATION_Z, Step ); + } + + //************* COMPUTING METHODS + //************************************************************************************// + //************************************************************************************// + + void TestElement::CalculateLocalSystem( MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo ) + { + + KRATOS_TRY; + + /* Calculate elemental system */ + + // Compute RHS (RHS = rRightHandSideVector = Fext - Fint) + this->CalculateRightHandSide(rRightHandSideVector, rCurrentProcessInfo); + + // Compute LHS + this->CalculateLeftHandSide(rLeftHandSideMatrix, rCurrentProcessInfo); + + KRATOS_CATCH( "" ); + } + + //*********************************************************************************** + //*********************************************************************************** + + void TestElement::CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo ) + { + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + // Resizing as needed the RHS + const unsigned int system_size = dimension; + + if ( rRightHandSideVector.size() != system_size ) + rRightHandSideVector.resize( system_size, false ); + + rRightHandSideVector = ZeroVector( system_size ); //resetting RHS + + const array_1d& delta_displacement = GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT) - GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT, 1); + + switch ( mResidualType ) + { + case ResidualType::LINEAR: + for ( unsigned int j = 0; j < dimension; ++j ) + rRightHandSideVector[j] -= delta_displacement[j] - 1.0; + break; + case ResidualType::NON_LINEAR: + for ( unsigned int j = 0; j < dimension; ++j ) + rRightHandSideVector[j] -= std::pow(delta_displacement[j], 2) - 1.0; + break; + default: + KRATOS_ERROR << "NOT IMPLEMENTED" << std::endl; + } + } + + //*********************************************************************************** + //*********************************************************************************** + + void TestElement::CalculateLeftHandSide( MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo ) + { + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + // Resizing as needed the LHS + const unsigned int system_size = dimension; + + if ( rLeftHandSideMatrix.size1() != system_size ) + rLeftHandSideMatrix.resize( system_size, system_size, false ); + + noalias( rLeftHandSideMatrix ) = ZeroMatrix( system_size, system_size ); //resetting LHS + + const array_1d& delta_displacement = GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT) - GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT, 1); + + switch ( mResidualType ) + { + case ResidualType::LINEAR: + for ( unsigned int j = 0; j < dimension; ++j ) + rLeftHandSideMatrix(j, j) += 1.0; + break; + case ResidualType::NON_LINEAR: + for ( unsigned int j = 0; j < dimension; ++j ) + rLeftHandSideMatrix(j, j) += delta_displacement[j] * 2; + break; + default: + KRATOS_ERROR << "NOT IMPLEMENTED" << std::endl; + } + } + + //************************************************************************************// + //************************************************************************************// + + void TestElement::CalculateMassMatrix( MatrixType& rMassMatrix, ProcessInfo& rCurrentProcessInfo ) + { + KRATOS_TRY + + //lumped + unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + unsigned int system_size = dimension; + + if ( rMassMatrix.size1() != system_size ) + rMassMatrix.resize( system_size, system_size, false ); + + rMassMatrix = ZeroMatrix( system_size, system_size ); + + KRATOS_CATCH( "" ); + } + + //************************************************************************************// + //************************************************************************************// + + void TestElement::CalculateDampingMatrix( + MatrixType& rDampingMatrix, + ProcessInfo& rCurrentProcessInfo + ) + { + KRATOS_TRY; + + //0.-Initialize the DampingMatrix: + const unsigned int dimension = GetGeometry().WorkingSpaceDimension(); + + // Resizing as needed the LHS + const unsigned int system_size = dimension; + + rDampingMatrix = ZeroMatrix( system_size, system_size ); + + KRATOS_CATCH( "" ); + } + + //************************************************************************************// + //************************************************************************************// + + int TestElement::Check( const ProcessInfo& rCurrentProcessInfo ) + { + KRATOS_TRY + + // Check that all required variables have been registered + KRATOS_CHECK_VARIABLE_KEY(DISPLACEMENT) + KRATOS_CHECK_VARIABLE_KEY(VELOCITY) + KRATOS_CHECK_VARIABLE_KEY(ACCELERATION) + + // Check that the element's nodes contain all required SolutionStepData and Degrees of freedom + for ( std::size_t i = 0; i < this->GetGeometry().size(); ++i ) { + Node<3>& rnode = this->GetGeometry()[i]; + + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(DISPLACEMENT,rnode) + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY,rnode) + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ACCELERATION,rnode) + + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_X,rnode) + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_Y,rnode) + KRATOS_CHECK_DOF_IN_NODE(DISPLACEMENT_Z,rnode) + } + + return 0; + + KRATOS_CATCH( "Problem in the Check in the TestElement" ) + } + + + //************************************************************************************// + //************************************************************************************// + + void TestElement::save( Serializer& rSerializer ) const + { + KRATOS_SERIALIZE_SAVE_BASE_CLASS( rSerializer, Element ) + } + + void TestElement::load( Serializer& rSerializer ) + { + KRATOS_SERIALIZE_LOAD_BASE_CLASS( rSerializer, Element ) + } + + } // Namespace Testing +} // Namespace Kratos + + diff --git a/kratos/tests/cpp_tests/auxiliar_files/test_element.h b/kratos/tests/cpp_tests/auxiliar_files/test_element.h new file mode 100644 index 000000000000..f559a25c5de9 --- /dev/null +++ b/kratos/tests/cpp_tests/auxiliar_files/test_element.h @@ -0,0 +1,331 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +#if !defined(KRATOS_TEST_ELEMENT_H_INCLUDED ) +#define KRATOS_TEST_ELEMENT_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "includes/element.h" + +namespace Kratos +{ + namespace Testing + { + ///@name Testing Globals + ///@{ + + ///@} + ///@name Type Definitions + ///@{ + + ///@} + ///@name Enum's + ///@{ + + ///@} + ///@name Functions + ///@{ + + ///@} + ///@name Testing Classes + ///@{ + + /** + * @class TestElement + * @ingroup KratosCore + * @brief This is simple test element + * @details It is designed to create a simple LHS and RHS in order to test strategies, processes. etc.... This way the common interface of the elements/conditions can be used to minimize the difference between the actual implementation and the test + * @author Vicente Mataix Ferrandiz + */ + class TestElement + : public Element + { + public: + + ///@name Type Definitions + ///@{ + /// Counted pointer of TestElement + KRATOS_CLASS_POINTER_DEFINITION( TestElement); + ///@} + + ///@name Enum's + ///@{ + + /** + * @brief This enum is used in order of differentiante + * @details If more implementations are added, add the corresponding enum + */ + enum class ResidualType {LINEAR = 0, NON_LINEAR = 1, ARC_LENGTH = 2}; + + ///@} + ///@name Life Cycle + ///@{ + + /** + * @brief Default constructor + * @param NewId the ID of the new element + * @param pGeometry the nodes of the new element + * @param TheResidualType The problem to be solved (linear, non-linear, arc-length ...) + */ + TestElement(IndexType NewId, GeometryType::Pointer pGeometry, const ResidualType TheResidualType = ResidualType::LINEAR); + + /** + * @brief Default constructor + * @param NewId The ID of the new element + * @param pGeometry The nodes of the new element + * @param pProperties The properties assigned to the new element + * @param TheResidualType The problem to be solved (linear, non-linear, arc-length ...) + */ + TestElement(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties, const ResidualType TheResidualType = ResidualType::LINEAR); + + ///Copy constructor + TestElement(TestElement const& rOther); + + /// Destructor. + ~TestElement() override; + + ///@} + ///@name Operators + ///@{ + + /// Assignment operator. + TestElement& operator=(TestElement const& rOther); + + ///@} + ///@name Operations + ///@{ + + /** + * @brief Creates a new total lagrangian updated element pointer + * @param NewId the ID of the new element + * @param ThisNodes the nodes of the new element + * @param pProperties the properties assigned to the new element + * @return a Pointer to the new element + */ + Element::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes, PropertiesType::Pointer pProperties) const override; + + /** + * @brief Clones the selected element variables, creating a new one + * @param NewId the ID of the new element + * @param ThisNodes the nodes of the new element + * @return a Pointer to the new element + */ + Element::Pointer Clone(IndexType NewId, NodesArrayType const& ThisNodes) const override; + + //************* GETTING METHODS + + /** + * @brief Sets on rElementalDofList the degrees of freedom of the considered element geometry + * @param rElementalDofList The vector containing the list of the DoFs + * @param rCurrentProcessInfo The current process info instance + */ + void GetDofList( + DofsVectorType& rElementalDofList, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief Sets on rResult the ID's of the element degrees of freedom + * @param rResult The vector containing the ids of the DoFs + * @param rCurrentProcessInfo The current process info instance + */ + void EquationIdVector( + EquationIdVectorType& rResult, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief Sets on rValues the nodal displacements + * @param rValues The vector containing the dofs values + * @param Step The time step computed (must be in the buffer) + */ + void GetValuesVector(Vector& rValues, int Step = 0) override; + + /** + * @brief Sets on rValues the nodal velocities + * @param rValues The vector containing the first derivatives + * @param Step The time step computed (must be in the buffer) + */ + void GetFirstDerivativesVector(Vector& rValues, int Step = 0) override; + + /** + * @brief Sets on rValues the nodal accelerations + * @param rValues The vector containing the second derivatives + * @param Step The time step computed (must be in the buffer) + */ + void GetSecondDerivativesVector(Vector& rValues, int Step = 0) override; + + //************* COMPUTING METHODS + + /** + * @brief This is called during the assembling process in order to calculate all elemental contributions to the global system matrix and the right hand side + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateLocalSystem( + MatrixType& rLeftHandSideMatrix, + VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This calculates just the RHS + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateRightHandSide( + VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This calculates just the LHS + * @param rLeftHandSideMatrix The elemental left hand side matrix + * @param rRightHandSideVector The elemental right hand side + * @param rCurrentProcessInfo The current process info instance + */ + + void CalculateLeftHandSide( + MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This is called during the assembling process in order to calculate the elemental mass matrix + * @param rMassMatrix the elemental mass matrix + * @param rCurrentProcessInfo the current process info instance + */ + void CalculateMassMatrix( + MatrixType& rMassMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This is called during the assembling process in order + * to calculate the elemental damping matrix + * @param rDampingMatrix The elemental damping matrix + * @param rCurrentProcessInfo The current process info instance + */ + void CalculateDampingMatrix( + MatrixType& rDampingMatrix, + ProcessInfo& rCurrentProcessInfo + ) override; + + /** + * @brief This function provides the place to perform checks on the completeness of the input. + * @details It is designed to be called only once (or anyway, not often) typically at the beginning of the calculations, so to verify that nothing is missing from the input or that no common error is found. + * @param rCurrentProcessInfo The current process info instance + */ + int Check(const ProcessInfo& rCurrentProcessInfo) override; + + ///@} + ///@name Access + ///@{ + ///@} + ///@name Inquiry + ///@{ + ///@} + ///@name Input and output + ///@{ + ///@} + ///@name Friends + ///@{ + ///@} + + protected: + ///@name Protected static Member Variables + ///@{ + ///@} + ///@name Protected member Variables + ///@{ + ///@} + + ResidualType mResidualType; + + ///@name Protected Operators + ///@{ + + TestElement() : Element() + { + } + + ///@} + ///@name Protected Operations + ///@{ + + ///@} + ///@name Protected Access + ///@{ + ///@} + ///@name Protected Inquiry + ///@{ + ///@} + ///@name Protected LifeCycle + ///@{ + ///@} + + private: + + ///@name Static Member Variables + ///@{ + ///@} + ///@name Member Variables + ///@{ + ///@} + ///@name Private Operators + ///@{ + ///@} + ///@name Private Operations + ///@{ + ///@} + ///@name Private Access + ///@{ + ///@} + ///@} + ///@name Serialization + ///@{ + + friend class Serializer; + + // A private default constructor necessary for serialization + + void save(Serializer& rSerializer) const override; + + void load(Serializer& rSerializer) override; + + ///@name Private Inquiry + ///@{ + ///@} + ///@name Un accessible methods + ///@{ + ///@} + + }; // Class TestElement + + ///@} + ///@name Type Definitions + ///@{ + ///@} + ///@name Input and output + ///@{ + ///@} + } // namespace Testing. +} // namespace Kratos. +#endif // KRATOS_TEST_ELEMENT_H_INCLUDED defined diff --git a/kratos/tests/cpp_tests/constitutive_laws/test_constitutive_law.cpp b/kratos/tests/cpp_tests/constitutive_laws/test_constitutive_law.cpp new file mode 100644 index 000000000000..4f10bab60f02 --- /dev/null +++ b/kratos/tests/cpp_tests/constitutive_laws/test_constitutive_law.cpp @@ -0,0 +1,83 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "includes/kratos_flags.h" +#include "includes/constitutive_law.h" + +namespace Kratos +{ + namespace Testing + { + /** + * Checks the correct work of the Has methods + */ + KRATOS_TEST_CASE_IN_SUITE(ConstitutiveLawHasMethods, KratosCoreFastSuite) + { + ConstitutiveLaw this_cl = ConstitutiveLaw(); + + KRATOS_CHECK_IS_FALSE(this_cl.Has(IS_RESTARTED)); // Bool + KRATOS_CHECK_IS_FALSE(this_cl.Has(DOMAIN_SIZE)); // Integer + KRATOS_CHECK_IS_FALSE(this_cl.Has(NODAL_H)); // Double + KRATOS_CHECK_IS_FALSE(this_cl.Has(DISPLACEMENT)); // Array 1D + KRATOS_CHECK_IS_FALSE(this_cl.Has(INITIAL_STRAIN)); // Vector + KRATOS_CHECK_IS_FALSE(this_cl.Has(GREEN_LAGRANGE_STRAIN_TENSOR)); // Matrix + } + + /** + * Checks the correct work of the GetStrainMeasure method + */ + KRATOS_TEST_CASE_IN_SUITE(ConstitutiveLawGetStrainMeasureMethod, KratosCoreFastSuite) + { + ConstitutiveLaw this_cl = ConstitutiveLaw(); + + KRATOS_CHECK_EQUAL(this_cl.GetStrainMeasure(), ConstitutiveLaw::StrainMeasure_Infinitesimal); + } + + /** + * Checks the correct work of the ValidateInput method + */ + KRATOS_TEST_CASE_IN_SUITE(ConstitutiveLawValidateInputMethod, KratosCoreFastSuite) + { + ConstitutiveLaw this_cl = ConstitutiveLaw(); + Properties prop = Properties(); + + KRATOS_CHECK_IS_FALSE(this_cl.ValidateInput(prop)); + } + + /** + * Checks the correct work of the IsIncremental method + */ + KRATOS_TEST_CASE_IN_SUITE(ConstitutiveLawIsIncrementalMethod, KratosCoreFastSuite) + { + ConstitutiveLaw this_cl = ConstitutiveLaw(); + + KRATOS_CHECK_IS_FALSE(this_cl.IsIncremental()); + } + + /** + * Checks the correct work of the GetStressMeasure method + */ + KRATOS_TEST_CASE_IN_SUITE(ConstitutiveLawGetStressMeasureMethod, KratosCoreFastSuite) + { + ConstitutiveLaw this_cl = ConstitutiveLaw(); + + KRATOS_CHECK_EQUAL(this_cl.GetStressMeasure(), ConstitutiveLaw::StressMeasure_PK1); + } + + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/containers/test_data_value_container.cpp b/kratos/tests/cpp_tests/containers/test_data_value_container.cpp new file mode 100644 index 000000000000..4c84e5562bb7 --- /dev/null +++ b/kratos/tests/cpp_tests/containers/test_data_value_container.cpp @@ -0,0 +1,80 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: +// kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "containers/data_value_container.h" +#include "includes/variables.h" +#include "testing/testing.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(DataValueContainerHas, KratosCoreFastSuite) { + DataValueContainer container; + double area = 0.0; + container.SetValue(NODAL_AREA, area); + const bool check_true = container.Has(NODAL_AREA); + const bool check_false = container.Has(DISPLACEMENT); + + KRATOS_CHECK_EQUAL(check_true, true); + KRATOS_CHECK_EQUAL(check_false, false); +} + +KRATOS_TEST_CASE_IN_SUITE(DataValueContainer, KratosCoreFastSuite) { + DataValueContainer container; + Vector original_distances(4); + original_distances[0] = 0.00; + original_distances[1] = 0.10; + original_distances[2] = 0.20; + original_distances[3] = 0.30; + container.SetValue(ELEMENTAL_DISTANCES, original_distances); + auto& distances = container.GetValue(ELEMENTAL_DISTANCES); + + for (std::size_t i = 0; i < distances.size(); i++) + KRATOS_CHECK_EQUAL(distances[i], original_distances[i]); +} + +KRATOS_TEST_CASE_IN_SUITE(DataValueContainerMerge, KratosCoreFastSuite) { + DataValueContainer container_origin; + DataValueContainer container_target; + + const double density = 1000.0; + const double viscosity_1 = 1e-3; + const double viscosity_2 = 2e-3; + + container_origin.SetValue(DENSITY, density); + container_origin.SetValue(VISCOSITY, viscosity_1); + container_target.SetValue(VISCOSITY, viscosity_2); + Flags options; + //First case: do not overwrite old values + options.Set(DataValueContainer::OVERWRITE_OLD_VALUES, false); + container_target.Merge(container_origin, options); + + KRATOS_CHECK_EQUAL(container_target.GetValue(DENSITY), density); + KRATOS_CHECK_EQUAL(container_target.GetValue(VISCOSITY), viscosity_2); + + //Second case: do overwrite old values + options.Set(DataValueContainer::OVERWRITE_OLD_VALUES, true); + container_target.Merge(container_origin, options); + KRATOS_CHECK_EQUAL(container_target.GetValue(DENSITY), density); + KRATOS_CHECK_EQUAL(container_target.GetValue(VISCOSITY), viscosity_1); + +} +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/containers/test_model.cpp b/kratos/tests/cpp_tests/containers/test_model.cpp new file mode 100644 index 000000000000..ad0771a12cda --- /dev/null +++ b/kratos/tests/cpp_tests/containers/test_model.cpp @@ -0,0 +1,128 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// +// + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(ModelGetModelPart, KratosCoreFastSuite) + { + Model model; + + auto& model_part = model.CreateModelPart("Main"); + + model_part.CreateSubModelPart("Inlet1"); + + + KRATOS_CHECK_EQUAL(model.GetModelPart("Main").Name(), model_part.Name()); + + ModelPart& smp = model_part.GetSubModelPart("Inlet1"); + KRATOS_CHECK_EQUAL(model.GetModelPart("Main.Inlet1").Name(), smp.Name()); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(model.GetModelPart("Main.Random"), + "Error: The ModelPart named : \"Random\" was not found as SubModelPart of : \"Main\". The total input string was \"Main.Random\""); + + // TODO this should throw in the future + // KRATOS_CHECK_EXCEPTION_IS_THROWN(model.GetModelPart("Inlet1"), + // "Error: The ModelPart named : \"Inlet1\" was not found as root-ModelPart. The total input string was \"Inlet1\""); + + KRATOS_CHECK_EXCEPTION_IS_THROWN( + model.GetModelPart("Maiiiiin"), + "Error: The ModelPart named : \"Maiiiiin\" was not found either as root-ModelPart or as a flat name. The total input string was \"Maiiiiin\""); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelHasModelPart, KratosCoreFastSuite) + { + Model model; + + auto& model_part = model.CreateModelPart("Main"); + + model_part.CreateSubModelPart("Inlet1"); + + + KRATOS_CHECK(model.HasModelPart("Main")); + KRATOS_CHECK(model.HasModelPart("Main.Inlet1")); + + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Inlet1")); + + ModelPart& smp = model_part.GetSubModelPart("Inlet1"); + smp.CreateSubModelPart("SubInlet"); + + KRATOS_CHECK(model.HasModelPart("Main.Inlet1.SubInlet")); + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main.SubInlet")); + + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Random")); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelDeleteModelPart, KratosCoreFastSuite) + { + Model model; + + auto& model_part = model.CreateModelPart("Main"); + model_part.CreateSubModelPart("Inlet1"); + model_part.GetSubModelPart("Inlet1").CreateSubModelPart("SubSub"); + + KRATOS_CHECK(model.HasModelPart("Main")); + KRATOS_CHECK(model.HasModelPart("Main.Inlet1")); + KRATOS_CHECK(model.HasModelPart("Main.Inlet1.SubSub")); + + model.DeleteModelPart("Main"); + + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main")); + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main.Inlet1")); + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main.Inlet1.SubSub")); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelRenameModelPart, KratosCoreFastSuite) + { + Model model; + + auto& model_part = model.CreateModelPart("Main"); + model_part.CreateSubModelPart("Inlet1"); + model_part.GetSubModelPart("Inlet1").CreateSubModelPart("SubSub"); + + KRATOS_CHECK(model.HasModelPart("Main")); + KRATOS_CHECK(model.HasModelPart("Main.Inlet1")); + KRATOS_CHECK(model.HasModelPart("Main.Inlet1.SubSub")); + + model.RenameModelPart("Main", "Renamed"); + + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main")); + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main.Inlet1")); + KRATOS_CHECK_IS_FALSE(model.HasModelPart("Main.Inlet1.SubSub")); + + KRATOS_CHECK(model.HasModelPart("Renamed")); + KRATOS_CHECK(model.HasModelPart("Renamed.Inlet1")); + KRATOS_CHECK(model.HasModelPart("Renamed.Inlet1.SubSub")); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelGetModel, KratosCoreFastSuite) + { + Model model; + + auto& model_part = model.CreateModelPart("Main"); + model_part.CreateSubModelPart("Inlet1"); + model_part.GetSubModelPart("Inlet1").CreateSubModelPart("SubSub"); + + KRATOS_CHECK(&model == &model_part.GetModel()); + + } + } // namespace Testing +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/containers/test_variables.cpp b/kratos/tests/cpp_tests/containers/test_variables.cpp new file mode 100644 index 000000000000..e6936c582915 --- /dev/null +++ b/kratos/tests/cpp_tests/containers/test_variables.cpp @@ -0,0 +1,64 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: +//kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "includes/variables.h" + +namespace Kratos { +namespace Testing { + +// This test is to check the hash function used in variable key, if it fails +// means that we should change the hash function. Pooyan. +KRATOS_TEST_CASE_IN_SUITE(VariablesKeyUniqueness, KratosCoreFastSuite) { + std::unordered_set registered_keys; + for (auto &i : KratosComponents::GetComponents()) { + auto hash = i.second->Key(); + if (registered_keys.find(hash) == registered_keys.end()) { + registered_keys.insert(hash); + } else { + KRATOS_ERROR << "Duplicated variables key founded for variable" << *(i.second) << std::endl; + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(VariablesKeyOrder, KratosCoreFastSuite) { + for(auto const& key_variable_pair : KratosComponents::GetComponents()){ + auto variable = key_variable_pair.second; + if(variable->IsNotComponent()){ + if(KratosComponents::Has(variable->Name() + "_X") && + KratosComponents::Has(variable->Name() + "_Y") && + KratosComponents::Has(variable->Name() + "_Z")){ + + auto const& variable_x = KratosComponents::Get(variable->Name() + "_X"); + auto const& variable_y = KratosComponents::Get(variable->Name() + "_Y"); + auto const& variable_z = KratosComponents::Get(variable->Name() + "_Z"); + if(variable_x.IsComponent() && variable_y.IsComponent() && variable_z.IsComponent()){ + KRATOS_CHECK_EQUAL(variable_x.Key() + 1, variable_y.Key()) << " for " << variable_x << " and " << variable_y << std::endl; + KRATOS_CHECK_EQUAL(variable_y.Key() + 1, variable_z.Key()) << " for " << variable_y << " and " << variable_z << std::endl; + } + } + } + } + +} + + +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/exceptions/test_exceptions.cpp b/kratos/tests/cpp_tests/exceptions/test_exceptions.cpp new file mode 100644 index 000000000000..ce3653781cb7 --- /dev/null +++ b/kratos/tests/cpp_tests/exceptions/test_exceptions.cpp @@ -0,0 +1,89 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "includes/exception.h" + +namespace Kratos +{ + namespace Testing + { + /// Tests + + /** Checks if CPP works as exception + * Checks if CPP works as exception + */ + + KRATOS_TEST_CASE_IN_SUITE(CPPExceptionTest, KratosCoreFastSuite) + { + try { + throw 1; + } catch (int e) { + KRATOS_CHECK_EQUAL(e, 1); + } catch (...) { + KRATOS_ERROR << std::endl; + } + } + + /** Checks if KRATOS_ERROR works as exception + * Checks if KRATOS_ERROR works as exception + */ + + KRATOS_TEST_CASE_IN_SUITE(KRATOS_ERRORTest, KratosCoreFastSuite) + { + try { + KRATOS_ERROR << std::endl; + } catch(Kratos::Exception& e){ + KRATOS_CHECK(true); + } catch (...) { + KRATOS_ERROR << "Default Exception"<< std::endl; + } + } + + /** Checks if KRATOS_ERROR_IF works as exception + * Checks if KRATOS_ERROR_IF works as exception + */ + + KRATOS_TEST_CASE_IN_SUITE(KRATOS_ERROR_IFTest, KratosCoreFastSuite) + { + try { + KRATOS_ERROR_IF(true) << std::endl; + } catch(Kratos::Exception& e){ + KRATOS_CHECK(true); + } catch (...) { + KRATOS_ERROR << "Default Exception"<< std::endl; + } + } + + /** Checks if KRATOS_ERROR_IF_NOT works as exception + * Checks if KRATOS_ERROR_IF_NOT works as exception + */ + + KRATOS_TEST_CASE_IN_SUITE(KRATOS_ERROR_IF_NOTTest, KratosCoreFastSuite) + { + try { + KRATOS_ERROR_IF_NOT(false) << std::endl; + } catch(Kratos::Exception& e){ + KRATOS_CHECK(true); + } catch (...) { + KRATOS_ERROR << "Default Exception"<< std::endl; + } + } + + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/geometries/cross_check_shape_functions_values.h b/kratos/tests/cpp_tests/geometries/cross_check_shape_functions_values.h new file mode 100644 index 000000000000..f6976a018864 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/cross_check_shape_functions_values.h @@ -0,0 +1,32 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// +// + +#if !defined(KRATOS_CROSS_CHECK_SHAPE_FUNCTIONS_VALUES_H_INCLUDED) +#define KRATOS_CROSS_CHECK_SHAPE_FUNCTIONS_VALUES_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "geometries/geometry.h" +#include "includes/node.h" +#include "includes/ublas_interface.h" + +namespace Kratos { +namespace Testing { +void CrossCheckShapeFunctionsValues(Geometry> const& rGeom); +} +} + +#endif // KRATOS_CROSS_CHECK_SHAPE_FUNCTIONS_VALUES_H_INCLUDED defined diff --git a/kratos/tests/cpp_tests/geometries/test_geometry.cpp b/kratos/tests/cpp_tests/geometries/test_geometry.cpp new file mode 100644 index 000000000000..544903510b01 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_geometry.cpp @@ -0,0 +1,388 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig +// Vicente Mataix Ferrandiz +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/geometry.h" +#include "tests/cpp_tests/geometries/test_geometry.h" + +namespace Kratos { +namespace Testing { + + /// Auxiliar check functions (from geometry_tester.h) + /// - All this functions should probably me moved somewhere else. + + /** Gets the corresponding string of the integration method provided. + * Gets the corresponding string of the integration method provided. + * @param ThisGeometry Geometry that is used for nothing + * @param ThisMethod Input Integration method + * @return String with the name of the input integration method + */ + std::string GetIntegrationName( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ) + { + switch(ThisMethod) { + case GeometryData::GI_GAUSS_1 : + return "GI_GAUSS_1"; + case GeometryData::GI_GAUSS_2 : + return "GI_GAUSS_2"; + case GeometryData::GI_GAUSS_3 : + return "GI_GAUSS_3"; + case GeometryData::GI_GAUSS_4 : + return "GI_GAUSS_4"; + case GeometryData::GI_GAUSS_5 : + return "GI_GAUSS_5"; + case GeometryData::GI_EXTENDED_GAUSS_1 : + return "GI_EXTENDED_GAUSS_1"; + case GeometryData::GI_EXTENDED_GAUSS_2 : + return "GI_EXTENDED_GAUSS_2"; + case GeometryData::GI_EXTENDED_GAUSS_3 : + return "GI_EXTENDED_GAUSS_3"; + case GeometryData::GI_EXTENDED_GAUSS_4 : + return "GI_EXTENDED_GAUSS_4"; + case GeometryData::GI_EXTENDED_GAUSS_5 : + return "GI_EXTENDED_GAUSS_5"; + case GeometryData::NumberOfIntegrationMethods : + return "NumberOfIntegrationMethods"; + }; + + return "UnknownIntegrationMethod"; + } + + /** Gets the corresponding string of the geometry name. + * Gets the corresponding string of the geometry name. + * @param ThisGeometry Input Geometry + * @return String corresponding to the name of the input geometry + */ + std::string GetGeometryName(GeometryType& ThisGeometry) + { + GeometryData::KratosGeometryType geom_type = ThisGeometry.GetGeometryType(); + + switch(geom_type) { + case GeometryData::Kratos_generic_type : + return "Kratos_generic_type"; + case GeometryData::Kratos_Hexahedra3D20 : + return "Kratos_Hexahedra3D20"; + case GeometryData::Kratos_Hexahedra3D27 : + return "Kratos_Hexahedra3D27"; + case GeometryData::Kratos_Hexahedra3D8 : + return "Kratos_Hexahedra3D8"; + case GeometryData::Kratos_Prism3D15 : + return "Kratos_Prism3D15"; + case GeometryData::Kratos_Prism3D6 : + return "Kratos_Prism3D6"; + case GeometryData::Kratos_Quadrilateral2D4 : + return "Kratos_Quadrilateral2D4"; + case GeometryData::Kratos_Quadrilateral2D8 : + return "Kratos_Quadrilateral2D8"; + case GeometryData::Kratos_Quadrilateral2D9 : + return "Kratos_Quadrilateral2D9"; + case GeometryData::Kratos_Quadrilateral3D4 : + return "Kratos_Quadrilateral3D4"; + case GeometryData::Kratos_Quadrilateral3D8 : + return "Kratos_Quadrilateral3D8"; + case GeometryData::Kratos_Quadrilateral3D9 : + return "Kratos_Quadrilateral3D9"; + case GeometryData::Kratos_Tetrahedra3D10 : + return "Kratos_Tetrahedra3D10"; + case GeometryData::Kratos_Tetrahedra3D4 : + return "Kratos_Tetrahedra3D4"; + case GeometryData::Kratos_Triangle2D3 : + return "Kratos_Triangle3D3"; + case GeometryData::Kratos_Triangle2D6 : + return "Kratos_Triangle2D6"; + case GeometryData::Kratos_Triangle3D3 : + return "Kratos_Triangle3D3"; + case GeometryData::Kratos_Triangle3D6 : + return "Kratos_Triangle3D6"; + case GeometryData::Kratos_Line2D2 : + return "Kratos_Line2D2"; + case GeometryData::Kratos_Line2D3 : + return "Kratos_Line2D3"; + case GeometryData::Kratos_Line3D2 : + return "Kratos_Line3D2"; + case GeometryData::Kratos_Line3D3 : + return "Kratos_Line3D3"; + case GeometryData::Kratos_Point2D : + return "Kratos_Point2D"; + case GeometryData::Kratos_Point3D : + return "Kratos_Point3D"; + case GeometryData::Kratos_Sphere3D1 : + return "Kratos_Sphere3D1"; + }; + + return "UnknownGeometry"; + } + + /** Computes the linear strain matrix. + * Computes the linear strain matrix which is useful to verify that + * a constant strain can be correctly reproduced + * @param B [description] + * @param DN_DX [description] + * @param NumberOfNodes Number of nodes of the geometry + * @param Dimension Dimension (i.e. 1, 2 or 3) + */ + void CalculateB( + Matrix& B, + Matrix& DN_DX, + const SizeType NumberOfNodes, + const SizeType Dimension + ) + { + if(Dimension == 2) { + B.resize(3, 2*NumberOfNodes, false); + } else { + B.resize(6, 3*NumberOfNodes, false); + } + + for(SizeType i = 0; i < NumberOfNodes; i++) { + SizeType index = Dimension * i; + + if(Dimension == 2) { + B(0, index + 0) = DN_DX(i, 0); + B(0, index + 1) = 0.0; + + B(1, index + 0) = 0.0; + B(1, index + 1) = DN_DX(i, 1); + + B(2, index + 0) = DN_DX(i, 1); + B(2, index + 1) = DN_DX(i, 0); + } else { + B(0, index + 0) = DN_DX(i, 0); + B(0, index + 1) = 0.0; + B(0, index + 2) = 0.0; + + B(1, index + 0) = 0.0; + B(1, index + 1) = DN_DX(i, 1); + B(1, index + 2) = 0.0; + + B(2, index + 0) = 0.0; + B(2, index + 1) = 0.0; + B(2, index + 2) = DN_DX(i, 2); + + B(3, index + 0) = DN_DX(i, 1); + B(3, index + 1) = DN_DX(i, 0); + B(3, index + 2) = 0.0; + + B(4, index + 0) = 0.0; + B(4, index + 1) = DN_DX(i, 2); + B(4, index + 2) = DN_DX(i, 1); + + B(5, index + 0) = DN_DX(i, 2); + B(5, index + 1) = 0.0; + B(5, index + 2) = DN_DX(i, 0); + } + } + } + + /** Verifies the area of the ThisGeometryetry using the integration method. + * Verifies the area of the ThisGeometryetry using the integration method. + * @param ThisGeometry Geometry to be tested + * @param ThisMethod Integration method used + * @param reference_area Expected area + * @param error_msg Buffer to write the error message + * @return Area claculated using the selected integration method. + */ + double CalculateAreaByIntegration( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ) + { + double area = 0.0; + + if(ThisGeometry.WorkingSpaceDimension() != ThisGeometry.LocalSpaceDimension()) { + KRATOS_ERROR << "VerifyStrainExactness can not be used if LocalSpaceDimension and WorkingSpaceDimension do not coincide --> ThisGeometryetry is " << GetGeometryName(ThisGeometry) << std::endl; + } + + const Element::GeometryType::IntegrationPointsArrayType& integration_points = ThisGeometry.IntegrationPoints( ThisMethod ); + + if(integration_points.size() == 0) { + KRATOS_ERROR << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " -- the integration method is not supported " << std::endl; + } + + // Resizing jacobian inverses containers + Matrix InvJ0(ThisGeometry.WorkingSpaceDimension(), ThisGeometry.WorkingSpaceDimension()); + + Element::GeometryType::JacobiansType J0; + J0 = ThisGeometry.Jacobian( J0, ThisMethod ); + + Vector determinants; + ThisGeometry.DeterminantOfJacobian(determinants, ThisMethod); + + for(SizeType PointNumber = 0; PointNumber < integration_points.size(); PointNumber++) { + const double IntegrationWeight = integration_points[PointNumber].Weight(); + + // Calculating and storing inverse of the jacobian and the parameters needed + double DetJ0 = MathUtils::Det( J0[PointNumber] ); + + KRATOS_ERROR_IF( std::abs(determinants[PointNumber] - DetJ0)/std::abs(DetJ0) > 1e-13) << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " --> " << " determinant as computed from DeterminantOfJacobian does not match the value computed by taking the determinant of J " << std::endl; + + // Calculating the total area + area += DetJ0 * IntegrationWeight; + } + + return area; + } + + /** Verifies that a displacement field produces the expected strain distribution. + * Verifies that a displacement field which varies linearly in space, produces the expected strain distribution. + * This shall be considered a test for shape function derivatives + * @param ThisGeometry Geometry to be tested + * @param ThisMethod Integration method used + * @param error_msg Buffer to write the error message + */ + void VerifyStrainExactness( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ) + { + const Element::GeometryType::IntegrationPointsArrayType& integration_points = ThisGeometry.IntegrationPoints( ThisMethod ); + const SizeType NumberOfNodes = ThisGeometry.PointsNumber(); + const SizeType dim = ThisGeometry.WorkingSpaceDimension(); + + if(dim != ThisGeometry.LocalSpaceDimension()) { + KRATOS_THROW_ERROR(std::logic_error,"VerifyStrainExactness can not be used if LocalSpaceDimension and WorkingSpaceDimension do not coincide ",GetGeometryName(ThisGeometry) ); + } + + if(integration_points.size() == 0) { + KRATOS_ERROR << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " -- the integration method is not supported " << std::endl; + } else { + // Charlie: Shouldn't this be initialized for dim = 1? + SizeType strain_size = 1; + + if(dim == 2) { + strain_size = 3; + } else { + strain_size = 6; + } + + // Definition of the expected strain + Matrix MatrixA(dim,dim); + Vector VectorB(dim); + + for(SizeType i=0; i1e-14) { + KRATOS_ERROR << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " --> " << " error: shape functions do not sum to 1 on gauss point" << std::endl; + } + + // Calculating and storing inverse of the jacobian and the parameters needed + MathUtils::InvertMatrix( J0[PointNumber], InvJ0, DetJ0 ); + DN_DX = prod( DN_De[PointNumber], InvJ0 ); + + // Check that the shape function gradients as obtained from the ThisGeometryety match what is obtained here starting from the local_gradients + if(norm_frobenius(DN_DX_ThisGeometry[PointNumber] - DN_DX)/norm_frobenius(DN_DX) > 1e-13) { + KRATOS_ERROR << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " --> " << std::endl; + KRATOS_ERROR << " error: shape function gradients are wrongly calculated in function ShapeFunctionsIntegrationPointsGradients: DN_DX_ThisGeometry " << DN_DX_ThisGeometry[PointNumber] << " vs " << DN_DX << std::endl; + KRATOS_ERROR << " norm_frobenius(DN_DX_ThisGeometry[PointNumber] - DN_DX)/norm_frobenius(DN_DX) = " << norm_frobenius(DN_DX_ThisGeometry[PointNumber] - DN_DX)/norm_frobenius(DN_DX) < 1e-13) { + KRATOS_ERROR << "Geometry Type = " << GetGeometryName(ThisGeometry) << " - IntegrationMethod = " << GetIntegrationName(ThisGeometry,ThisMethod) << " --> " << std::endl; + KRATOS_ERROR << " error: shape function gradients are wrongly calculated in function ShapeFunctionsIntegrationPointsGradients: DN_DX_ThisGeometry " << DN_DX_ThisGeometry[PointNumber] << " vs " << DN_DX << std::endl; + KRATOS_ERROR << " norm_frobenius(Jinv[PointNumber] - InvJ0)/norm_frobenius(InvJ0) = " << norm_frobenius(Jinv[PointNumber] - InvJ0)/norm_frobenius(InvJ0) <& coords = ThisGeometry[i].Coordinates(); + Vector disp(dim); + + for(SizeType k=0; k " << " error: expected strain found was not correctly recovered on gauss point. recovered strain = " << strain << " expected value " << expected_strain << std::endl; + } + } + + KRATOS_CHECK(succesful); + } + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_geometry.h b/kratos/tests/cpp_tests/geometries/test_geometry.h new file mode 100644 index 000000000000..49e420a75734 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_geometry.h @@ -0,0 +1,123 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig +// Vicente Mataix Ferrandiz +// Riccardo Rossi +// +// + +#if !defined(KRATOS_TEST_GEOMETRY_H_INCLUDED) +#define KRATOS_TEST_GEOMETRY_H_INCLUDED + +// System includes +#include + +// External includes + +// Project includes +#include "includes/node.h" +#include "includes/element.h" +#include "testing/testing.h" +#include "geometries/geometry.h" + +namespace Kratos { +namespace Testing { + + // Adding some typedef + typedef Node<3> NodeType; + typedef Geometry GeometryType; + typedef std::size_t SizeType; + typedef std::size_t IndexType; + + constexpr double EPSILON = std::numeric_limits::epsilon(); + constexpr double TOLERANCE = 1e-6; + + /// Factory functions + + /** Generates a point. + * Generates a point. If no coordinates are provided, random ones between 0 and 1 are selected. + * Coordinate Z is forced to 0 for 2D element tests. + * @param coordx Coordinate X + * @param coordy Coordinate Y + * @return A point with coordinates coordx, coordy + */ + template + typename TPointType::Pointer GeneratePoint( + double coordx = (((double) std::rand() / (RAND_MAX)) + 1), + double coordy = (((double) std::rand() / (RAND_MAX)) + 1), + double coordz = (((double) std::rand() / (RAND_MAX)) + 1)) { + static int id = 0; + return typename TPointType::Pointer(new TPointType(id++, coordx, coordy, coordz)); + } + + /// Auxiliar check functions (from geometry_tester.h) + /// - All this functions should probably me moved somewhere else. + + /** Gets the corresponding string of the integration method provided. + * Gets the corresponding string of the integration method provided. + * @param ThisGeometry Geometry that is used for nothing + * @param ThisMethod Input Integration method + * @return String with the name of the input integration method + */ + std::string GetIntegrationName( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ); + + /** Gets the corresponding string of the geometry name. + * Gets the corresponding string of the geometry name. + * @param ThisGeometry Input Geometry + * @return String corresponding to the name of the input geometry + */ + std::string GetGeometryName(GeometryType& geom); + + /** Computes the linear strain matrix. + * Computes the linear strain matrix which is useful to verify that + * a constant strain can be correctly reproduced + * @param B [description] + * @param DN_DX [description] + * @param NumberOfNodes Number of nodes of the geometry + * @param Dimension Dimension (i.e. 1, 2 or 3) + */ + void CalculateB( + Matrix& B, + Matrix& DN_DX, + const SizeType NumberOfNodes, + const SizeType Dimension + ); + + /** Verifies the area of the geometry using the integration method. + * Verifies the area of the geometry using the integration method. + * @param ThisGeometry Geometry to be tested + * @param ThisMethod Integration method used + * @param reference_area Expected area + * @param error_msg Buffer to write the error message + * @return Area claculated using the selected integration method. + */ + double CalculateAreaByIntegration( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ); + + /** Verifies that a displacement field produces the expected strain distribution. + * Verifies that a displacement field which varies linearly in space, produces the expected strain distribution. + * This shall be considered a test for shape function derivatives + * @param ThisGeometry Geometry to be tested + * @param ThisMethod Integration method used + * @param error_msg Buffer to write the error message + */ + void VerifyStrainExactness( + GeometryType& ThisGeometry, + GeometryType::IntegrationMethod ThisMethod + ); +} +} + +#endif // KRATOS_TEST_GEOMETRY_H_INCLUDED defined diff --git a/kratos/tests/cpp_tests/geometries/test_hexahedra_3d_8.cpp b/kratos/tests/cpp_tests/geometries/test_hexahedra_3d_8.cpp new file mode 100644 index 000000000000..a89039a14712 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_hexahedra_3d_8.cpp @@ -0,0 +1,278 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Bodhinanda Chandra +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/hexahedra_3d_8.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +namespace Kratos { + namespace Testing { + + typedef Node<3> PointType; + typedef Node<3>::Pointer PointPtrType; + typedef Hexahedra3D8 HexaGeometryType; + typedef HexaGeometryType::Pointer HexaGeometryPtrType; + + /** Generates a sample Hexahedra3D8. + * Generates a hexahedra defined by eight random points in the space. + * @return Pointer to a Hexahedra3D8 + */ + HexaGeometryPtrType GenerateHexahedra3D8( + PointPtrType PointA = GeneratePoint(), + PointPtrType PointB = GeneratePoint(), + PointPtrType PointC = GeneratePoint(), + PointPtrType PointD = GeneratePoint(), + PointPtrType PointE = GeneratePoint(), + PointPtrType PointF = GeneratePoint(), + PointPtrType PointG = GeneratePoint(), + PointPtrType PointH = GeneratePoint()) { + return HexaGeometryPtrType(new HexaGeometryType(PointA, PointB, PointC, PointD, PointE, PointF, PointG, PointH)); + } + + /** Generates a sample Hexahedra3D8. + * Generates a hexahedra with center on the origin with positive volume and side 1. + * @return Pointer to a Hexahedra3D8 + */ + HexaGeometryPtrType GenerateOriginCenterLen1Hexahedra3D8() { + return HexaGeometryPtrType(new HexaGeometryType( + GeneratePoint(-0.5, -0.5, -0.5), + GeneratePoint( 0.5, -0.5, -0.5), + GeneratePoint( 0.5, 0.5, -0.5), + GeneratePoint(-0.5, 0.5, -0.5), + GeneratePoint(-0.5, -0.5, 0.5), + GeneratePoint( 0.5, -0.5, 0.5), + GeneratePoint( 0.5, 0.5, 0.5), + GeneratePoint(-0.5, 0.5, 0.5) + )); + } + + /** Generates a sample Hexahedra3D8. + * Generates a hexahedra with center on the origin with positive volume and side 2. + * @return Pointer to a Hexahedra3D8 + */ + HexaGeometryPtrType GenerateOriginCenterLen2Hexahedra3D8() { + return HexaGeometryPtrType(new HexaGeometryType( + GeneratePoint(-1.0, -1.0, -1.0), + GeneratePoint( 1.0, -1.0, -1.0), + GeneratePoint( 1.0, 1.0, -1.0), + GeneratePoint(-1.0, 1.0, -1.0), + GeneratePoint(-1.0, -1.0, 1.0), + GeneratePoint( 1.0, -1.0, 1.0), + GeneratePoint( 1.0, 1.0, 1.0), + GeneratePoint(-1.0, 1.0, 1.0) + )); + } + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geomRegLen1 = GenerateOriginCenterLen1Hexahedra3D8(); + auto geomRegLen2 = GenerateOriginCenterLen2Hexahedra3D8(); + + KRATOS_CHECK_EQUAL(geomRegLen1->EdgesNumber(), 12); + KRATOS_CHECK_EQUAL(geomRegLen2->EdgesNumber(), 12); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8FacesNumber, KratosCoreGeometriesFastSuite) { + auto geomRegLen1 = GenerateOriginCenterLen1Hexahedra3D8(); + auto geomRegLen2 = GenerateOriginCenterLen2Hexahedra3D8(); + + KRATOS_CHECK_EQUAL(geomRegLen1->FacesNumber(), 6); + KRATOS_CHECK_EQUAL(geomRegLen2->FacesNumber(), 6); + } + + /** Checks if the characteristic length of the hexahedra is calculated correctly. + * Checks if the characteristic length of the hexahedra is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8Length, KratosCoreGeometriesFastSuite) { + auto geomRegLen1 = GenerateOriginCenterLen1Hexahedra3D8(); + auto geomRegLen2 = GenerateOriginCenterLen2Hexahedra3D8(); + + KRATOS_CHECK_NEAR(geomRegLen1->Length(), 0.353553, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Length(), 1.000000, TOLERANCE); + } + + /** Checks if the area of the hexahedra is calculated correctly. + * Checks if the area of the hexahedra is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8Area, KratosCoreGeometriesFastSuite) { + auto geomRegLen1 = GenerateOriginCenterLen1Hexahedra3D8(); + auto geomRegLen2 = GenerateOriginCenterLen2Hexahedra3D8(); + + KRATOS_CHECK_NEAR(geomRegLen1->Area(), 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Area(), 8.0, TOLERANCE); + } + + /** Checks if the volume of the hexahedra is calculated correctly. + * Checks if the volume of the hexahedra is calculated correctly. + * For hexahedra 3D8 'volume()' call defaults to 'area()' + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8Volume, KratosCoreGeometriesFastSuite) { + auto geomRegLen1 = GenerateOriginCenterLen1Hexahedra3D8(); + auto geomRegLen2 = GenerateOriginCenterLen2Hexahedra3D8(); + + KRATOS_CHECK_NEAR(geomRegLen1->Volume(), 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Volume(), 8.0, TOLERANCE); + } + + /** + * This test performs the check of the box intersection method + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8BoxIntersection, KratosCoreGeometriesFastSuite) { + auto hexahedron = GenerateOriginCenterLen1Hexahedra3D8(); + + //hexahedron inside the box + KRATOS_CHECK(hexahedron->HasIntersection(Point(-0.6,-0.6,-0.6), Point(0.6,0.6,0.6))); + + //hexahedron contains the box + KRATOS_CHECK(hexahedron->HasIntersection(Point(-.25,-.25,-.25), Point(.25,.25,.25))); + + //hexahedron intersects the box + KRATOS_CHECK(hexahedron->HasIntersection(Point(.25,.25,.25), Point(1.0,1.0,1.0))); + + //hexahedron not intersects the box + KRATOS_CHECK_IS_FALSE(hexahedron->HasIntersection(Point(.51,.51,.51), Point(1.1,1.1,1.1))); + } + + /** Checks the inside test for a given point respect to the hexahedra + * Checks the inside test for a given point respect to the hexahedra + * It performs 4 tests: + * A Point inside the hexahedra: Expected result TRUE + * A Point outside the hexahedra: Expected result FALSE + * A Point over a vertex of the hexahedra: Expected result TRUE + * A Point over an edge of the hexahedra: Expected result TRUE + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateOriginCenterLen1Hexahedra3D8(); + + Point PointInside(0.4999, 0.4999, 0.4999); + Point PointOutside(0.5001, 0.5001, 0.5001); + Point PointInVertex(-0.5, -0.5, -0.5); + Point PointInEdge(0.5, 0.5, 0.0); + + Point LocalCoords; + + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + /** Checks the point local coordinates for a given point respect to the + * hexahedra. The baricentre of the hexahedra is selected due to its known + * solution. + */ + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GenerateOriginCenterLen2Hexahedra3D8(); + + // Compute the global coordinates of the baricentre + auto points = geom->Points(); + Point baricentre = points[0] + points[1] + points[2] + points[3] + points[4] + points[5] + points[6] + points[7]; + baricentre /= 8.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords; + geom->PointLocalCoordinates(baricentre_local_coords, baricentre); + + KRATOS_CHECK_NEAR(baricentre_local_coords(0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(1), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(2), 0.0, TOLERANCE); + + Point baricentre_face_1; + baricentre_face_1.Coordinates()[0] = 1.0; + baricentre_face_1.Coordinates()[1] = 0.0; + baricentre_face_1.Coordinates()[2] = 0.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_1; + geom->PointLocalCoordinates(baricentre_local_coords_face_1, baricentre_face_1); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(0), 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(1), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(2), 0.0, TOLERANCE); + + Point baricentre_face_2; + baricentre_face_2.Coordinates()[0] = 0.0; + baricentre_face_2.Coordinates()[1] = -1.0; + baricentre_face_2.Coordinates()[2] = 0.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_2; + geom->PointLocalCoordinates(baricentre_local_coords_face_2, baricentre_face_2); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(1),-1.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(2), 0.0, TOLERANCE); + + Point baricentre_face_3; + baricentre_face_3.Coordinates()[0] = 0.0; + baricentre_face_3.Coordinates()[1] = 0.3; + baricentre_face_3.Coordinates()[2] = 1.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_3; + geom->PointLocalCoordinates(baricentre_local_coords_face_3, baricentre_face_3); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(1), 0.3, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(2), 1.0, TOLERANCE); + + Point outside_point; + outside_point.Coordinates()[0] = 1.0; + outside_point.Coordinates()[1] = 1.0; + outside_point.Coordinates()[2] = 1.0; + + // Compute the baricentre local coordinates + array_1d local_coords_outside_point; + geom->PointLocalCoordinates(local_coords_outside_point, outside_point); + + KRATOS_CHECK_NEAR(local_coords_outside_point(0), 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(local_coords_outside_point(1), 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(local_coords_outside_point(2), 1.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateOriginCenterLen2Hexahedra3D8(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 1.0 / 16.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.0439453125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.1318359375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.2197265625, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.0732421875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(4, coord), 0.0498046875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(5, coord), 0.1494140625, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(6, coord), 0.2490234375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(7, coord), 0.0830078125, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Hexahedra3D8ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateOriginCenterLen2Hexahedra3D8(); + TestAllShapeFunctionsLocalGradients(*geom); + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_line_2d_2.cpp b/kratos/tests/cpp_tests/geometries/test_line_2d_2.cpp new file mode 100644 index 000000000000..e2478c28b84d --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_line_2d_2.cpp @@ -0,0 +1,143 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Aditya Ghantasala +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/line_2d_2.h" +#include "tests/cpp_tests/geometries/test_geometry.h" + + +// Utility includes +#include "utilities/geometry_utilities.h" + +namespace Kratos { +namespace Testing { + + /// Factory functions + + /** Generates a point type sample Line2D2N + * @return Pointer to a Line2D2N + */ + Line2D2::Pointer GeneratePointsUnitXDirectionLine2D2() { + return Line2D2::Pointer(new Line2D2( + Point::Pointer(new Point(0.0, 0.0, 0.0)), + Point::Pointer(new Point(1.0, 0.0, 0.0)) + )); + } + + /** Generates a point type sample Line2D2N + * @return Pointer to a Line2D2N + */ + Line2D2::Pointer GeneratePointsUnitYDirectionLine2D2() { + return Line2D2::Pointer(new Line2D2( + Point::Pointer(new Point(0.0, 0.0, 0.0)), + Point::Pointer(new Point(0.0, 1.0, 0.0)) + )); + } + /** Generates a point type sample Line2D2N. + * @return Pointer to a Line2D2N + */ + Line2D2::Pointer GenerateLine2D2WithPoints(Point::Pointer rPointOne, Point::Pointer rPointTwo ) { + return Line2D2::Pointer(new Line2D2(rPointOne, rPointTwo)); + } + + + /** + * Test an overlaping box and line (line has only one node in the box) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2XIntersectionBoxSingleNodeInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitXDirectionLine2D2(); + Point point_1(0.5, -0.1, 0.0); + Point point_2(1.5, 0.1, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + KRATOS_TEST_CASE_IN_SUITE(Line2D2YIntersectionBoxSingleNodeInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitYDirectionLine2D2(); + Point point_1(-0.1, 0.5, 0.0); + Point point_2(0.1, 1.5, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test an overlaping box and line (line has both nodes in the box) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2XIntersectionBoxTwoNodesInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitXDirectionLine2D2(); + Point point_1(-0.5, -0.1, 0.0); + Point point_2(1.5, 0.1, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + KRATOS_TEST_CASE_IN_SUITE(Line2D2YIntersectionBoxTwoNodesInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitYDirectionLine2D2(); + Point point_1(-0.1, -0.5, 0.0); + Point point_2(0.1, 1.5, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test an intersection with another line + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2IntersectionWithAnotherLine, KratosCoreGeometriesFastSuite) { + auto geom_1 = GeneratePointsUnitXDirectionLine2D2(); + Point::Pointer point_1 = Point::Pointer(new Point(0.5, 0.5, 0.0)); + Point::Pointer point_2 = Point::Pointer(new Point(0.5, -0.5, 0.0)); + auto geom_2 = GenerateLine2D2WithPoints(point_1, point_2); + KRATOS_CHECK(geom_1->HasIntersection(*geom_2)); + } + + /** + * Test an intersection with another parallel line + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2IntersectionWithAnotherParallelLine, KratosCoreGeometriesFastSuite) { + auto geom_1 = GeneratePointsUnitXDirectionLine2D2(); + Point::Pointer point_1 = Point::Pointer(new Point(0.0, 0.5, 0.0)); + Point::Pointer point_2 = Point::Pointer(new Point(0.5, 0.5, 0.0)); + auto geom_2 = GenerateLine2D2WithPoints(point_1, point_2); + KRATOS_CHECK_IS_FALSE(geom_1->HasIntersection(*geom_2)); + } + + /** + * Test a box inside a line HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2IntersectionBoxInsideX, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitXDirectionLine2D2(); + Point point_1(0.25, -0.1, 0.0); + Point point_2(0.75, 0.1, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test a box inside a line HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2IntersectionBoxInsideY, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitYDirectionLine2D2(); + Point point_1(-0.1,0.25, 0.0); + Point point_2(0.1, 0.75, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + /** + * Test a non overlaping box HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Line2D2NoIntersectionBox, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsUnitXDirectionLine2D2(); + Point point_1(1, 1, 0.0); + Point point_2(2, 2, 0.0); + KRATOS_CHECK_IS_FALSE(geom->HasIntersection(point_1, point_2)); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_non_rectangular_jacobian.cpp b/kratos/tests/cpp_tests/geometries/test_non_rectangular_jacobian.cpp new file mode 100644 index 000000000000..d3c0b0703f5f --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_non_rectangular_jacobian.cpp @@ -0,0 +1,112 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "geometries/geometry.h" +#include "geometries/line_2d_2.h" +#include "geometries/triangle_3d_3.h" +#include "geometries/quadrilateral_3d_4.h" + +// Utility includes +#include "utilities/math_utils.h" + +namespace Kratos +{ + namespace Testing + { + ///@} + ///@name Type Definitions + ///@{ + + typedef GeometryData::IntegrationMethod IntegrationMethod; + + /// Tests + + /** Checks if the area of the triangle is calculated correctly using Heron equation. + * Checks if the area of the triangle is calculated correctly using Heron equation. + */ + + KRATOS_TEST_CASE_IN_SUITE(LineJacobianTest, KratosNonRectangularJacobianFastSuite) + { + Node<3>::Pointer PointA = GeneratePoint>(); + Node<3>::Pointer PointB = GeneratePoint>(); + + auto geom = Line2D2>(PointA,PointB); + + IntegrationMethod ThisMethod = geom.GetDefaultIntegrationMethod(); + + Matrix jacobian ( 2, 1 ); + + geom.Jacobian( jacobian, 0, ThisMethod); + + const double detJ = geom.DeterminantOfJacobian(0, ThisMethod); + + KRATOS_CHECK_NEAR(detJ, MathUtils::GeneralizedDet(jacobian), TOLERANCE); + } + + /** Checks if it gives you the absolute value of a given value + * Checks if It gives you the absolute value of a given value + */ + + KRATOS_TEST_CASE_IN_SUITE(TriangleJacobianTest, KratosNonRectangularJacobianFastSuite) + { + Node<3>::Pointer PointA = GeneratePoint>(); + Node<3>::Pointer PointB = GeneratePoint>(); + Node<3>::Pointer PointC = GeneratePoint>(); + + auto geom = Triangle3D3>(PointA,PointB,PointC); + + IntegrationMethod ThisMethod = geom.GetDefaultIntegrationMethod(); + + Matrix jacobian ( 3, 2 ); + + geom.Jacobian( jacobian, 0, ThisMethod); + + const double detJ = geom.DeterminantOfJacobian(0, ThisMethod); + + KRATOS_CHECK_NEAR(detJ, MathUtils::GeneralizedDet(jacobian), TOLERANCE); + } + + /** Checks if it gives you the minimum value of a given value + * Checks if It gives you the minimum value of a given value + */ + + KRATOS_TEST_CASE_IN_SUITE(QuadrilateralJacobianTest, KratosNonRectangularJacobianFastSuite) + { + Node<3>::Pointer PointA = Node<3>::Pointer(new Node<3>(1, 0.1, 0.2, 0.3)); + Node<3>::Pointer PointB = Node<3>::Pointer(new Node<3>(2, 0.4, 0.25, 0.35)); + Node<3>::Pointer PointC = Node<3>::Pointer(new Node<3>(3, 0.4, 0.55, 0.3)); + Node<3>::Pointer PointD = Node<3>::Pointer(new Node<3>(4, 0.15, 0.45, 0.45)); + + auto geom = Quadrilateral3D4>(PointA,PointB,PointC,PointD); + + IntegrationMethod ThisMethod = geom.GetDefaultIntegrationMethod(); + + Matrix jacobian ( 3, 2 ); + + geom.Jacobian( jacobian, 0, ThisMethod); + + const double detJ = geom.DeterminantOfJacobian(0, ThisMethod); + + KRATOS_CHECK_NEAR(detJ, MathUtils::GeneralizedDet(jacobian), TOLERANCE); + } + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/geometries/test_prism_3d_6.cpp b/kratos/tests/cpp_tests/geometries/test_prism_3d_6.cpp new file mode 100644 index 000000000000..2e342c146c5e --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_prism_3d_6.cpp @@ -0,0 +1,266 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/prism_3d_6.h" +#include "tests/cpp_tests/geometries/test_geometry.h" + +namespace Kratos { +namespace Testing { + + typedef Node<3> PointType; + typedef Node<3>::Pointer PointPtrType; + typedef Prism3D6 PrismGeometryType; + typedef PrismGeometryType::Pointer PrismGeometryPtrType; + + /** Generates a sample Prism3D6. + * Generates a prism defined by three random points in the space. + * @return Pointer to a Prism3D6 + */ + PrismGeometryPtrType GeneratePrism3D6( + PointPtrType PointA = GeneratePoint(), + PointPtrType PointB = GeneratePoint(), + PointPtrType PointC = GeneratePoint(), + PointPtrType PointD = GeneratePoint(), + PointPtrType PointE = GeneratePoint(), + PointPtrType PointF = GeneratePoint()) { + return PrismGeometryPtrType(new PrismGeometryType(PointA, PointB, PointC, PointD, PointE, PointF)); + } + + /** Generates a sample Prism3D6. + * Generates a trirectangular prism on the origin with positive volume and side 1. + * @return Pointer to a Prism3D6 + */ + PrismGeometryPtrType GenerateRegularPrism3D6() { + return PrismGeometryPtrType(new PrismGeometryType( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(1.0, 0.0, 0.0), + GeneratePoint(0.0, 1.0, 0.0), + GeneratePoint(0.0, 0.0, 1.0), + GeneratePoint(1.0, 0.0, 1.0), + GeneratePoint(0.0, 1.0, 1.0) + )); + } + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geomRegular = GenerateRegularPrism3D6(); + + KRATOS_CHECK_EQUAL(geomRegular->EdgesNumber(), 9); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6FacesNumber, KratosCoreGeometriesFastSuite) { + auto geomRegular = GenerateRegularPrism3D6(); + + KRATOS_CHECK_EQUAL(geomRegular->FacesNumber(), 5); + } + + /** Checks if the characteristic length of the prism is calculated correctly. + * Checks if the characteristic length of the prism is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6Length, KratosCoreGeometriesFastSuite) { + auto geomRegular = GenerateRegularPrism3D6(); + + KRATOS_CHECK_NEAR(geomRegular->Length(), 0.264567, TOLERANCE); + } + + /** Checks if the area of the prism is calculated correctly. + * Checks if the area of the prism is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6Area, KratosCoreGeometriesFastSuite) { + auto geomRegular = GenerateRegularPrism3D6(); + + KRATOS_CHECK_NEAR(geomRegular->Area(), 0.5, TOLERANCE); + } + + /** Checks if the volume of the prism is calculated correctly. + * Checks if the volume of the prism is calculated correctly. + * For prism 3D6 'volume()' call defaults to 'area()' + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6Volume, KratosCoreGeometriesFastSuite) { + auto geomRegular = GenerateRegularPrism3D6(); + + KRATOS_CHECK_NEAR(geomRegular->Volume(), 0.5, TOLERANCE); + } + + /** Checks the inside test for a given point respect to the prism + * Checks the inside test for a given point respect to the prism + * It performs 4 tests: + * A Point inside the prism: Expected result TRUE + * A Point outside the prism: Expected result FALSE + * A Point over a vertex of the prism: Expected result TRUE + * A Point over an edge of the prism: Expected result TRUE + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + Point PointInside(0.1666, 0.1666, 0.1666); + Point PointOutside(0.66, 0.66, 0.66); + Point PointInVertex(0.0, 0.0, 0.0); + Point PointInEdge(0.33, 0.33, 0.33); + + Point LocalCoords; + + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + /** Checks the point local coordinates for a given point respect to the + * prism. The centre of the prism is selected due to its known + * solution. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + // Compute the global coordinates of the centre + auto points = geom->Points(); + Point centre = points[0] + points[1] + points[2] + points[3] + points[4] + points[5]; + centre /= 6.0; + + // Compute the centre local coordinates + array_1d centre_local_coords; + geom->PointLocalCoordinates(centre_local_coords, centre); + + KRATOS_CHECK_NEAR(centre_local_coords(0), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(centre_local_coords(1), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(centre_local_coords(2), 1.0/2.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Prism3D6ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 1.0 / 16.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.234375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.46875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.234375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.015625, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(4, coord), 0.03125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(5, coord), 0.015625, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Prism3D6ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + Matrix gradient; + + // Compute the global coordinates of the centre + auto points = geom->Points(); + Point centre = points[0] + points[1] + points[2] + points[3] + points[4] + points[5]; + centre /= 6.0; + + // Compute the centre local coordinates + array_1d centre_local_coords; + geom->PointLocalCoordinates(centre_local_coords, centre); + + gradient = geom->ShapeFunctionsLocalGradients(gradient, centre_local_coords); + + KRATOS_CHECK_NEAR(gradient(0,0), -0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(0,1), -0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(0,2), -1.0/3.0, TOLERANCE); + + KRATOS_CHECK_NEAR(gradient(1,0), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(1,1), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(1,2), -1.0/3.0, TOLERANCE); + + KRATOS_CHECK_NEAR(gradient(2,0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(2,1), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(2,2), -1.0/3.0, TOLERANCE); + + KRATOS_CHECK_NEAR(gradient(3,0), -0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(3,1), -0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(3,2), 1.0/3.0, TOLERANCE); + + KRATOS_CHECK_NEAR(gradient(4,0), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(4,1), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(4,2), 1.0/3.0, TOLERANCE); + + KRATOS_CHECK_NEAR(gradient(5,0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(5,1), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(gradient(5,2), 1.0/3.0, TOLERANCE); + } + + /** Tests the area using 'GI_GAUSS_1' integration method. + * Tests the area using 'GI_GAUSS_1' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6GaussPoint1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + const double expected_vol = 0.5; + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_1), expected_vol, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_1); + } + + /** Tests the area using 'GI_GAUSS_2' integration method. + * Tests the area using 'GI_GAUSS_2' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6GaussPoint2, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + const double expected_vol = 0.5; + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_2), expected_vol, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_2); + } + + /** Tests the area using 'GI_GAUSS_3' integration method. + * Tests the area using 'GI_GAUSS_3' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6GaussPoint3, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + const double expected_vol = 0.5; + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_3), expected_vol, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_3); + } + + /** Tests the area using 'GI_GAUSS_4' integration method. + * Tests the area using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6GaussPoint4, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + const double expected_vol = 0.5; + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_4), expected_vol, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_4); + } + + /** Tests the area using 'GI_GAUSS_5' integration method. + * Tests the area using 'GI_GAUSS_5' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Prism3D6GaussPoint5, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRegularPrism3D6(); + + const double expected_vol = 0.5; + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_5), expected_vol, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_5); + } +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_quadrilateral_2d_4.cpp b/kratos/tests/cpp_tests/geometries/test_quadrilateral_2d_4.cpp new file mode 100644 index 000000000000..818e5078fe20 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_quadrilateral_2d_4.cpp @@ -0,0 +1,177 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Miguel Maso Sotomayor +// +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/quadrilateral_2d_4.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +// Utility includes +#include "utilities/geometry_utilities.h" + +namespace Kratos +{ +namespace Testing +{ + /// Factory functions + + /** Generates a sample Quadrilateral2D4 + * Generates a quadrilateral defined by four random + * points in the space. + * @return Pointer to a Quadrilateral2D4 + */ + template + typename Quadrilateral2D4::Pointer GenerateQuadrilateral2D4( + typename TPointType::Pointer PointA = GeneratePoint(), + typename TPointType::Pointer PointB = GeneratePoint(), + typename TPointType::Pointer PointC = GeneratePoint(), + typename TPointType::Pointer PointD = GeneratePoint() + ) + { + return typename Quadrilateral2D4::Pointer(new Quadrilateral2D4( + PointA, + PointB, + PointC, + PointD + )); + } + + /** Generates a sample Quadrilateral2D4 + * Generates a regular quadrilateral on the origin + * @return Pointer to a Quadrilateral2D4 + */ + template + typename Quadrilateral2D4::Pointer GenerateRightQuadrilateral2D4() + { + return typename Quadrilateral2D4::Pointer(new Quadrilateral2D4( + GeneratePoint( 0.0, 0.0, 0.0), + GeneratePoint( 1.0, 0.0, 0.0), + GeneratePoint( 1.0, 1.0, 0.0), + GeneratePoint( 0.0, 1.0, 0.0) + )); + } + + /** Generates a sample Quadrilateral2D4 + * Generates a regular quadrilateral centered on the origin + * and 45deg rotated + * @return Pointer to a Quadrilateral2D4 + */ + template + typename Quadrilateral2D4::Pointer GenerateDiagQuadrilateral2D4() + { + return typename Quadrilateral2D4::Pointer(new Quadrilateral2D4( + GeneratePoint( 1.0, 0.0, 0.0), + GeneratePoint( 0.0, 1.0, 0.0), + GeneratePoint(-1.0, 0.0, 0.0), + GeneratePoint( 0.0,-1.0, 0.0) + )); + } + + /** Test a box and quadrilateral HasIntersection which should give true + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4NodeBoxIntersection, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightQuadrilateral2D4>(); + Point point_1 (-0.3, 0.8, 0.0); + Point point_2 ( 0.2, 1.5, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3 ( 0.9, 1.5, 0.0); + Point point_4 ( 1.1, 0.8, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5 ( 0.9,-0.8, 0.0); + Point point_6 ( 1.1, 0.1, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + + Point point_7 (-0.3, 0.1, 0.0); + Point point_8 ( 0.2,-0.6, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_7, point_8)); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4EdgeBoxIntersection, KratosCoreGeometriesFastSuite) { + auto geom = GenerateDiagQuadrilateral2D4>(); + Point point_1 ( 0.2, 0.2, 0.0 ); + Point point_2 ( 1.0, 1.0, 0.0 ); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3 (-0.2, 0.2, 0.0 ); + Point point_4 (-0.9, 0.9, 0.0 ); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5 (-0.2,-0.2, 0.0 ); + Point point_6 (-0.9,-0.9, 0.0 ); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + + Point point_7 ( 0.2,-0.2, 0.0 ); + Point point_8 ( 1.0,-1.0, 0.0 ); + KRATOS_CHECK(geom->HasIntersection(point_7, point_8)); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4BoxNoIntersection, KratosCoreGeometriesFastSuite) { + auto geom = GenerateDiagQuadrilateral2D4>(); + Point point_1 ( 0.7, 0.4, 0.0 ); + Point point_2 ( 1.0, 1.2, 0.0 ); + KRATOS_CHECK_IS_FALSE(geom->HasIntersection(point_1, point_2)); + } + + /** Tests the PointLocalCoordinates for Quadrilateral2D4. + * Tests the PointLocalCoordinates for Quadrilateral2D4. + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightQuadrilateral2D4>(); + + Point TestPointA(1.0, 1.0, 0.0); + Point TestPointB(0.5, 0.5, 0.0); + Point TestResultA(0.0, 0.0, 0.0); + Point TestResultB(0.0, 0.0, 0.0); + + geom->PointLocalCoordinates(TestResultA, TestPointA); + geom->PointLocalCoordinates(TestResultB, TestPointB); + + // Test transformation in the edge + KRATOS_CHECK_NEAR(TestResultA[0], 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultA[1], 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultA[2], 0.0, TOLERANCE); + + // Test transformation in the center + KRATOS_CHECK_NEAR(TestResultB[0], 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultB[1], 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultB[2], 0.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightQuadrilateral2D4>(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 0.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.09375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.28125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.46875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.15625, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral2D4ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightQuadrilateral2D4>(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +} // namespace Testing +} // namespace Kratos diff --git a/kratos/tests/cpp_tests/geometries/test_quadrilateral_3d_4.cpp b/kratos/tests/cpp_tests/geometries/test_quadrilateral_3d_4.cpp new file mode 100644 index 000000000000..e98efa324180 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_quadrilateral_3d_4.cpp @@ -0,0 +1,378 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/quadrilateral_3d_4.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +// Utility includes +#include "utilities/geometry_utilities.h" + +namespace Kratos +{ +namespace Testing +{ + /// Factory functions + + /** Generates a sample Quadrilateral3D4. + * Generates a quadrilateral defined by three random points in the space. + * @return Pointer to a Quadrilateral3D4 + */ + template + typename Quadrilateral3D4::Pointer GenerateQuadrilateral3D4( + typename TPointType::Pointer PointA = GeneratePoint(), + typename TPointType::Pointer PointB = GeneratePoint(), + typename TPointType::Pointer PointC = GeneratePoint(), + typename TPointType::Pointer PointD = GeneratePoint() + ) + { + return typename Quadrilateral3D4::Pointer(new Quadrilateral3D4( + PointA, + PointB, + PointC, + PointD + )); + } + + /** Generates a sample Quadrilateral3D4. + * Generates a right quadrilateral with origin in the origin and leg size 1. + * @return Pointer to a Quadrilateral3D4 + */ + template + typename Quadrilateral3D4::Pointer GenerateRightQuadrilateral3D4() + { + return typename Quadrilateral3D4::Pointer(new Quadrilateral3D4( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(std::cos(Globals::Pi/4), 0.0, std::sin(Globals::Pi/4)), + GeneratePoint(1.0, 1.0, 0.5), + GeneratePoint(0.0, 1.0, 0.0) + )); + } + + /** Generates a sample Quadrilateral3D4. + * Generates a right quadrilateral with origin in the origin and leg size 1. + * @return Pointer to a Quadrilateral3D4 + */ + template + typename Quadrilateral3D4::Pointer GenerateFlatQuadrilateral3D4() + { + return typename Quadrilateral3D4::Pointer(new Quadrilateral3D4( + GeneratePoint( 0.0, 0.0, 0.0), + GeneratePoint( 1.0, 0.0, 0.0), + GeneratePoint( 1.0, 1.0, 0.0), + GeneratePoint( 0.0, 1.0, 0.0) + )); + } + + /// Tests + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4EdgesNumber, KratosCoreGeometriesFastSuite) + { + auto geom = GenerateRightQuadrilateral3D4>(); + + KRATOS_CHECK_EQUAL(geom->EdgesNumber(), 4); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4FacesNumber, KratosCoreGeometriesFastSuite) + { + auto geom = GenerateRightQuadrilateral3D4>(); + + // That for planar geometries it also return the number of edges. + KRATOS_CHECK_EQUAL(geom->FacesNumber(), 4); + } + + /** Checks if the area of the quadrilateral is calculated correctly. + * Checks if the area of the quadrilateral is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4Area, KratosCoreGeometriesFastSuite) + { + auto geom = GenerateRightQuadrilateral3D4>(); + + KRATOS_CHECK_NEAR(geom->Area(), 1.06947235, TOLERANCE); +// KRATOS_CHECK_NEAR(geom->Area(), 1.08935, TOLERANCE); // NOTE: Solution from Mathematica + } + + /** Tests the PointLocalCoordinates for Quadrilateral2D4. + * Tests the PointLocalCoordinates for Quadrilateral2D4. + */ + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GenerateFlatQuadrilateral3D4>(); + + Point TestPointA(1.0, 1.0, 0.0); + Point TestPointB(0.5, 0.5, 0.0); + Point TestResultA(0.0, 0.0, 0.0); + Point TestResultB(0.0, 0.0, 0.0); + + geom->PointLocalCoordinates(TestResultA, TestPointA); + geom->PointLocalCoordinates(TestResultB, TestPointB); + + // Test transformation in the edge + KRATOS_CHECK_NEAR(TestResultA[0], 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultA[1], 1.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultA[2], 0.0, TOLERANCE); + + // Test transformation in the center + KRATOS_CHECK_NEAR(TestResultB[0], 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultB[1], 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(TestResultB[2], 0.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateFlatQuadrilateral3D4>(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 0.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.09375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.28125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.46875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.15625, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateFlatQuadrilateral3D4>(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +// /** Checks if the volume of the quadrilateral is calculated correctly. +// * Checks if the volume of the quadrilateral is calculated correctly. +// * For quadrilateral 2D3 'volume()' call defaults to 'area()' +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4Volume, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// +// KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Volume(), "Calling base class 'Volume' method instead of derived class one."); +// } +// +// /** Checks the inside test for a given point respect to the quadrilateral +// * Checks the inside test for a given point respect to the quadrilateral +// * It performs 4 tests: +// * A Point inside the quadrilateral: Expected result TRUE +// * A Point outside the quadrilateral: Expected result FALSE +// * A Point over a vertex of the quadrilateral: Expected result TRUE +// * A Point over an edge of the quadrilateral: Expected result TRUE +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4IsInside, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// +// Point<3> PointInside(1.0/3.0, 2.0/3.0, 1.0/6.0); +// Point<3> PointOutside(2.0/3.0, 2.0/3.0, 0.0); +// Point<3> PointInVertex(0.0, 0.0, 0.0); +// Point<3> PointInEdge(0.5, 0.5, 0.0); +// +// Point<3> LocalCoords; +// +// // It appears that the function checks whether the PROJECTION of the point is inside the geometry. +// KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); +// KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); +// KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); +// KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); +// } +// +// /** Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. +// * Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4DeterminantOfJacobianArray1, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// const double ExpectedJacobian = 1.0; +// +// Vector JacobianDeterminants; +// geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_1 ); +// +// for (unsigned int i=0; i>(); +// const double ExpectedJacobian = 1.0; +// +// Vector JacobianDeterminants; +// geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_2 ); +// +// for (unsigned int i=0; i>(); +// const double ExpectedJacobian = 1.0; +// +// Vector JacobianDeterminants; +// geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_3 ); +// +// for (unsigned int i=0; i>(); +// const double ExpectedJacobian = 1.0; +// +// Vector JacobianDeterminants; +// geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_4 ); +// +// for (unsigned int i=0; i>(); +// const double ExpectedJacobian = 1.0; +// +// Vector JacobianDeterminants; +// geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_5 ); +// +// for (unsigned int i=0; i>(); +// const double ExpectedJacobian = 1.0; +// +// double JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_1 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// } +// +// /** Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. +// * Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4DeterminantOfJacobianIndex2, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// double JacobianDeterminant = 0.0; +// const double ExpectedJacobian = 1.0; +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_2 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_2 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// } +// +// /** Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. +// * Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4DeterminantOfJacobianIndex3, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// double JacobianDeterminant = 0.0; +// const double ExpectedJacobian = 1.0; +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_3 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_3 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_3 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// } +// +// /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. +// * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4DeterminantOfJacobianIndex4, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// double JacobianDeterminant = 0.0; +// const double ExpectedJacobian = 1.0; +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_4 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_4 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_4 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_4 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// } +// +// /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. +// * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. +// */ +// KRATOS_TEST_CASE_IN_SUITE(Quadrilateral3D4DeterminantOfJacobianIndex5, KratosCoreGeometriesFastSuite) +// { +// auto geom = GenerateRightQuadrilateral3D4>(); +// double JacobianDeterminant = 0.0; +// const double ExpectedJacobian = 1.0; +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_5 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_5 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_5 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_5 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// +// JacobianDeterminant = geom->DeterminantOfJacobian( 5, GeometryData::GI_GAUSS_5 ); +// KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); +// } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_shape_function_derivatives.h b/kratos/tests/cpp_tests/geometries/test_shape_function_derivatives.h new file mode 100644 index 000000000000..06217380ef0f --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_shape_function_derivatives.h @@ -0,0 +1,51 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// +// + +#if !defined(KRATOS_TEST_SHAPE_FUNCTION_DERIVATIVES_H_INCLUDED) +#define KRATOS_TEST_SHAPE_FUNCTION_DERIVATIVES_H_INCLUDED + +// System includes + +// External includes + +// Project includes +#include "geometries/geometry.h" +#include "includes/node.h" +#include "includes/ublas_interface.h" + +namespace Kratos { +namespace Testing { +void TestShapeFunctionsLocalGradients(Geometry> const& rGeom); + +void TestShapeFunctionsLocalGradients(Geometry> const& rGeom, + GeometryData::IntegrationMethod ThisMethod); + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex(Geometry> const& rGeom); + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex( + Geometry> const& rGeom, GeometryData::IntegrationMethod ThisMethod); + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex_ShapeFunctionIndex( + Geometry> const& rGeom, GeometryData::IntegrationMethod ThisMethod); + +void TestShapeFunctionsLocalGradients_Point(Geometry> const& rGeom); + +void TestAllShapeFunctionsLocalGradients(Geometry> const& rGeom); + +void TestShapeFunctionsLocalGradient(Geometry> const& rGeom, + Geometry>::IntegrationPointType Point, + Matrix const& rLocalGradient); +} +} + +#endif // KRATOS_TEST_SHAPE_FUNCTION_DERIVATIVES_H_INCLUDED defined diff --git a/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_10.cpp b/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_10.cpp new file mode 100644 index 000000000000..8c5669034351 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_10.cpp @@ -0,0 +1,171 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/tetrahedra_3d_10.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +namespace Kratos { +namespace Testing { + + // /// Factory functions + +namespace{ + typedef Node<3> NodeType; + + Geometry::PointsArrayType GenerateReferenceNodes3D10() + { + Geometry::PointsArrayType points; + points.push_back(NodeType::Pointer(new NodeType(1, 0.0, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(2, 1.0, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(3, 0.0, 1.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(4, 0.0, 0.0, 1.0))); + points.push_back(NodeType::Pointer(new NodeType(5, 0.5, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(6, 0.5, 0.5, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(7, 0.0, 0.5, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(8, 0.0, 0.0, 0.5))); + points.push_back(NodeType::Pointer(new NodeType(9, 0.5, 0.0, 0.5))); + points.push_back(NodeType::Pointer(new NodeType(10, 0.0, 0.5, 0.5))); + return points; + } + + Geometry::Pointer GenerateReferenceTetrahedra3D10() { + return Geometry::Pointer( + new Tetrahedra3D10(GenerateReferenceNodes3D10())); + } + + Geometry::Pointer GenerateCurvedTetrahedra3D10() { + auto nodes = GenerateReferenceNodes3D10(); + nodes[5].X0() = nodes[5].X() = 0.4; + nodes[5].Y0() = nodes[5].Y() = 0.4; + nodes[6].X0() = nodes[6].X() = 0.1; + nodes[6].Z0() = nodes[6].Z() = 0.1; + nodes[7].X0() = nodes[7].X() = 0.1; + nodes[7].Y0() = nodes[7].Y() = 0.1; + nodes[8].X0() = nodes[8].X() = 0.4; + nodes[8].Z0() = nodes[8].Z() = 0.4; + nodes[9].Y0() = nodes[9].Y() = 0.4; + nodes[9].Z0() = nodes[9].Z() = 0.4; + return Geometry::Pointer(new Tetrahedra3D10(nodes)); + } +} + + // /// Tests + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EQUAL(geom->EdgesNumber(), 6); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10FacesNumber, KratosCoreGeometriesFastSuite) { + Geometry::Pointer geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EQUAL(geom->FacesNumber(), 4); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10Volume, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_NEAR(geom->Volume(), 1.0 / 6.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10MinEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->MinEdgeLength(), "Calling base class 'MinEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10MaxEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->MaxEdgeLength(), "Calling base class 'MaxEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10AverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->AverageEdgeLength(), "Calling base class 'AverageEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10Circumradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Circumradius(), "Calling base class 'Circumradius' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10Inradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Inradius(), "Calling base class 'Inradius' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateCurvedTetrahedra3D10(); + Point PointInside(0.1, 0.1, 0.1); + Point PointOutside(0.5, 0.5, 0.0); + Point PointInVertex(0.0, 0.0, 0.0); + Point PointInEdge(0.6, 0.0, 0.0); + Point LocalCoords; + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + geom->IsInside(PointInEdge, LocalCoords, EPSILON); + KRATOS_WATCH(LocalCoords); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10DeterminantOfJacobianArray1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + Vector JacobianDeterminants; + geom->DeterminantOfJacobian(JacobianDeterminants, GeometryData::GI_GAUSS_2); + for (unsigned int i=0; iIntegrationPointsNumber(), 4); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10DeterminantOfJacobianIndex1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + for (unsigned g = 0; g < geom->IntegrationPointsNumber(); ++g) + KRATOS_CHECK_NEAR(geom->DeterminantOfJacobian(g), 1.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 1.0 / 16.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), -0.1171875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), -0.125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), -0.0546875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(4, coord), 0.375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(5, coord), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(6, coord), 0.1875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(7, coord), 0.046875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(8, coord), 0.125, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(9, coord), 0.0625, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D10ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTetrahedra3D10(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_4.cpp b/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_4.cpp new file mode 100644 index 000000000000..d1a2627fe888 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_tetrahedra_3d_4.cpp @@ -0,0 +1,546 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig +// Vicente Mataix Ferrandiz +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/tetrahedra_3d_4.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +namespace Kratos { + namespace Testing { + + typedef Node<3> PointType; + typedef Node<3>::Pointer PointPtrType; + typedef Tetrahedra3D4 TetGeometryType; + typedef TetGeometryType::Pointer TetGeometryPtrType; + + /** Generates a sample Tetrahedra3D4. + * Generates a tetrahedra defined by three random points in the space. + * @return Pointer to a Tetrahedra3D4 + */ + TetGeometryPtrType GenerateTetrahedra3D4( + PointPtrType PointA = GeneratePoint(), + PointPtrType PointB = GeneratePoint(), + PointPtrType PointC = GeneratePoint(), + PointPtrType PointD = GeneratePoint()) { + return TetGeometryPtrType(new TetGeometryType(PointA, PointB, PointC, PointD)); + } + + /** Generates a sample Tetrahedra3D4. + * Generates a trirectangular tetrahedra on the origin with positive volume and side 1. + * @return Pointer to a Tetrahedra3D4 + */ + TetGeometryPtrType GenerateTriRectangularTetrahedra3D4() { + return TetGeometryPtrType(new TetGeometryType( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(1.0, 0.0, 0.0), + GeneratePoint(0.0, 1.0, 0.0), + GeneratePoint(0.0, 0.0, 1.0) + )); + } + + /** Generates a sample Tetrahedra3D4. + * Generates a regular tetrahedra with positive volume and side 1. + * @return Pointer to a Tetrahedra3D4 + */ + TetGeometryPtrType GenerateRegInvtLen1Tetrahedra3D4() { + return TetGeometryPtrType(new TetGeometryType( + GeneratePoint(0.0, 1.0, 1.0), + GeneratePoint(1.0, 0.0, 1.0), + GeneratePoint(1.0, 1.0, 0.0), + GeneratePoint(0.0, 0.0, 0.0) + )); + } + + /** Generates a sample Tetrahedra3D4. + * Generates a regular tetrahedra with negative volume and side 1. + * @return Pointer to a Tetrahedra3D4 + */ + TetGeometryPtrType GenerateRegularLen1Tetrahedra3D4() { + return TetGeometryPtrType(new TetGeometryType( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(0.0, 1.0, 1.0), + GeneratePoint(1.0, 0.0, 1.0), + GeneratePoint(1.0, 1.0, 0.0) + )); + } + + /** Generates a sample Tetrahedra3D4. + * Generates a regular tetrahedra with positive volume with side 2. + * @return Pointer to a Tetrahedra3D4 + */ + TetGeometryPtrType GenerateRegularLen2Tetrahedra3D4() { + return TetGeometryPtrType(new TetGeometryType( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(0.0, 2.0, 2.0), + GeneratePoint(2.0, 0.0, 2.0), + GeneratePoint(2.0, 2.0, 0.0) + )); + } + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_EQUAL(geomInvLen1->EdgesNumber(), 6); + KRATOS_CHECK_EQUAL(geomRegLen1->EdgesNumber(), 6); + KRATOS_CHECK_EQUAL(geomRegLen2->EdgesNumber(), 6); + KRATOS_CHECK_EQUAL(geomTriRect->EdgesNumber(), 6); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4FacesNumber, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + // Charlie: I will let this to 3 but probably 'FacesNumber' needs to be documented to state + // that for planar geometries it also return the number of edges. + KRATOS_CHECK_EQUAL(geomInvLen1->FacesNumber(), 4); + KRATOS_CHECK_EQUAL(geomRegLen1->FacesNumber(), 4); + KRATOS_CHECK_EQUAL(geomRegLen2->FacesNumber(), 4); + KRATOS_CHECK_EQUAL(geomTriRect->FacesNumber(), 4); + } + + /** Checks if the characteristic length of the tetrahedra is calculated correctly. + * Checks if the characteristic length of the tetrahedra is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4Length, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->Length(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Length(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Length(), 2.828427, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Length(), 1.122462, TOLERANCE); + } + + /** Checks if the area of the tetrahedra is calculated correctly. + * Checks if the area of the tetrahedra is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4Area, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->Area(), -1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Area(), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Area(), 8.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Area(), 1.0/6.0, TOLERANCE); + } + + /** Checks if the volume of the tetrahedra is calculated correctly. + * Checks if the volume of the tetrahedra is calculated correctly. + * For tetrahedra 3D4 'volume()' call defaults to 'area()' + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4Volume, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->Volume(), -1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Volume(), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Volume(), 8.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Volume(), 1.0/6.0, TOLERANCE); + } + + /** Checks if the minimum edge length is calculated correctly. + * Checks if the minimum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4MinEdgeLength, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->MinEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->MinEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->MinEdgeLength(), 2.828427, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->MinEdgeLength(), 1.000000, TOLERANCE); + } + + /** Checks if the maximum edge length is calculated correctly. + * Checks if the maximum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4MaxEdgeLength, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->MaxEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->MaxEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->MaxEdgeLength(), 2.828427, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->MaxEdgeLength(), 1.414213, TOLERANCE); + } + + /** Checks if the average edge length is calculated correctly. + * Checks if the average edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4AverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->AverageEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->AverageEdgeLength(), 1.414213, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->AverageEdgeLength(), 2.828427, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->AverageEdgeLength(), 1.207106, TOLERANCE); + } + + /** Checks if the circumradius is calculated correctly. + * Checks if the circumradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4Circumradius, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->Circumradius(), 0.866025, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Circumradius(), 0.866025, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Circumradius(), 1.732050, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Circumradius(), 0.866025, TOLERANCE); + } + + /** Checks if the inradius is calculated correctly. + * Checks if the inradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4Inradius, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + KRATOS_CHECK_NEAR(geomInvLen1->Inradius(), 0.288675, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Inradius(), 0.288675, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Inradius(), 0.577350, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Inradius(), 0.211324, TOLERANCE); + } + + /** Checks if the inradius to circumradius quality metric is correctly calculated. + * Checks if the inradius to circumradius quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4InradiusToCircumradiusQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::INRADIUS_TO_CIRCUMRADIUS; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.732051, TOLERANCE); + } + + /** Checks if the inradius to longest edge quality metric is correctly calculated. + * Checks if the inradius to longest edge quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4InradiusToLongestEdgeQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::INRADIUS_TO_LONGEST_EDGE; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.732051, TOLERANCE); + } + + /** Checks if the shortest to longest edge length quality metric is correctly calculated. + * Checks if the shortest to longest edge length quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4ShortestToLongestEdgeQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::SHORTEST_TO_LONGEST_EDGE; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.707106, TOLERANCE); + } + + /** Checks if the regularity quality metric is correctly calculated. + * Checks if the regularity quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4RegularityQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::REGULARITY; + + // KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.0, TOLERANCE); + // KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.0, TOLERANCE); + // KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), -1.0, TOLERANCE); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomInvLen1->Quality(criteria), "Method 'RegularityQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomRegLen1->Quality(criteria), "Method 'RegularityQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomRegLen2->Quality(criteria), "Method 'RegularityQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomTriRect->Quality(criteria), "Method 'RegularityQuality' is not yet implemented for Tetrahedra3D4"); + } + + /** Checks if the volume to surface area quality metric is correctly calculated. + * Checks if the volume to surface area quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4VolumeToSurfaceAreaQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::VOLUME_TO_SURFACE_AREA; + + // KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.0, TOLERANCE); + // KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.0, TOLERANCE); + // KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), -1.0, TOLERANCE); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomInvLen1->Quality(criteria), "Method 'VolumeToSurfaceAreaQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomRegLen1->Quality(criteria), "Method 'VolumeToSurfaceAreaQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomRegLen2->Quality(criteria), "Method 'VolumeToSurfaceAreaQuality' is not yet implemented for Tetrahedra3D4"); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geomTriRect->Quality(criteria), "Method 'VolumeToSurfaceAreaQuality' is not yet implemented for Tetrahedra3D4"); + } + + /** Checks if the volume to edge length quality metric is correctly calculated. + * Checks if the volume to edge length quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4VolumeToEdgeLengthQuality, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::VOLUME_TO_EDGE_LENGTH; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), -1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.839947, TOLERANCE); + } + + /** Checks if the volume to average edge length quality metric is correctly calculated. + * Checks if the volume to average edge length quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4VolumeToAverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::VOLUME_TO_AVERAGE_EDGE_LENGTH; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), -1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.804041, TOLERANCE); + } + + /** Checks if the volume to RMS edge length quality metric is correctly calculated. + * Checks if the volume to RMS edge length quality metric is correctly calculated for: + * - Regular tetrahedra, which should return a perfect score. + * - TriRectangular tetrahedra, which should return a sub-optimal score. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4VolumeToRMSEdgeLength, KratosCoreGeometriesFastSuite) { + auto geomInvLen1 = GenerateRegInvtLen1Tetrahedra3D4(); + auto geomRegLen1 = GenerateRegularLen1Tetrahedra3D4(); + auto geomRegLen2 = GenerateRegularLen2Tetrahedra3D4(); + auto geomTriRect = GenerateTriRectangularTetrahedra3D4(); + + auto criteria = TetGeometryType::QualityCriteria::VOLUME_TO_RMS_EDGE_LENGTH; + + KRATOS_CHECK_NEAR(geomInvLen1->Quality(criteria), -1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen1->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomRegLen2->Quality(criteria), 1.000000, TOLERANCE); + KRATOS_CHECK_NEAR(geomTriRect->Quality(criteria), 0.769800, TOLERANCE); + } + + /** + * This test performs the check of the box intersection method + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4BoxIntersection, KratosCoreGeometriesFastSuite) { + auto tetrahedron = GenerateTriRectangularTetrahedra3D4(); + + //tetrahedron inside the box + KRATOS_CHECK(tetrahedron->HasIntersection(Point(-.1,-.2,-.1), Point(1.1,1.1,1.2))); + + //tetrahedron contains the box + KRATOS_CHECK(tetrahedron->HasIntersection(Point(.25,.25,.25), Point(.26,.26,.26))); + + //tetrahedron intersects the box + KRATOS_CHECK(tetrahedron->HasIntersection(Point(.25,.25,.25), Point(1.1,1.1,1.2))); + + //tetrahedron not intersects the box + KRATOS_CHECK_IS_FALSE(tetrahedron->HasIntersection(Point(.51,.51,.51), Point(1.1,1.1,1.2))); + } + + /** Checks the inside test for a given point respect to the tetrahedra + * Checks the inside test for a given point respect to the tetrahedra + * It performs 4 tests: + * A Point inside the tetrahedra: Expected result TRUE + * A Point outside the tetrahedra: Expected result FALSE + * A Point over a vertex of the tetrahedra: Expected result TRUE + * A Point over an edge of the tetrahedra: Expected result TRUE + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateTriRectangularTetrahedra3D4(); + + Point PointInside(0.1666, 0.1666, 0.1666); + Point PointOutside(0.66, 0.66, 0.66); + Point PointInVertex(0.0, 0.0, 0.0); + Point PointInEdge(0.33, 0.33, 0.33); + + Point LocalCoords; + + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + /** Checks the point local coordinates for a given point respect to the + * tetrahedra. The baricentre of the tetrahedra is selected due to its known + * solution. + */ + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GenerateTriRectangularTetrahedra3D4(); + + // Compute the global coordinates of the baricentre + auto points = geom->Points(); + Point baricentre = points[0] + points[1] + points[2] + points[3]; + baricentre /= 3.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords; + geom->PointLocalCoordinates(baricentre_local_coords, baricentre); + + KRATOS_CHECK_NEAR(baricentre_local_coords(0), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(1), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(2), 1.0/3.0, TOLERANCE); + + Point baricentre_face_1; + baricentre_face_1.Coordinates()[0] = 0.5; + baricentre_face_1.Coordinates()[1] = 0.5; + baricentre_face_1.Coordinates()[2] = 0.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_1; + geom->PointLocalCoordinates(baricentre_local_coords_face_1, baricentre_face_1); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(0), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(1), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_1(2), 0.0, TOLERANCE); + + Point baricentre_face_2; + baricentre_face_2.Coordinates()[0] = 0.5; + baricentre_face_2.Coordinates()[1] = 0.0; + baricentre_face_2.Coordinates()[2] = 0.5; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_2; + geom->PointLocalCoordinates(baricentre_local_coords_face_2, baricentre_face_2); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(0), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(1), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_2(2), 0.5, TOLERANCE); + + Point baricentre_face_3; + baricentre_face_3.Coordinates()[0] = 0.0; + baricentre_face_3.Coordinates()[1] = 0.5; + baricentre_face_3.Coordinates()[2] = 0.5; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords_face_3; + geom->PointLocalCoordinates(baricentre_local_coords_face_3, baricentre_face_3); + + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(0), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(1), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords_face_3(2), 0.5, TOLERANCE); + + Point outside_point; + outside_point.Coordinates()[0] = 0.5; + outside_point.Coordinates()[1] = 0.5; + outside_point.Coordinates()[2] = 0.5; + + // Compute the baricentre local coordinates + array_1d local_coords_outside_point; + geom->PointLocalCoordinates(local_coords_outside_point, outside_point); + + KRATOS_CHECK_NEAR(local_coords_outside_point(0), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(local_coords_outside_point(1), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(local_coords_outside_point(2), 0.5, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateTriRectangularTetrahedra3D4(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 4.0; + coord[2] = 1.0 / 16.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.1875, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.25, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.0625, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3D4ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateTriRectangularTetrahedra3D4(); + TestAllShapeFunctionsLocalGradients(*geom); + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_triangle_2d_3.cpp b/kratos/tests/cpp_tests/geometries/test_triangle_2d_3.cpp new file mode 100644 index 000000000000..32c62a647d58 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_triangle_2d_3.cpp @@ -0,0 +1,578 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/triangle_2d_3.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +// Utility includes +#include "utilities/geometry_utilities.h" + +namespace Kratos { +namespace Testing { + + /// Factory functions + + /** Generates a sample triangle2D3. + * Generates a triangle defined by three random points in the space. + * @return Pointer to a triangle2D3 + */ + template + typename Triangle2D3::Pointer GenerateTriangle2D3( + typename TPointType::Pointer PointA = GeneratePoint(), + typename TPointType::Pointer PointB = GeneratePoint(), + typename TPointType::Pointer PointC = GeneratePoint()) { + return typename Triangle2D3::Pointer(new Triangle2D3( + PointA, + PointB, + PointC + )); + } + + /** Generates a point type sample triangle2D3. + * Generates a point type right triangle with origin in the origin and leg size 1. + * @return Pointer to a triangle2D3 + */ + Triangle2D3::Pointer GeneratePointsRightTriangle2D3() { + return Triangle2D3::Pointer(new Triangle2D3( + Point::Pointer(new Point(0.0, 0.0, 0.0)), + Point::Pointer(new Point(1.0, 0.0, 0.0)), + Point::Pointer(new Point(0.0, 1.0, 0.0)) + )); + } + + /** Generates a node type sample triangle2D3. + * Generates a point type right triangle with origin in the origin and leg size 1. + * @return Pointer to a triangle2D3 + */ + Triangle2D3>::Pointer GenerateNodesRightTriangle2D3() { + return Triangle2D3>::Pointer(new Triangle2D3>( + Node<3>::Pointer(new Node<3>(1, 0.0, 0.0, 0.0)), + Node<3>::Pointer(new Node<3>(2, 1.0, 0.0, 0.0)), + Node<3>::Pointer(new Node<3>(3, 0.0, 1.0, 0.0)) + )); + } + + /** Generates a point type sample triangle2D3. + * Generates a point type irregular triangle. + * @return Pointer to a triangle2D3 + */ + Triangle2D3::Pointer GeneratePointsIrregularTriangle2D3() { + return Triangle2D3::Pointer(new Triangle2D3( + Point::Pointer(new Point(1.0, 1.0, 0.0)), + Point::Pointer(new Point(3.0, 0.5, 0.0)), + Point::Pointer(new Point(2.5, 2.0, 0.0)) + )); + } + + /** Generates a sample triangle2D3. + * Generates a node irregular triangle. + * @return Pointer to a triangle2D3 + */ + Triangle2D3>::Pointer GenerateNodesIrregularTriangle2D3() { + return Triangle2D3>::Pointer(new Triangle2D3>( + Node<3>::Pointer(new Node<3>(1, 1.0, 1.0, 0.0)), + Node<3>::Pointer(new Node<3>(2, 3.0, 0.5, 0.0)), + Node<3>::Pointer(new Node<3>(3, 2.5, 2.0, 0.0)) + )); + } + + /// Tests + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_EQUAL(geom->EdgesNumber(), 3); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3FacesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + // Charlie: I will let this to 3 but probably 'FacesNumber' needs to be documented to state + // that for planar geometries it also return the number of edges. + KRATOS_CHECK_EQUAL(geom->FacesNumber(), 3); + } + + /** Checks if the area of the triangle is calculated correctly. + * Checks if the area of the triangle is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3Area, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->Area(), 0.5, TOLERANCE); + } + + /** Checks if the area of the triangle is calculated correctly. + * Checks if the area of the triangle is calculated correctly using the Jaccobian matrix. + * This test correctness is tied to the correctness of 'TestTriangle2D3Area'. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3AreaJaccobi, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double Area; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, Area); + + KRATOS_CHECK_NEAR(Area, 0.5, TOLERANCE); + } + + /** Checks if the volume of the triangle is calculated correctly. + * Checks if the volume of the triangle is calculated correctly. + * For triangle 2D3 'volume()' call defaults to 'area()' + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3Volume, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Volume(), "Calling base class 'Volume' method instead of derived class one."); + } + + /** Checks if the minimum edge length is calculated correctly. + * Checks if the minimum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3MinEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->MinEdgeLength(), 1.0, TOLERANCE); + } + + /** Checks if the maximum edge length is calculated correctly. + * Checks if the maximum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3MaxEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->MaxEdgeLength(), 1.414213, TOLERANCE); + } + + /** Checks if the average edge length is calculated correctly. + * Checks if the average edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3AverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->AverageEdgeLength(), 1.138071, TOLERANCE); + } + + /** Checks if the circumradius is calculated correctly. + * Checks if the circumradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3Circumradius, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->Circumradius(), 0.707107, TOLERANCE); + } + + /** Checks if the inradius is calculated correctly. + * Checks if the inradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3Inradius, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + KRATOS_CHECK_NEAR(geom->Inradius(), 0.292893, TOLERANCE); + } + + /** Checks the inside test for a given point respect to the triangle + * Checks the inside test for a given point respect to the triangle + * It performs 4 tests: + * A Point inside the triangle: Expected result TRUE + * A Point outside the triangle: Expected result FALSE + * A Point over a vertex of the triangle: Expected result TRUE + * A Point over an edge of the triangle: Expected result TRUE + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + + Point PointInside(0.33, 0.33); + Point PointOutside(0.66, 0.66); + Point PointInVertex(0.0, 0.0); + Point PointInEdge(0.5, 0.5); + + Point LocalCoords; + + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + /** Checks the point local coordinates for a given point respect to the + * triangle. The baricentre of the triangle is selected due to its known + * solution. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3PointLocalCoordinates, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsIrregularTriangle2D3(); + + // Compute the global coordinates of the baricentre + const Geometry::PointsArrayType geom_pts = geom->Points(); + Point baricentre = geom_pts[0] + geom_pts[1] + geom_pts[2]; + baricentre *= 1.0/3.0; + + // Compute the baricentre local coordinates + array_1d baricentre_local_coords; + geom->PointLocalCoordinates(baricentre_local_coords, baricentre); + + KRATOS_CHECK_NEAR(baricentre_local_coords(0), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(1), 1.0/3.0, TOLERANCE); + KRATOS_CHECK_NEAR(baricentre_local_coords(2), 0.0, TOLERANCE); + } + + /** Tests the area using 'GI_GAUSS_1' integration method. + * Tests the area using 'GI_GAUSS_1' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3GaussPoint1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double ExpectedArea; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, ExpectedArea); + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_1), ExpectedArea, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_1); + } + + /** Tests the area using 'GI_GAUSS_2' integration method. + * Tests the area using 'GI_GAUSS_2' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3GaussPoint2, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double ExpectedArea; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, ExpectedArea); + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_2), ExpectedArea, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_2); + } + + /** Tests the area using 'GI_GAUSS_3' integration method. + * Tests the area using 'GI_GAUSS_3' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3GaussPoint3, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double ExpectedArea; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, ExpectedArea); + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_3), ExpectedArea, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_3); + } + + /** Tests the area using 'GI_GAUSS_4' integration method. + * Tests the area using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3GaussPoint4, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double ExpectedArea; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, ExpectedArea); + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_4), ExpectedArea, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_4); + } + + /** Tests the area using 'GI_GAUSS_5' integration method. + * Tests the area using 'GI_GAUSS_5' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3GaussPoint5, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + + BoundedMatrix DN_DX; + array_1d N; + double ExpectedArea; + + GeometryUtils::CalculateGeometryData(*geom, DN_DX, N, ExpectedArea); + + KRATOS_CHECK_NEAR(CalculateAreaByIntegration(*geom, GeometryData::GI_GAUSS_5), ExpectedArea, TOLERANCE); + VerifyStrainExactness(*geom, GeometryData::GI_GAUSS_5); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3DeterminantOfJacobianArray1, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_1 ); + + for (unsigned int i=0; iDeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_2 ); + + for (unsigned int i=0; iDeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_3 ); + + for (unsigned int i=0; iDeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_4 ); + + for (unsigned int i=0; iDeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_5 ); + + for (unsigned int i=0; iDeterminantOfJacobian( 1, GeometryData::GI_GAUSS_1 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3DeterminantOfJacobianIndex2, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_2 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_2 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3DeterminantOfJacobianIndex3, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3DeterminantOfJacobianIndex4, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3DeterminantOfJacobianIndex5, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 5, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** + * Test an overlaping box and triangle (intersects a triangle edge) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IntersectionBoxEdge, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + Point point_1(-0.1, 0.1, 0.0); + Point point_2( 0.1, 0.3, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3( 0.1,-0.1, 0.0); + Point point_4( 0.3, 0.1, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5( 0.3, 0.2, 0.0); + Point point_6( 1.0, 1.0, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + } + + /** + * Test an overlaping box and triangle (intersects a triangle node) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IntersectionBoxNode, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + Point point_1(-0.5, 0.8, 0.0); + Point point_2( 0.5, 1.2, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3( 0.3,-0.5, 0.0); + Point point_4( 1.2, 0.5, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5( 0.2, 0.3, 0.0); + Point point_6(-0.8,-0.3, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + } + + /** + * Test a box inside a triangle HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IntersectionBoxInside, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + Point point_1( 0.1, 0.1, 0.0); + Point point_2( 0.3, 0.4, 0.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test a non overlaping box and triangle HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IntersectionBoxNoIntersect, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + Point point_1( 0.6, 0.5, 0.0); + Point point_2( 1.0, 1.0, 0.0); + KRATOS_CHECK_IS_FALSE(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test a box outside the triangle plane + * HasIntersection should return true, because a 2D-space does not take care about Z-coordinates + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3IntersectionBoxOutsidePlane, KratosCoreGeometriesFastSuite) { + auto geom = GeneratePointsRightTriangle2D3(); + Point point_1( 0.2, 0.1, 0.1); + Point point_2( 0.3, 0.5, 1.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 8.0; + coord[2] = 0.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.125, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D3ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateNodesRightTriangle2D3(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_triangle_2d_6.cpp b/kratos/tests/cpp_tests/geometries/test_triangle_2d_6.cpp new file mode 100644 index 000000000000..78a380a96b11 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_triangle_2d_6.cpp @@ -0,0 +1,158 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/triangle_2d_6.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +namespace Kratos { +namespace Testing { +typedef Node<3> NodeType; + +// /// Factory functions +namespace { + Geometry::PointsArrayType GenerateReferenceNodes2D6() + { + Geometry::PointsArrayType points; + points.push_back(NodeType::Pointer(new NodeType(1, 0.0, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(2, 1.0, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(3, 0.0, 1.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(4, 0.5, 0.0, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(5, 0.5, 0.5, 0.0))); + points.push_back(NodeType::Pointer(new NodeType(6, 0.0, 0.5, 0.0))); + return points; + } + + Geometry::Pointer GenerateReferenceTriangle2D6() { + return Geometry::Pointer( + new Triangle2D6(GenerateReferenceNodes2D6())); + } + + Geometry::Pointer GenerateCurvedTriangle2D6() { + auto nodes = GenerateReferenceNodes2D6(); + nodes[3].Y0() = nodes[3].Y() = 0.1; + nodes[4].X0() = nodes[4].X() = 0.4; + nodes[4].Y0() = nodes[4].Y() = 0.4; + nodes[5].X0() = nodes[5].X() = 0.1; + return Geometry::Pointer(new Triangle2D6(nodes)); + } +} + + // /// Tests + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EQUAL(geom->EdgesNumber(), 3); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6FacesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EQUAL(geom->FacesNumber(), 3); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6Area, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_NEAR(geom->Area(), 0.5, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6Volume, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Volume(), "Calling base class 'Volume' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6MinEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->MinEdgeLength(), "Calling base class 'MinEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6MaxEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->MaxEdgeLength(), "Calling base class 'MaxEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6AverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->AverageEdgeLength(), "Calling base class 'AverageEdgeLength' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6Circumradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Circumradius(), "Calling base class 'Circumradius' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6Inradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Inradius(), "Calling base class 'Inradius' method instead of derived class one."); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateCurvedTriangle2D6(); + Point PointInside(0.1, 0.1); + Point PointOutside(0.5, 0.5); + Point PointInVertex(0.0, 0.0); + Point PointInEdge(0.5, 0.1); + Point LocalCoords; + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6DeterminantOfJacobianArray1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + Vector JacobianDeterminants; + geom->DeterminantOfJacobian(JacobianDeterminants, GeometryData::GI_GAUSS_2); + for (unsigned int i=0; iIntegrationPointsNumber(), 3); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6DeterminantOfJacobianIndex1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + for (unsigned g = 0; g < geom->IntegrationPointsNumber(); ++g) + KRATOS_CHECK_NEAR(geom->DeterminantOfJacobian(g), 1.0, TOLERANCE); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 8.0; + coord[2] = 0.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), -0.09375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.0, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), -0.09375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(3, coord), 0.75, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(4, coord), 0.25, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(5, coord), 0.1875, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle2D6ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateReferenceTriangle2D6(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/geometries/test_triangle_3d_3.cpp b/kratos/tests/cpp_tests/geometries/test_triangle_3d_3.cpp new file mode 100644 index 000000000000..1df34462cfe1 --- /dev/null +++ b/kratos/tests/cpp_tests/geometries/test_triangle_3d_3.cpp @@ -0,0 +1,645 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/triangle_3d_3.h" +#include "tests/cpp_tests/geometries/test_geometry.h" +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +// Utility includes +#include "utilities/geometry_utilities.h" + +namespace Kratos +{ +namespace Testing +{ + /// Factory functions + + typedef Node<3> NodeType; + + /** Generates a sample Triangle3D3. + * Generates a triangle defined by three random points in the space. + * @return Pointer to a Triangle3D3 + */ + template + typename Triangle3D3::Pointer GenerateTriangle3D3( + typename TPointType::Pointer PointA = GeneratePoint(), + typename TPointType::Pointer PointB = GeneratePoint(), + typename TPointType::Pointer PointC = GeneratePoint()) { + return typename Triangle3D3::Pointer(new Triangle3D3( + PointA, + PointB, + PointC + )); + } + + /** Generates a sample Triangle3D3. + * Generates a right triangle with origin in the origin and leg size 1. + * @return Pointer to a Triangle3D3 + */ + template + typename Triangle3D3::Pointer GenerateRightTriangle3D3() { + return typename Triangle3D3::Pointer(new Triangle3D3( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(std::cos(Globals::Pi/4), 0.0, std::sin(Globals::Pi/4)), + GeneratePoint(0.0, 1.0, 0.0) + )); + } + + /** Generates a sample Triangle3D3. + * Generates an equilateral triangle with vertices at each axis. + * @return Pointer to a Triangle3D3 + */ + template + typename Triangle3D3::Pointer GenerateEquilateralTriangle3D3() { + return typename Triangle3D3::Pointer(new Triangle3D3( + GeneratePoint(1.0, 0.0, 0.0), + GeneratePoint(0.0, 1.0, 0.0), + GeneratePoint(0.0, 0.0, 1.0) + )); + } + + /// Tests + + /** Checks if the number of edges is correct. + * Checks if the number of edges is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3EdgesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_EQUAL(geom->EdgesNumber(), 3); + } + + /** Checks if the number of faces is correct. + * Checks if the number of faces is correct. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3FacesNumber, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + // Charlie: I will let this to 3 but probably 'FacesNumber' needs to be documented to state + // that for planar geometries it also return the number of edges. + KRATOS_CHECK_EQUAL(geom->FacesNumber(), 3); + } + + /** Checks if the area of the triangle is calculated correctly. + * Checks if the area of the triangle is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3Area, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->Area(), 0.5, TOLERANCE); + } + + /** Checks if the volume of the triangle is calculated correctly. + * Checks if the volume of the triangle is calculated correctly. + * For triangle 2D3 'volume()' call defaults to 'area()' + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3Volume, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(geom->Volume(), "Calling base class 'Volume' method instead of derived class one."); + } + + /** Checks if the minimum edge length is calculated correctly. + * Checks if the minimum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3MinEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->MinEdgeLength(), 1.0, TOLERANCE); + } + + /** Checks if the maximum edge length is calculated correctly. + * Checks if the maximum edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3MaxEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->MaxEdgeLength(), 1.414213, TOLERANCE); + } + + /** Checks if the average edge length is calculated correctly. + * Checks if the average edge length is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AverageEdgeLength, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->AverageEdgeLength(), 1.138071, TOLERANCE); + } + + /** Checks if the circumradius is calculated correctly. + * Checks if the circumradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3Circumradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->Circumradius(), 0.707107, TOLERANCE); + } + + /** Checks if the inradius is calculated correctly. + * Checks if the inradius is calculated correctly. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3Inradius, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + KRATOS_CHECK_NEAR(geom->Inradius(), 0.292893, TOLERANCE); + } + + /** Checks the inside test for a given point respect to the triangle + * Checks the inside test for a given point respect to the triangle + * It performs 4 tests: + * A Point inside the triangle: Expected result TRUE + * A Point outside the triangle: Expected result FALSE + * A Point over a vertex of the triangle: Expected result TRUE + * A Point over an edge of the triangle: Expected result TRUE + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3IsInside, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + + Point PointInside(0.33, 0.33, 0.0); + Point PointOutside(0.66, 0.66, 0.0); + Point PointInVertex(0.0, 0.0, 0.0); + Point PointInEdge(0.5, 0.5, 0.0); + + Point LocalCoords; + + // It appears that the function checks whether the PROJECTION of the point is inside the geometry. + KRATOS_CHECK(geom->IsInside(PointInside, LocalCoords, EPSILON)); + KRATOS_CHECK_IS_FALSE(geom->IsInside(PointOutside, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInVertex, LocalCoords, EPSILON)); + KRATOS_CHECK(geom->IsInside(PointInEdge, LocalCoords, EPSILON)); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_1' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3DeterminantOfJacobianArray1, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_1 ); + + for (unsigned int i=0; i(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_2 ); + + for (unsigned int i=0; i(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_3 ); + + for (unsigned int i=0; i(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_4 ); + + for (unsigned int i=0; i(); + const double ExpectedJacobian = 1.0; + + Vector JacobianDeterminants; + geom->DeterminantOfJacobian( JacobianDeterminants, GeometryData::GI_GAUSS_5 ); + + for (unsigned int i=0; i(); + const double ExpectedJacobian = 1.0; + + double JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_1 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_2' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3DeterminantOfJacobianIndex2, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_2 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_2 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_3' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3DeterminantOfJacobianIndex3, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_3 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3DeterminantOfJacobianIndex4, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_4 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + /** Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + * Tests the Jacobian determinants using 'GI_GAUSS_4' integration method. + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3DeterminantOfJacobianIndex5, KratosCoreGeometriesFastSuite) { + auto geom = GenerateRightTriangle3D3(); + double JacobianDeterminant = 0.0; + const double ExpectedJacobian = 1.0; + + JacobianDeterminant = geom->DeterminantOfJacobian( 1, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 2, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 3, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 4, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + + JacobianDeterminant = geom->DeterminantOfJacobian( 5, GeometryData::GI_GAUSS_5 ); + KRATOS_CHECK_NEAR(JacobianDeterminant, ExpectedJacobian, TOLERANCE); + } + + + /** Tests two very near parallel triangles HasIntegration which should give false + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3ParallelNoIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, 1.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.0, 0.0, 0.01), + GeneratePoint(10., 0.0, 2.01), + GeneratePoint(0.0, 1.0, 0.01) + ); + + KRATOS_CHECK_IS_FALSE(triangle_1.HasIntersection(triangle_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3ParallelNearIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, 1.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.0, 0.0, 0.00000001), + GeneratePoint(10., 0.0, 2.00000001), + GeneratePoint(0.0, 1.0, 0.00000001) + ); + + KRATOS_CHECK_IS_FALSE(triangle_1.HasIntersection(triangle_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3CoplanarNoIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, 1.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.00000001, 0.00000001, 0.00000001), + GeneratePoint(-10., 0.0, -2.0), + GeneratePoint(0.0, -1.0, 0.00) + ); + + KRATOS_CHECK_IS_FALSE(triangle_1.HasIntersection(triangle_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3CoplanarPointIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, 1.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.00, 0.00, 0.0), + GeneratePoint(-10., 0.0, -2.0), + GeneratePoint(0.0, -1.0, 0.00) + ); + + KRATOS_CHECK(triangle_1.HasIntersection(triangle_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3EdgeIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, 1.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.00, 0.00, 0.0), + GeneratePoint(10., 0.0, 2.0), + GeneratePoint(0.0, -1.0, 0.00) + ); + + KRATOS_CHECK(triangle_1.HasIntersection(triangle_2)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3InsideIntersection, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.0, 0.0, 0.0), + GeneratePoint(0.0, 0.0, 4.0), + GeneratePoint(0.0, 4.0, 0.0) + ); + Triangle3D3 triangle_2( + GeneratePoint(0.0, 1.0, 1.0), + GeneratePoint(0.0, 1.0, 3.0), + GeneratePoint(0.0, 3.0, 1.0) + ); + + KRATOS_CHECK(triangle_1.HasIntersection(triangle_2)); + } + + /** + * Test an overlaping box and triangle (intersects a triangle edge) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3IntersectionBoxEdge, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + Point point_1( 0.3, 0.3,-0.3); + Point point_2( 1.0, 1.0, 1.0); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3(-0.3, 0.3, 0.3); + Point point_4( 1.0, 1.0, 1.0); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5( 0.3,-0.3, 0.3); + Point point_6( 1.0, 1.0, 1.0); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + } + + /** + * Test an overlaping box and triangle (intersects a triangle node) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3IntersectionBoxNode, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + Point point_1(-0.5, 0.8,-0.3); + Point point_2( 0.5, 1.2, 0.3); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + + Point point_3(-0.3,-0.5, 0.8); + Point point_4( 0.3, 0.5, 1.2); + KRATOS_CHECK(geom->HasIntersection(point_3, point_4)); + + Point point_5( 1.2, 0.3, 0.5); + Point point_6( 0.8,-0.3,-0.5); + KRATOS_CHECK(geom->HasIntersection(point_5, point_6)); + } + + /** + * Test an overlaping box and triangle (intersects the triangle face) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3IntersectionBoxPlane, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + Point point_1( 0.0, 0.0, 0.0); + Point point_2( 0.4, 0.5, 0.6); + KRATOS_CHECK(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test a non overlaping box and triangle HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3IntersectionBoxNoIntersect, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + Point point_1( 0.4, 0.5, 0.6); + Point point_2( 1.0, 1.0, 1.0); + KRATOS_CHECK_IS_FALSE(geom->HasIntersection(point_1, point_2)); + } + + /** + * Test an overlaping non-cubic box and triangle (intersects a triangle edge) HasIntersection + */ + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongXPlaneX, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.55, -0.25, 0.25), + GeneratePoint(0.50, -0.25, 0.75), + GeneratePoint(0.50, 0.25, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(2.0, 1.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongXPlaneY, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.50, 0.25), + GeneratePoint(-0.25, 0.55, 0.75), + GeneratePoint( 0.25, 0.50, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(2.0, 1.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongXPlaneZ, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.25, 0.50), + GeneratePoint(-0.25, 0.75, 0.50), + GeneratePoint( 0.25, 0.25, 0.55) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(2.0, 1.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongYPlaneX, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.55, -0.25, 0.25), + GeneratePoint(0.50, -0.25, 0.75), + GeneratePoint(0.50, 0.25, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 2.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongYPlaneY, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.50, 0.25), + GeneratePoint(-0.25, 0.55, 0.75), + GeneratePoint( 0.25, 0.50, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 2.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongYPlaneZ, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.25, 0.50), + GeneratePoint(-0.25, 0.75, 0.50), + GeneratePoint( 0.25, 0.25, 0.55) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 2.0, 1.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongZPlaneX, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(0.55, -0.25, 0.25), + GeneratePoint(0.50, -0.25, 0.75), + GeneratePoint(0.50, 0.25, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 1.0, 2.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongZPlaneY, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.50, 0.25), + GeneratePoint(-0.25, 0.55, 0.75), + GeneratePoint( 0.25, 0.50, 0.25) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 1.0, 2.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3AABoxIntersectionNonEquilaterElongZPlaneZ, KratosCoreGeometriesFastSuite) { + Triangle3D3 triangle_1( + GeneratePoint(-0.25, 0.25, 0.50), + GeneratePoint(-0.25, 0.75, 0.50), + GeneratePoint( 0.25, 0.25, 0.55) + ); + + auto aabb_min = GeneratePoint(0.0, 0.0, 0.0); + auto aabb_max = GeneratePoint(1.0, 1.0, 2.0); + + KRATOS_CHECK(triangle_1.HasIntersection(*aabb_min, *aabb_max)); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3ShapeFunctionsValues, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + array_1d coord(3); + coord[0] = 1.0 / 2.0; + coord[1] = 1.0 / 8.0; + coord[2] = 0.0; + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(0, coord), 0.375, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(1, coord), 0.5, TOLERANCE); + KRATOS_CHECK_NEAR(geom->ShapeFunctionValue(2, coord), 0.125, TOLERANCE); + CrossCheckShapeFunctionsValues(*geom); + } + + KRATOS_TEST_CASE_IN_SUITE(Triangle3D3ShapeFunctionsLocalGradients, KratosCoreGeometriesFastSuite) { + auto geom = GenerateEquilateralTriangle3D3(); + TestAllShapeFunctionsLocalGradients(*geom); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/global_pointers/test_global_pointer.cpp b/kratos/tests/cpp_tests/global_pointers/test_global_pointer.cpp new file mode 100644 index 000000000000..3f5657697475 --- /dev/null +++ b/kratos/tests/cpp_tests/global_pointers/test_global_pointer.cpp @@ -0,0 +1,195 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos A. Roig + +#include "testing/testing.h" +#include "includes/global_pointer.h" + +namespace Kratos { +namespace Testing { + +class TestClass { + private: + TestClass() {} + + public: + TestClass(int MagicNbr) { this->mMagicNbr = MagicNbr; } + TestClass(const TestClass & rOther) { this->mMagicNbr = rOther.mMagicNbr; } + + ~TestClass() {} + + int getVar() const { return this->mMagicNbr; } + + void setVar(int MagicNbr) { this->mMagicNbr = MagicNbr; } + + int mMagicNbr; +}; + +// Basic Type +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateRaw, KratosCoreFastSuite) +{ + int sample_var = 1337; + + auto from_raw = GlobalPointer(&sample_var); + + KRATOS_CHECK_EQUAL(*from_raw, sample_var); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateConstRaw, KratosCoreFastSuite) +{ + const int sample_var = 1337; + + auto from_raw = GlobalPointer(&sample_var); + + KRATOS_CHECK_EQUAL(*from_raw, sample_var); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerModifyRaw, KratosCoreFastSuite) +{ + int sample_var = 1337; + int new_value = 42; + + auto from_raw = GlobalPointer(&sample_var); + *from_raw = new_value; + + KRATOS_CHECK_EQUAL(*from_raw, new_value); +} + +// Class +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateClass, KratosCoreFastSuite) +{ + TestClass sample_var(1337); + + auto from_raw = GlobalPointer(&sample_var); + + KRATOS_CHECK_EQUAL(from_raw->getVar(), sample_var.getVar()); + KRATOS_CHECK_EQUAL((*from_raw).getVar(), sample_var.getVar()); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateConstClass, KratosCoreFastSuite) +{ + const TestClass sample_var(1337); + + auto from_raw = GlobalPointer(&sample_var); + + KRATOS_CHECK_EQUAL(from_raw->getVar(), sample_var.getVar()); + KRATOS_CHECK_EQUAL((*from_raw).getVar(), sample_var.getVar()); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerModifyClass, KratosCoreFastSuite) +{ + TestClass sample_var(1337); + + auto from_raw = GlobalPointer(&sample_var); + + from_raw->setVar(42); + sample_var.setVar(42); + + KRATOS_CHECK_EQUAL(from_raw->getVar(), sample_var.getVar()); + KRATOS_CHECK_EQUAL((*from_raw).getVar(), sample_var.getVar()); +} + +// Kratos::shared_ptr +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateSharedPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + + auto sample_var = PtrType(new TestClass(1337)); + auto from_shared_ptr = GlobalPointer(sample_var); + + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), sample_var->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), sample_var->getVar()); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateConstSharedPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + + const auto sample_var = PtrType(new TestClass(1337)); + auto from_shared_ptr = GlobalPointer(sample_var); + + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), sample_var->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), sample_var->getVar()); +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerModifySharedPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + + auto sample_var = PtrType(new TestClass(1337)); + auto from_shared_ptr = GlobalPointer(sample_var); + + from_shared_ptr->setVar(42); + sample_var->setVar(42); + + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), sample_var->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), sample_var->getVar()); +} + +// Kratos::weak_ptr +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateWeakPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + typedef Kratos::weak_ptr WeakPtrType; + + auto sample_var = PtrType(new TestClass(1337)); + WeakPtrType weak_var = sample_var; + + auto from_shared_ptr = GlobalPointer(sample_var); + + if(weak_var.lock()) { + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), weak_var.lock()->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), weak_var.lock()->getVar()); + } else { + KRATOS_CHECK_EQUAL(strcmp("Error", "Unable to lock Kratos::weakptr"), 0); + } +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerCreateConstWeakPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + typedef Kratos::weak_ptr WeakPtrType; + + auto sample_var = PtrType(new TestClass(1337)); + const WeakPtrType weak_var = sample_var; + + auto from_shared_ptr = GlobalPointer(weak_var); + + if(weak_var.lock()) { + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), weak_var.lock()->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), weak_var.lock()->getVar()); + } else { + KRATOS_CHECK_EQUAL(strcmp("Error", "Unable to lock Kratos::weakptr"), 0); + } +} + +KRATOS_TEST_CASE_IN_SUITE(GlobalPointerModifyWeakPtr, KratosCoreFastSuite) +{ + typedef Kratos::shared_ptr PtrType; + typedef Kratos::weak_ptr WeakPtrType; + + auto sample_var = PtrType(new TestClass(1337)); + WeakPtrType weak_var = sample_var; + + auto from_shared_ptr = GlobalPointer(sample_var); + + if(weak_var.lock()) { + from_shared_ptr->setVar(42); + weak_var.lock()->setVar(42); + + KRATOS_CHECK_EQUAL(from_shared_ptr->getVar(), weak_var.lock()->getVar()); + KRATOS_CHECK_EQUAL((*from_shared_ptr).getVar(), weak_var.lock()->getVar()); + } else { + KRATOS_CHECK_EQUAL(strcmp("Error", "Unable to lock Kratos::weakptr"), 0); + } +} + +} // namespace Testing +} // namespace Kratos diff --git a/kratos/tests/cpp_tests/input_output/test_logger.cpp b/kratos/tests/cpp_tests/input_output/test_logger.cpp new file mode 100644 index 000000000000..e646174ddcd4 --- /dev/null +++ b/kratos/tests/cpp_tests/input_output/test_logger.cpp @@ -0,0 +1,297 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + + +// Project includes +#include "testing/testing.h" +#include "input_output/logger.h" +#include "input_output/logger_table_output.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(LoggerMessageStream, KratosCoreFastSuite) + { + LoggerMessage message("label"); + + message << "Test message with number " << 12 << 'e' << "00"; + + KRATOS_CHECK_C_STRING_EQUAL(message.GetLabel().c_str(), "label"); + KRATOS_CHECK_C_STRING_EQUAL(message.GetMessage().c_str(), "Test message with number 12e00"); + KRATOS_CHECK_EQUAL(message.GetSeverity(), LoggerMessage::Severity::INFO); + KRATOS_CHECK_EQUAL(message.GetCategory(), LoggerMessage::Category::STATUS); + KRATOS_CHECK_EQUAL(message.GetLocation().GetFileName(), "Unknown"); + KRATOS_CHECK_EQUAL(message.GetLocation().GetFunctionName(), "Unknown"); + KRATOS_CHECK_EQUAL(message.GetLocation().GetLineNumber(), -1); + + message << LoggerMessage::Severity::DETAIL + << LoggerMessage::Category::CRITICAL + << KRATOS_CODE_LOCATION << std::endl; + + KRATOS_CHECK_C_STRING_EQUAL(message.GetMessage().c_str(), "Test message with number 12e00\n"); + KRATOS_CHECK_EQUAL(message.GetSeverity(), LoggerMessage::Severity::DETAIL); + KRATOS_CHECK_EQUAL(message.GetCategory(), LoggerMessage::Category::CRITICAL); + KRATOS_CHECK_NOT_EQUAL(message.GetLocation().GetFileName().find("test_logger.cpp"), std::string::npos); + KRATOS_CHECK_EQUAL(message.GetLocation().GetFunctionName(), KRATOS_CURRENT_FUNCTION); + KRATOS_CHECK_EQUAL(message.GetLocation().GetLineNumber(), 40); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerOutput, KratosCoreFastSuite) + { + std::stringstream buffer; + LoggerOutput output(buffer); + + LoggerMessage message("label"); + message << "Test message with number " << 12 << 'e' << "00"; + + output.WriteMessage(message); + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "label: Test message with number 12e00"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStream, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + Logger("TestLabel") << "Test message with number " << 12 << 'e' << "00"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestLabel: Test message with number 12e00"); + + Logger("TestDetail") << Logger::Severity::DETAIL << "This log has detailed severity and will not be printed in output " + << Logger::Category::CRITICAL << std::endl; + + // The message has DETAIL severity and should not be written + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestLabel: Test message with number 12e00"); + } + + KRATOS_TEST_CASE_IN_SUITE(CheckPoint, KratosCoreFastSuite) + { + std::stringstream buffer; + LoggerOutput output(buffer); + + KRATOS_CHECK_POINT("TestCheckPoint") << "The value in check point is " << 3.14; + +#if defined(KRATOS_ENABLE_CHECK_POINT) + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestCheckPoint: The value in check point is 3.14"); +#else + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), ""); // should print noting +#endif + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamInfo, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + KRATOS_INFO("TestInfo") << "Test info message"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestInfo: Test info message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamInfoIf, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + KRATOS_INFO_IF("TestInfo", true) << "Test info message"; + KRATOS_INFO_IF("TestInfo", false) << "This should not appear"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestInfo: Test info message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamInfoOnce, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_INFO_ONCE("TestInfo") << "Test info message - " << i; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestInfo: Test info message - 0"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamInfoFirst, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_INFO_FIRST_N("TestInfo", 4) << "."; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestInfo: .TestInfo: .TestInfo: .TestInfo: ."); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamWarning, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + KRATOS_WARNING("TestWarning") << "Test warning message"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestWarning: Test warning message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamWarningIf, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + KRATOS_WARNING_IF("TestWarning", true) << "Test warning message"; + KRATOS_WARNING_IF("TestWarning", false) << "This should not appear"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestWarning: Test warning message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamWarningOnce, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_WARNING_ONCE("TestWarning") << "Test warning message - " << i; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestWarning: Test warning message - 0"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamWarningFirst, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_WARNING_FIRST_N("TestWarning", 4) << "."; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestWarning: .TestWarning: .TestWarning: .TestWarning: ."); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamDetail, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + p_output->SetSeverity(LoggerMessage::Severity::DETAIL); + Logger::AddOutput(p_output); + + KRATOS_DETAIL("TestDetail") << "Test detail message"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestDetail: Test detail message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamDetailIf, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + p_output->SetSeverity(LoggerMessage::Severity::DETAIL); + Logger::AddOutput(p_output); + + KRATOS_DETAIL_IF("TestDetail", true) << "Test detail message"; + KRATOS_DETAIL_IF("TestDetail", false) << "This should not appear"; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestDetail: Test detail message"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamDetailOnce, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + p_output->SetSeverity(LoggerMessage::Severity::DETAIL); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_DETAIL_ONCE("TestDetail") << "Test detail message - " << i; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestDetail: Test detail message - 0"); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerStreamDetailFirst, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerOutput(buffer)); + p_output->SetSeverity(LoggerMessage::Severity::DETAIL); + Logger::AddOutput(p_output); + + for(std::size_t i = 0; i < 10; i++) { + KRATOS_DETAIL_FIRST_N("TestDetail", 4) << "."; + } + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), "TestDetail: .TestDetail: .TestDetail: .TestDetail: ."); + } + + KRATOS_TEST_CASE_IN_SUITE(LoggerTableOutput, KratosCoreFastSuite) + { + static std::stringstream buffer; + LoggerOutput::Pointer p_output(new LoggerTableOutput(buffer, {"Time Step ", "Iteration Number ", "Convergence ", "Is converged"})); + Logger::AddOutput(p_output); + p_output->WriteHeader(); + std::stringstream reference_output; + reference_output << "Time Step Iteration Number Convergence Is converged " << std::endl; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), reference_output.str().c_str()); + + std::size_t time_step = 1; + Logger("Time Step") << time_step << std::endl; + reference_output << "1 "; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), reference_output.str().c_str()); + + Logger("Label") << "This log has a lable which is not in the output columns and will not be printed in output " << std::endl; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), reference_output.str().c_str()); + + double convergence = 0.00; + for(time_step = 2;time_step < 4; time_step++){ + Logger("Time Step") << time_step << std::endl; + for(int iteration_number = 1 ; iteration_number < 3; iteration_number++){ + convergence = 0.3 / (iteration_number * time_step); + Logger("Iteration Number") << iteration_number << std::endl; + Logger("Convergence") << convergence << std::endl; + } + if(convergence < 0.06) { + Logger("Is converged") << "Yes" << std::endl; + } + else { + Logger("Is converged") << "No" << std::endl; + } + + } + + reference_output << std::endl << "2 1 0.15 "; + reference_output << std::endl << " 2 0.075 No "; + reference_output << std::endl << "3 1 0.1 "; + reference_output << std::endl << " 2 0.05 Yes "; + + KRATOS_CHECK_C_STRING_EQUAL(buffer.str().c_str(), reference_output.str().c_str()); + + std::cout << std::endl; + std::cout << buffer.str() << std::endl; + + } + + } // namespace Testing +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/modified_shape_functions/test_tetrahedra_3d_4_ausas_modified_shape_functions.cpp b/kratos/tests/cpp_tests/modified_shape_functions/test_tetrahedra_3d_4_ausas_modified_shape_functions.cpp new file mode 100644 index 000000000000..da5fc3fbdaa5 --- /dev/null +++ b/kratos/tests/cpp_tests/modified_shape_functions/test_tetrahedra_3d_4_ausas_modified_shape_functions.cpp @@ -0,0 +1,1290 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +#include "includes/gid_io.h" +#include "utilities/divide_tetrahedra_3d_4.h" +#include "modified_shape_functions/tetrahedra_3d_4_ausas_modified_shape_functions.h" + +namespace Kratos +{ + namespace Testing + { + + KRATOS_TEST_CASE_IN_SUITE(AusasModifiedShapeFunctionsTetrahedra3D4Horizontal, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + base_model_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4AusasModifiedShapeFunctions tetrahedra_ausas_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_ausas_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + tetrahedra_ausas_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2, + pos_ext_face_sh_func_3, neg_ext_face_sh_func_3; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2, + pos_ext_face_sh_func_gradients_3, neg_ext_face_sh_func_gradients_3; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2, + pos_ext_face_weights_3, neg_ext_face_weights_3; + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_3, + pos_ext_face_sh_func_gradients_3, + pos_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_3, + neg_ext_face_sh_func_gradients_3, + neg_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + tetrahedra_ausas_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2, + area_normals_pos_face_3, area_normals_neg_face_3; + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_3, 3, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_3, 3, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,3), 1.00, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,3), 0.00, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,3), 0.00, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(2,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,2), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,3), 0.00, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 0.08333333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(2), 0.02083333333, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,2), 0.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,3), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,3), 0.0, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.125, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,3), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.433013, 10e-5); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(1), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](2), 0.125, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,3), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,3), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](2), 0.0, tolerance); + + // Check face 3 values + KRATOS_CHECK_EQUAL(pos_ext_face_weights_3.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_3.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_3.size2(), 4); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_3.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(0), 0.5, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_3.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](2), -0.5, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), -0.125, tolerance); + + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.125, tolerance); + } + + + KRATOS_TEST_CASE_IN_SUITE(AusasModifiedShapeFunctionsTetrahedra3D4Oblique, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + base_model_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4AusasModifiedShapeFunctions tetrahedra_ausas_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_ausas_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + tetrahedra_ausas_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2, + pos_ext_face_sh_func_3, neg_ext_face_sh_func_3; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2, + pos_ext_face_sh_func_gradients_3, neg_ext_face_sh_func_gradients_3; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2, + pos_ext_face_weights_3, neg_ext_face_weights_3; + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_3, + pos_ext_face_sh_func_gradients_3, + pos_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_3, + neg_ext_face_sh_func_gradients_3, + neg_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + tetrahedra_ausas_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2, + area_normals_pos_face_3, area_normals_neg_face_3; + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_3, 3, GeometryData::GI_GAUSS_1); + + tetrahedra_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_3, 3, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,3), 0.75, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,0), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,1), 0.50, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,2), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,3), 0.50, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,0), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,1), 0.75, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,2), 0.00, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,3), 0.25, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 0.75, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 0.00, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,3), 0.00, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 0.00, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,3), 0.00, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,1), 0.00, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,2), 0.75, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,3), 0.00, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(positive_side_weights(1), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(positive_side_weights(2), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(2), 0.02083333333, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,2), 0.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,3), 1.0/3.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,3), 1.0/3.0, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(positive_interface_side_weights(1), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(negative_interface_side_weights(1), 0.176777, 1e-6); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.216506, 10e-5); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(1), 0.433013, 10e-5); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](0), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](1), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](2), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.125, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,3), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](1,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.125, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(1), 0.250, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](1), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + + // Check face 3 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_3(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,2), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,2), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](2), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](2), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](2), -0.125, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](0), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](2), -0.125, 1e-6); + + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](0), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](2), 0.125, 1e-6); + } + + + KRATOS_TEST_CASE_IN_SUITE(AusasModifiedShapeFunctionsTetrahedra3D4Volumes, KratosCoreFastSuite) + { + Model current_model; + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 2.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 1.0, 2.0, 0.0); + base_model_part.CreateNewNode(4, 1.0, 2.0, 2.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -0.5; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -0.5; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4AusasModifiedShapeFunctions tetrahedra_ausas_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_ausas_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_2); + + tetrahedra_ausas_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_2); + + const double tolerance = 1e-10; + + // Check Gauss pts. weights + const unsigned int n_gauss_pos = positive_side_weights.size(); + const unsigned int n_gauss_neg = negative_side_weights.size(); + + double pos_vol = 0.0; + for (unsigned int i=0; i>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4ModifiedShapeFunctions tetrahedra_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + tetrahedra_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2, + pos_ext_face_sh_func_3, neg_ext_face_sh_func_3; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2, + pos_ext_face_sh_func_gradients_3, neg_ext_face_sh_func_gradients_3; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2, + pos_ext_face_weights_3, neg_ext_face_weights_3; + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_3, + pos_ext_face_sh_func_gradients_3, + pos_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_3, + neg_ext_face_sh_func_gradients_3, + neg_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + tetrahedra_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2, + area_normals_pos_face_3, area_normals_neg_face_3; + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_3, 3, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_3, 3, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,3), 0.625, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 0.375, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,3), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 0.375, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,3), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,1), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,2), 0.375, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,3), 0.375, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 0.08333333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(2), 0.02083333333, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,2), 1.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,3), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,3), 0.5, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.125, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.433013, 10e-5); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(1), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[1](2), 0.125, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[1](2), 0.0, tolerance); + + // Check face 3 values + KRATOS_CHECK_EQUAL(pos_ext_face_weights_3.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_3.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_3.size2(), 4); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_3.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(0), 0.5, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_3.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](2), -0.5, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), -0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.125, tolerance); + } + + + KRATOS_TEST_CASE_IN_SUITE(ModifiedShapeFunctionsTetrahedra3D4Oblique, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + base_model_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4ModifiedShapeFunctions tetrahedra_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + tetrahedra_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2, + pos_ext_face_sh_func_3, neg_ext_face_sh_func_3; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2, + pos_ext_face_sh_func_gradients_3, neg_ext_face_sh_func_gradients_3; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2, + pos_ext_face_weights_3, neg_ext_face_weights_3; + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_3, + pos_ext_face_sh_func_gradients_3, + pos_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_3, + neg_ext_face_sh_func_gradients_3, + neg_ext_face_weights_3, + 3, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + tetrahedra_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2, + area_normals_pos_face_3, area_normals_neg_face_3; + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_3, 3, GeometryData::GI_GAUSS_1); + + tetrahedra_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_3, 3, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.250, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,3), 0.500, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,1), 0.250, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,2), 0.250, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(1,3), 0.375, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,1), 0.500, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,2), 0.125, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(2,3), 0.250, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 0.500, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,3), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 0.375, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,3), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,0), 0.125, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,1), 0.250, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,2), 0.500, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(2,3), 0.125, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(positive_side_weights(1), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(positive_side_weights(2), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 0.04166666666, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 0.02083333333, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(2), 0.02083333333, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[1](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[2](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[2](3,2), 1.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(1,3), 1.0/6.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(1,3), 1.0/6.0, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(positive_interface_side_weights(1), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.176777, 1e-6); + KRATOS_CHECK_NEAR(negative_interface_side_weights(1), 0.176777, 1e-6); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[1](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](3,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[1](3,2), 1.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,3), 0.5, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(1,3), 2.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.216506, 10e-5); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(1), 0.433013, 10e-5); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.216506, 10e-5); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](0), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](1), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[1](2), 0.250, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.125, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,3), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.250, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](0), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[1](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,3), 0.5, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(1,3), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.125, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(1), 0.250, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,3), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](1), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[1](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + + // Check face 3 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_3[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_3(0), 0.125, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(0,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_3(1,3), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[0](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](0,2), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](1,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](2,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_3[1](3,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(0), 0.250, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_3(1), 0.125, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_3[0](2), -0.125, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[0](2), -0.25, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_3[1](2), -0.125, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](0), -0.125, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(positive_side_area_normals[1](2), -0.125, 1e-6); + + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](0), 0.125, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](1), 0.0, 1e-6); + KRATOS_CHECK_NEAR(negative_side_area_normals[1](2), 0.125, 1e-6); + } + + + KRATOS_TEST_CASE_IN_SUITE(ModifiedShapeFunctionsTetrahedra3D4Volumes, KratosCoreFastSuite) + { + Model current_model; + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 2.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 1.0, 2.0, 0.0); + base_model_part.CreateNewNode(4, 1.0, 2.0, 2.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -0.5; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -0.5; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Tetrahedra3D4ModifiedShapeFunctions tetrahedra_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + tetrahedra_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_2); + + tetrahedra_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_2); + + const double tolerance = 1e-10; + + // Check Gauss pts. weights + const unsigned int n_gauss_pos = positive_side_weights.size(); + const unsigned int n_gauss_neg = negative_side_weights.size(); + + double pos_vol = 0.0; + for (unsigned int i=0; i>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + const Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Triangle2D3AusasModifiedShapeFunctions triangle_ausas_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + triangle_ausas_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + triangle_ausas_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2; + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + triangle_ausas_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2; + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 0.0, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 1.0/4.0, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 0.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 1.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 0.0, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.50, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.0, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_2.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_2.size2(), 3); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_2.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_weights_2.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 1.0, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_2.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -1.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + } + + + KRATOS_TEST_CASE_IN_SUITE(AusasModifiedShapeFunctionsTriangle2D3Vertical, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + const Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Triangle2D3AusasModifiedShapeFunctions triangle_ausas_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + triangle_ausas_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + triangle_ausas_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2; + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + triangle_ausas_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2; + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + triangle_ausas_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 2.0/3.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 1.0/3.0, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 1.0/4.0, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 2.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 0.5, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.50, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 2.0, tolerance); + + // Check Gauss pts. outwards unit normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), 0.0, tolerance); + + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.5 * std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 2.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.5 * std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.0, tolerance); + + // Check face 1 values + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_1.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_1.size2(), 3); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_1.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_weights_1.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 1.0, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_1.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -1.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + } + } // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/modified_shape_functions/test_triangle_2d_3_modified_shape_functions.cpp b/kratos/tests/cpp_tests/modified_shape_functions/test_triangle_2d_3_modified_shape_functions.cpp new file mode 100644 index 000000000000..edc00bb05455 --- /dev/null +++ b/kratos/tests/cpp_tests/modified_shape_functions/test_triangle_2d_3_modified_shape_functions.cpp @@ -0,0 +1,725 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +#include "includes/gid_io.h" +#include "utilities/divide_triangle_2d_3.h" +#include "modified_shape_functions/triangle_2d_3_modified_shape_functions.h" + +namespace Kratos +{ + namespace Testing + { + + KRATOS_TEST_CASE_IN_SUITE(ModifiedShapeFunctionsTriangle2D3Horizontal, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + const Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Triangle2D3ModifiedShapeFunctions triangle_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + triangle_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + triangle_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2; + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal area vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + triangle_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2; + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 1.0/2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 1.0/2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 1.0/6.0, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 1.0/4.0, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 0.50, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.50, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + + // Check Gauss pts. outwards area normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 0.75, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 0.75, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.0, tolerance); + + // Check face 1 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_1(0,2), 0.75, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_1(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 0.75, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_1[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_2.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_2.size2(), 3); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_2.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_weights_2.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 1.0, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_2.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -1.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + } + + + KRATOS_TEST_CASE_IN_SUITE(ModifiedShapeFunctionsTriangle2D3Vertical, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + const Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Triangle2D3ModifiedShapeFunctions triangle_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + triangle_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface modified shape functions calculator + Matrix positive_interface_side_sh_func, negative_interface_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_interface_side_sh_func_gradients, negative_interface_side_sh_func_gradients; + Vector positive_interface_side_weights, negative_interface_side_weights; + + triangle_shape_functions.ComputeInterfacePositiveSideShapeFunctionsAndGradientsValues( + positive_interface_side_sh_func, + positive_interface_side_sh_func_gradients, + positive_interface_side_weights, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeInterfaceNegativeSideShapeFunctionsAndGradientsValues( + negative_interface_side_sh_func, + negative_interface_side_sh_func_gradients, + negative_interface_side_weights, + GeometryData::GI_GAUSS_1); + + // Call the interface outwards normal unit vector calculator + std::vector positive_side_area_normals, negative_side_area_normals; + + triangle_shape_functions.ComputePositiveSideInterfaceAreaNormals( + positive_side_area_normals, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeSideInterfaceAreaNormals( + negative_side_area_normals, + GeometryData::GI_GAUSS_1); + + // Call the external face modified shape functions calculator + Matrix pos_ext_face_sh_func_0, neg_ext_face_sh_func_0, + pos_ext_face_sh_func_1, neg_ext_face_sh_func_1, + pos_ext_face_sh_func_2, neg_ext_face_sh_func_2; + + ModifiedShapeFunctions::ShapeFunctionsGradientsType + pos_ext_face_sh_func_gradients_0, neg_ext_face_sh_func_gradients_0, + pos_ext_face_sh_func_gradients_1, neg_ext_face_sh_func_gradients_1, + pos_ext_face_sh_func_gradients_2, neg_ext_face_sh_func_gradients_2; + + Vector pos_ext_face_weights_0, neg_ext_face_weights_0, + pos_ext_face_weights_1, neg_ext_face_weights_1, + pos_ext_face_weights_2, neg_ext_face_weights_2; + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_0, + pos_ext_face_sh_func_gradients_0, + pos_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_0, + neg_ext_face_sh_func_gradients_0, + neg_ext_face_weights_0, + 0, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_1, + pos_ext_face_sh_func_gradients_1, + pos_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_1, + neg_ext_face_sh_func_gradients_1, + neg_ext_face_weights_1, + 1, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceShapeFunctionsAndGradientsValues( + pos_ext_face_sh_func_2, + pos_ext_face_sh_func_gradients_2, + pos_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceShapeFunctionsAndGradientsValues( + neg_ext_face_sh_func_2, + neg_ext_face_sh_func_gradients_2, + neg_ext_face_weights_2, + 2, + GeometryData::GI_GAUSS_1); + + // Call the exterior faces outwards normal area vector calculator + std::vector + area_normals_pos_face_0, area_normals_neg_face_0, + area_normals_pos_face_1, area_normals_neg_face_1, + area_normals_pos_face_2, area_normals_neg_face_2; + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_0, 0, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_1, 1, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputePositiveExteriorFaceAreaNormals( + area_normals_pos_face_2, 2, GeometryData::GI_GAUSS_1); + + triangle_shape_functions.ComputeNegativeExteriorFaceAreaNormals( + area_normals_neg_face_2, 2, GeometryData::GI_GAUSS_1); + + const double tolerance = 1e-10; + + // Check shape functions values + KRATOS_CHECK_NEAR(positive_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,1), 2.0/3.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func(0,2), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,0), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,1), 1.0/3.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(0,2), 1.0/2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,0), 1.0/2.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,1), 1.0/6.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func(1,2), 1.0/3.0, tolerance); + + // Check Gauss pts. weights + KRATOS_CHECK_NEAR(positive_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(0), 1.0/8.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_weights(1), 1.0/4.0, tolerance); + + // Check Gauss pts. shape functions gradients values + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_sh_func_gradients[1](2,1), 1.0, tolerance); + + // Check interface shape function values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,1), 0.50, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,1), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func(0,2), 0.25, tolerance); + + // Check interface Gauss pts. weights + KRATOS_CHECK_NEAR(positive_interface_side_weights(0), 0.50, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_weights(0), 0.50, tolerance); + + // Check Gauss pts. interface shape function gradients values + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_interface_side_sh_func_gradients[0](2,1), 1.0, tolerance); + + // Check Gauss pts. outwards area normal values + KRATOS_CHECK_NEAR(positive_side_area_normals[0](0), -0.5, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(positive_side_area_normals[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(negative_side_area_normals[0](2), 0.0, tolerance); + + // Check face 0 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,1), 0.75, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_0(0,2), 0.25, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_0(0,2), 0.75, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_0[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_0(0), 0.5*std::sqrt(2.0), tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_0[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](0), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](1), 0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_0[0](2), 0.0, tolerance); + + // Check face 1 values + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_1.size1(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_1.size2(), 3); + KRATOS_CHECK_EQUAL(pos_ext_face_sh_func_gradients_1.size(), 0); + KRATOS_CHECK_EQUAL(pos_ext_face_weights_1.size(), 0); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,0), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_1(0,2), 0.5, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_1[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_1(0), 1.0, tolerance); + + KRATOS_CHECK_EQUAL(area_normals_pos_face_1.size(), 0); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](0), -1.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](1), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_1[0](2), 0.0, tolerance); + + // Check face 2 values + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,0), 0.25, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,1), 0.75, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(pos_ext_face_weights_2(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,0), 0.75, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,1), 0.25, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_2(0,2), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,0), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](0,1), -1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,0), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](1,1), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,0), 0.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_sh_func_gradients_2[0](2,1), 1.0, tolerance); + KRATOS_CHECK_NEAR(neg_ext_face_weights_2(0), 0.5, tolerance); + + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_pos_face_2[0](2), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](0), 0.0, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](1), -0.5, tolerance); + KRATOS_CHECK_NEAR(area_normals_neg_face_2[0](2), 0.0, tolerance); + } + + + KRATOS_TEST_CASE_IN_SUITE(ModifiedShapeFunctionsTriangle2D3Areas, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 2.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 1.0, 2.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -0.5; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -0.5; + + // Set the elemental distances vector + Geometry>::Pointer p_geometry = base_model_part.Elements()[1].pGetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < p_geometry->size(); ++i) { + distances_vector(i) = (*p_geometry)[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + const Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Call the modified shape functions calculator + Triangle2D3ModifiedShapeFunctions triangle_shape_functions(p_geometry, r_elemental_distances); + Matrix positive_side_sh_func, negative_side_sh_func; + ModifiedShapeFunctions::ShapeFunctionsGradientsType positive_side_sh_func_gradients, negative_side_sh_func_gradients; + Vector positive_side_weights, negative_side_weights; + + triangle_shape_functions.ComputePositiveSideShapeFunctionsAndGradientsValues( + positive_side_sh_func, + positive_side_sh_func_gradients, + positive_side_weights, + GeometryData::GI_GAUSS_2); + + triangle_shape_functions.ComputeNegativeSideShapeFunctionsAndGradientsValues( + negative_side_sh_func, + negative_side_sh_func_gradients, + negative_side_weights, + GeometryData::GI_GAUSS_2); + + const double tolerance = 1e-10; + + // Check Gauss pts. weights + const unsigned int n_gauss_pos = positive_side_weights.size(); + const unsigned int n_gauss_neg = negative_side_weights.size(); + + double pos_area = 0.0; + for (unsigned int i=0; i disc_dist_proc(fluid_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = (fluid_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.5, 1e-12); + KRATOS_CHECK_NEAR(r_elem_dist[1], -0.5, 1e-12); + KRATOS_CHECK_NEAR(r_elem_dist[2], 0.5, 1e-12); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessPlaneApproximation2D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the element + ModelPart &fluid_part = current_model.CreateModelPart("Surface"); + fluid_part.AddNodalSolutionStepVariable(DISTANCE); + fluid_part.CreateNewNode(1, 0.0, 0.0, 0.0); + fluid_part.CreateNewNode(2, 1.0, 0.0, 0.0); + fluid_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties_0(new Properties(0)); + fluid_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties_0); + + // Generate the skin + const double plane_height = 0.5; + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(1, -1.0, plane_height, 0.0); + skin_part.CreateNewNode(2, 0.75, plane_height, 0.0); + skin_part.CreateNewNode(3, 0.75, -1.0, 0.0); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element2D2N", 1, {{1, 2}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 2, {{2, 3}}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<2> disc_dist_proc(fluid_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = (fluid_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.483157, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[1], 0.0216888, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[2], 0.380052, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessCubeInCube3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, -0.5, -0.5, -0.5); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, 0.5, -0.5, -0.5); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 0.5, 0.5, -0.5); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, -0.5, 0.5, -0.5); + Node<3>::Pointer p_point_5 = Kratos::make_shared>(5, -0.5, -0.5, 0.5); + Node<3>::Pointer p_point_6 = Kratos::make_shared>(6, 0.5, -0.5, 0.5); + Node<3>::Pointer p_point_7 = Kratos::make_shared>(7, 0.5, 0.5, 0.5); + Node<3>::Pointer p_point_8 = Kratos::make_shared>(8, -0.5, 0.5, 0.5); + + Hexahedra3D8 > geometry(p_point_1, p_point_2, p_point_3, p_point_4, p_point_5, p_point_6, p_point_7, p_point_8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 5, + "element_name": "Element3D4N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(VELOCITY); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the cube skin + const double cube_radious = 0.35; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1, -cube_radious, -cube_radious, -cube_radious); + skin_part.CreateNewNode(2, cube_radious, -cube_radious, -cube_radious); + skin_part.CreateNewNode(3, cube_radious, cube_radious, -cube_radious); + skin_part.CreateNewNode(4, -cube_radious, cube_radious, -cube_radious); + skin_part.CreateNewNode(5, -cube_radious, -cube_radious, cube_radious); + skin_part.CreateNewNode(6, cube_radious, -cube_radious, cube_radious); + skin_part.CreateNewNode(7, cube_radious, cube_radious, cube_radious); + skin_part.CreateNewNode(8, -cube_radious, cube_radious, cube_radious); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 1, { 1,2,3 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 2, { 1,3,4 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 3, { 5,6,7 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 4, { 5,7,8 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 5, { 3,6,2 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 6, { 3,7,6 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 7, { 4,5,1 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 8, { 4,8,5 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 9, { 3,4,8 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 10, { 3,8,7 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 11, { 2,1,5 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 12, { 2,5,6 }, p_properties); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_dist_elem_1 = (volume_part.ElementsBegin() + 7)->GetValue(ELEMENTAL_DISTANCES); + const auto &r_dist_elem_2 = (volume_part.ElementsEnd() - 7)->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_dist_elem_1[0], -0.15, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_1[1], 0.05, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_1[2], 0.05, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_1[3], -0.15, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_2[0], -0.05, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_2[1], 0.15, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_2[2], 0.15, 1e-6); + KRATOS_CHECK_NEAR(r_dist_elem_2[3], -0.05, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessSharpCornerInCube3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, 0.0, 0.0, 0.0); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, 1.0, 0.0, 0.0); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 1.0, 1.0, 0.0); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 0.0, 1.0, 0.0); + Node<3>::Pointer p_point_5 = Kratos::make_shared>(5, 0.0, 0.0, 1.0); + Node<3>::Pointer p_point_6 = Kratos::make_shared>(6, 1.0, 0.0, 1.0); + Node<3>::Pointer p_point_7 = Kratos::make_shared>(7, 1.0, 1.0, 1.0); + Node<3>::Pointer p_point_8 = Kratos::make_shared>(8, 0.0, 1.0, 1.0); + + Hexahedra3D8> geometry(p_point_1, p_point_2, p_point_3, p_point_4, p_point_5, p_point_6, p_point_7, p_point_8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 1, + "element_name": "Element3D4N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the corner entities + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1, 2.0, 0.5, 2.0); + skin_part.CreateNewNode(2, 2.0, 0.5, -2.0); + skin_part.CreateNewNode(3, 0.25, 0.5, 2.0); + skin_part.CreateNewNode(4, 0.25, 0.5, -2.0); + skin_part.CreateNewNode(5, 0.25, -2.0, 2.0); + skin_part.CreateNewNode(6, 0.25, -2.0, -2.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 1, {1, 2, 3}, p_properties); + skin_part.CreateNewElement("Element3D3N", 2, {2, 3, 4}, p_properties); + skin_part.CreateNewElement("Element3D3N", 3, {3, 4, 5}, p_properties); + skin_part.CreateNewElement("Element3D3N", 4, {4, 5, 6}, p_properties); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_dist_begin = (volume_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + const auto &r_dist_end = (volume_part.ElementsEnd() - 1)->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_dist_begin[0], 1.0, 1e-6); + KRATOS_CHECK_NEAR(r_dist_begin[1], 1.0, 1e-6); + KRATOS_CHECK_NEAR(r_dist_begin[2], 1.0, 1e-6); + KRATOS_CHECK_NEAR(r_dist_begin[3], 1.0, 1e-6); + KRATOS_CHECK_NEAR(r_dist_end[0], -0.406059, 1e-6); + KRATOS_CHECK_NEAR(r_dist_end[1], -0.489839, 1e-6); + KRATOS_CHECK_NEAR(r_dist_end[2], 0.388306, 1e-6); + KRATOS_CHECK_NEAR(r_dist_end[3], 0.0649427, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessHorizontalPlane3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the evil element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.214286, -0.357143, 0.0714286); + volume_part.CreateNewNode(2, 0.214286, -0.214286, 0.0714286); + volume_part.CreateNewNode(3, 0.357143, -0.214286, 0.0714286); + volume_part.CreateNewNode(4, 0.214286, -0.357143, -0.0714286); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the cube skin + const double plane_height = 0.0; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(1, -1.0, -1.0, plane_height); + skin_part.CreateNewNode(2, 1.0, -1.0, plane_height); + skin_part.CreateNewNode(3, 1.0, 1.0, plane_height); + skin_part.CreateNewNode(4, -1.0, 1.0, plane_height); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 1, {1, 2, 4}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 2, {2, 3, 4}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = (volume_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], 0.0714286, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[1], 0.0714286, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[2], 0.0714286, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[3], -0.0714286, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessPlaneApproximationSkewed3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the tetrahedron element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.0, -0.5, 0.0); + volume_part.CreateNewNode(2, 1.0, -0.5, 0.0); + volume_part.CreateNewNode(3, 0.0, 0.5, 0.0); + volume_part.CreateNewNode(4, 0.0, -0.5, 1.0); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the skin such that one edge is cut twice + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(1, -1.0, -1.0, 0.75); + skin_part.CreateNewNode(2, 1.0, -1.0, 0.75); + skin_part.CreateNewNode(3, -1.0, 1.0, 0.75); + skin_part.CreateNewNode(4, 0.75, -1.0, 1.0); + skin_part.CreateNewNode(5, 0.75, -1.0, -1.0); + skin_part.CreateNewNode(6, 0.75, 1.0, -1.0); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 1, {1,2,3}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 2, {4,5,6}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = (volume_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.569400, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[1], 0.1044875, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[2], -0.266495, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[3], 0.104487, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessPlaneApproximationVertical3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the triangular element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.0, 0.0, 0.0); + volume_part.CreateNewNode(2, 1.0, 0.0, 0.0); + volume_part.CreateNewNode(3, 0.0, 1.0, 0.0); + volume_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the skin such that there is 4 intersection pts. + // Recall that with more than 3 intersection pts. the plane + // approximation is used. Since the skin in here yields a + // uniplanar intersection, the approximated plane is the + // same one as the original intersection one. + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1, 0.5, -1.0, 1.0); + skin_part.CreateNewNode(2, 0.5, -1.0, -1.0); + skin_part.CreateNewNode(3, 0.5, 1.0, -1.0); + skin_part.CreateNewNode(4, 0.5, 1.0, 1.0); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 1, {1,2,4}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 2, {2,3,4}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const Vector elem_dist = (volume_part.ElementsBegin())->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(elem_dist[0], -0.5, 1e-10); + KRATOS_CHECK_NEAR(elem_dist[1], 0.5, 1e-10); + KRATOS_CHECK_NEAR(elem_dist[2], -0.5, 1e-10); + KRATOS_CHECK_NEAR(elem_dist[3], -0.5, 1e-10); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessOneEdgeIntersection3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the tetrahedron element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.666963, 0.800762, 0.388769); + volume_part.CreateNewNode(2, 0.731067, 0.821936, 0.422077); + volume_part.CreateNewNode(3, 0.652002, 0.85453, 0.463652); + volume_part.CreateNewNode(4, 0.684484, 0.796908, 0.48275); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the skin such that it only intersects in one edge + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(1, 0.675, 0.803109, 0.5); + skin_part.CreateNewNode(2, 0.663088, 0.808771, 0.476277); + skin_part.CreateNewNode(3, 0.685008, 0.796367, 0.479053); + skin_part.CreateNewNode(4, 0.682845, 0.794215, 0.449949); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 1, {1,2,3}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 2, {3,2,4}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check elemental distance values + const auto &r_elem_dist = volume_part.ElementsBegin()->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], 1.0, 1e-10); + KRATOS_CHECK_NEAR(r_elem_dist[1], 1.0, 1e-10); + KRATOS_CHECK_NEAR(r_elem_dist[2], 1.0, 1e-10); + KRATOS_CHECK_NEAR(r_elem_dist[3], 1.0, 1e-10); + + + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessMultipleIntersections3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the tetrahedron element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.597905, 0.597905, 0.100929); + volume_part.CreateNewNode(2, 0.608229, 0.490745, 0.204129); + volume_part.CreateNewNode(3, 0.697865, 0.493815, 0.126859); + volume_part.CreateNewNode(4, 0.65897, 0.571858, 0.175526); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the skin such that it has multiple intersections + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(1, 0.633131, 0.539808, 0.178766); + skin_part.CreateNewNode(2, 0.671961, 0.517362, 0.195651); + skin_part.CreateNewNode(3, 0.66866, 0.566563, 0.200629); + skin_part.CreateNewNode(4, 0.635672, 0.588229, 0.189664); + skin_part.CreateNewNode(5, 0.631307, 0.501763, 0.175569); + skin_part.CreateNewNode(6, 0.664311, 0.467496, 0.19268); + skin_part.CreateNewNode(7, 0.595066, 0.567432, 0.169977); + skin_part.CreateNewNode(8, 0.589401, 0.523455, 0.162424); + skin_part.CreateNewNode(9, 0.629759, 0.452428, 0.178442); + skin_part.CreateNewNode(10, 0.591444, 0.479469, 0.162781); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 1, {1,2,3}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 2, {1,3,4}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 3, {1,5,2}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 4, {2,5,6}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 5, {7,1,4}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 6, {7,8,1}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 7, {8,5,1}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 8, {9,6,5}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 9, {9,10,5}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 10, {5,10,9}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check elemental distance values + const auto &r_elem_dist = volume_part.ElementsBegin()->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.0636738, 1e-7); + KRATOS_CHECK_NEAR(r_elem_dist[1], 0.0342287, 1e-7); + KRATOS_CHECK_NEAR(r_elem_dist[2], -0.0709816, 1e-7); + KRATOS_CHECK_NEAR(r_elem_dist[3], -0.0159295, 1e-7); + + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessStandard3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the tetrahedron element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, -0.625, -1.625, 1.125); + volume_part.CreateNewNode(2, -0.5, -1.75, 1.25); + volume_part.CreateNewNode(3, -0.5, -1.75, 1.0); + volume_part.CreateNewNode(4, -0.375, -1.625, 1.125); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties_0); + + // Generate the skin such that it generates a standard intersection + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(2196, -0.542249, -1.7162, 1.23726); + skin_part.CreateNewNode(2155, -0.544766, -1.71316, 1.19334); + skin_part.CreateNewNode(2228, -0.507166, -1.69137, 1.20104); + skin_part.CreateNewNode(2220, -0.502438, -1.68588, 1.17549); + skin_part.CreateNewNode(2335, -0.457592, -1.66163, 1.20154); + skin_part.CreateNewNode(2118, -0.547284, -1.71012, 1.14943); + skin_part.CreateNewNode(2368, -0.419474, -1.62945, 1.14036); + skin_part.CreateNewNode(2318, -0.453428, -1.65552, 1.17619); + skin_part.CreateNewNode(2276, -0.462077, -1.65634, 1.14339); + skin_part.CreateNewNode(2324, -0.42378, -1.62452, 1.09704); + skin_part.CreateNewNode(2422, -0.389158, -1.5991, 1.10588); + skin_part.CreateNewNode(2263, -0.463227, -1.65498, 1.12885); + skin_part.CreateNewNode(2250, -0.464376, -1.65362, 1.11431); + skin_part.CreateNewNode(2236, -0.460832, -1.64688, 1.08915); + skin_part.CreateNewNode(2209, -0.503559, -1.68456, 1.16095); + skin_part.CreateNewNode(2190, -0.50468, -1.68323, 1.14641); + skin_part.CreateNewNode(2086, -0.550732, -1.70604, 1.10582); + skin_part.CreateNewNode(2154, -0.513394, -1.68396, 1.11361); + skin_part.CreateNewNode(2141, -0.509278, -1.67779, 1.08826); + skin_part.CreateNewNode(2049, -0.55418, -1.70196, 1.06221); + skin_part.CreateNewNode(2131, -0.510714, -1.67615, 1.07382); + skin_part.CreateNewNode(2120, -0.512149, -1.6745, 1.05938); + skin_part.CreateNewNode(2091, -0.521568, -1.67444, 1.02683); + skin_part.CreateNewNode(2021, -0.558662, -1.69672, 1.01895); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 32933, {2196,2155,2228}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 32940, {2228,2220,2335}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 32934, {2228,2118,2220}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 32937, {2155,2118,2228}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38354, {2368,2318,2276}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33145, {2368,2324,2422}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33157, {2368,2276,2263}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33163, {2368,2263,2250}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38573, {2236,2368,2250}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38576, {2324,2368,2236}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38353, {2209,2318,2220}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38355, {2318,2335,2220}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38357, {2209,2276,2318}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38356, {2118,2209,2220}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38351, {2209,2190,2276}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33155, {2118,2086,2154}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33161, {2118,2154,2190}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38350, {2118,2190,2209}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38579, {2236,2250,2141}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33160, {2263,2154,2250}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33162, {2154,2141,2250}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33164, {2263,2190,2154}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33159, {2086,2049,2154}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38577, {2131,2236,2141}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33156, {2154,2049,2141}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38580, {2049,2131,2141}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 38574, {2049,2120,2131}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33399, {2049,2091,2120}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 33393, {2049,2021,2091}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = volume_part.ElementsBegin()->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.108523, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[1], 0.0485713, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[2], 0.0764035, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[3], 0.0222594, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessBoundaryIntersection3D, KratosCoreFastSuite) + { + Model current_model; + + // Generate the tetrahedron element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(787, 0.3, 0.1, 0.5); + volume_part.CreateNewNode(629, 0.3, 0.2, 0.5); + volume_part.CreateNewNode(700, 0.4, 0.2, 0.5); + volume_part.CreateNewNode(712, 0.3, 0.1, 0.4); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 861, {787, 629, 700, 712}, p_properties_0); + + // Generate the skin such that one edge intersection is close to the boundary entity + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.CreateNewNode(345, 0.372131, 0.174194, 0.5); + skin_part.CreateNewNode(375, 0.396836, 0.16555, 0.5); + skin_part.CreateNewNode(333, 0.384461, 0.170563, 0.475061); + skin_part.CreateNewNode(384, 0.384461, 0.170563, 0.524939); + skin_part.CreateNewNode(351, 0.35857, 0.180817, 0.524898); + skin_part.CreateNewNode(310, 0.348141, 0.184661, 0.5); + skin_part.CreateNewNode(319, 0.335115, 0.192276, 0.524874); + skin_part.CreateNewNode(280, 0.325, 0.196891, 0.5); + skin_part.CreateNewNode(266, 0.335115, 0.192276, 0.475126); + skin_part.CreateNewNode(290, 0.31342, 0.204924, 0.524859); + skin_part.CreateNewNode(248, 0.302838, 0.210816, 0.5); + skin_part.CreateNewNode(236, 0.31342, 0.204924, 0.475141); + skin_part.CreateNewNode(299, 0.35857, 0.180817, 0.475102); + skin_part.CreateNewNode(285, 0.371864, 0.179378, 0.442703); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 554, {345,375,333}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1081, {375,345,384}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1295, {384,345,351}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1199, {351,310,319}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 574, {280,310,266}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1101, {310,280,319}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1193, {319,280,290}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 582, {248,280,236}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1109, {280,248,290}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 667, {280,266,236}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 562, {310,345,299}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 1089, {345,310,351}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 769, {345,333,299}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 673, {310,299,266}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 770, {299,333,285}, p_properties_1); + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<3> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + + // Check values + const auto &r_elem_dist = volume_part.ElementsBegin()->GetValue(ELEMENTAL_DISTANCES); + KRATOS_CHECK_NEAR(r_elem_dist[0], -0.0984855, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[1], -0.00883326, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[2], 0.0352186, 1e-6); + KRATOS_CHECK_NEAR(r_elem_dist[3], -0.103167, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessDoubleEmbeddedVariableComplex, KratosCoreFastSuite) + { + Model current_model; + + // Generate a triangle element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.0, 0.0, 0.0); + volume_part.CreateNewNode(2, 1.0, 0.0, 0.0); + volume_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties_0); + + // Generate the skin + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(TEMPERATURE); + skin_part.CreateNewNode(1,-0.1, 0.5,0.0); + skin_part.CreateNewNode(2, 0.1, 0.5,0.0); + skin_part.CreateNewNode(3,-0.1, 0.3,0.0); + skin_part.CreateNewNode(4, 0.1, 0.3,0.0); + skin_part.CreateNewNode(5, 0.1,-0.1,0.0); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 4, {{4,5}}, p_properties_1); + + // Set the embedded cube double variable + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(TEMPERATURE) = i_node.Y(); + } + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<2> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + disc_dist_proc.CalculateEmbeddedVariableFromSkin(TEMPERATURE, TEMPERATURE); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(1).GetValue(TEMPERATURE), 0.2, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessArrayEmbeddedVariableComplex, KratosCoreFastSuite) + { + Model current_model; + + // Generate a triangle element + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 0.0, 0.0, 0.0); + volume_part.CreateNewNode(2, 1.0, 0.0, 0.0); + volume_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties_0); + + // Generate the skin + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1,-0.1, 0.5,0.0); + skin_part.CreateNewNode(2, 0.1, 0.5,0.0); + skin_part.CreateNewNode(3,-0.1, 0.3,0.0); + skin_part.CreateNewNode(4, 0.1, 0.3,0.0); + skin_part.CreateNewNode(5, 0.1,-0.1,0.0); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties_1); + skin_part.CreateNewElement("Element2D2N", 4, {{4,5}}, p_properties_1); + + // Set the embedded cube double variable + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(VELOCITY_X) = i_node.X(); + i_node.FastGetSolutionStepValue(VELOCITY_Y) = i_node.Y(); + } + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<2> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + disc_dist_proc.CalculateEmbeddedVariableFromSkin(VELOCITY, EMBEDDED_VELOCITY); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(1).GetValue(EMBEDDED_VELOCITY_X), 0.05, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(1).GetValue(EMBEDDED_VELOCITY_Y), 0.2, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessDoubleEmbeddedVariable, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, -0.5, -0.5, 0.0); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, -0.5, 0.5, 0.0); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 0.5, 0.5, 0.0); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 0.5, -0.5, 0.0); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 7, + "element_name": "Element2D3N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.AddNodalSolutionStepVariable(TEMPERATURE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the cube skin + const double cube_radious = 0.25; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(TEMPERATURE); + skin_part.CreateNewNode(1, -cube_radious, -cube_radious, 0.0); + skin_part.CreateNewNode(2, -cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(3, cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(4, cube_radious, -cube_radious, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 4, {{4,1}}, p_properties); + + // Set the embedded cube double variable + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(TEMPERATURE) = 1.0; + } + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<2> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + disc_dist_proc.CalculateEmbeddedVariableFromSkin(TEMPERATURE, TEMPERATURE); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(TEMPERATURE), 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(TEMPERATURE), 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(TEMPERATURE), 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(TEMPERATURE), 0.0, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DiscontinuousDistanceProcessArrayEmbeddedVariable, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, -0.5, -0.5, 0.0); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, -0.5, 0.5, 0.0); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 0.5, 0.5, 0.0); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 0.5, -0.5, 0.0); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 7, + "element_name": "Element2D3N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the cube skin + const double cube_radious = 0.25; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1, -cube_radious, -cube_radious, 0.0); + skin_part.CreateNewNode(2, -cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(3, cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(4, cube_radious, -cube_radious, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 4, {{4,1}}, p_properties); + + // Set the embedded cube array variable + array_1d velocity = ZeroVector(3); + velocity[0] = 1.0; + velocity[1] = 1.0; + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(VELOCITY) = velocity; + } + + // Compute the discontinuous distance function + CalculateDiscontinuousDistanceToSkinProcess<2> disc_dist_proc(volume_part, skin_part); + disc_dist_proc.Execute(); + disc_dist_proc.CalculateEmbeddedVariableFromSkin(VELOCITY, EMBEDDED_VELOCITY); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[0], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[1], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[0], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[1], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_calculate_distance_to_skin_process.cpp b/kratos/tests/cpp_tests/processes/test_calculate_distance_to_skin_process.cpp new file mode 100644 index 000000000000..a2effe488453 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_calculate_distance_to_skin_process.cpp @@ -0,0 +1,487 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// Ruben Zorrilla +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +// #include "includes/gid_io.h" +#include "geometries/hexahedra_3d_8.h" +#include "geometries/quadrilateral_2d_4.h" +#include "processes/structured_mesh_generator_process.h" +#include "processes/calculate_distance_to_skin_process.h" + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(DistanceProcessQuadrilateral2D, KratosCoreFastSuite) + { + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 10.00, 0.00, 0.00); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 7, + "element_name": "Element2D3N" + })"); + + Model current_model; + ModelPart &surface_part = current_model.CreateModelPart("Volume"); + surface_part.AddNodalSolutionStepVariable(VELOCITY); + surface_part.AddNodalSolutionStepVariable(DISTANCE); + surface_part.AddNodalSolutionStepVariable(EMBEDDED_VELOCITY); + StructuredMeshGeneratorProcess(geometry, surface_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 2.4, 3.4, 0.0); + skin_part.CreateNewNode(902, 7.6, 3.4, 0.0); + skin_part.CreateNewNode(903, 7.6, 6.6, 0.0); + skin_part.CreateNewNode(904, 2.4, 6.6, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 901, {{901,902}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 902, {{902,903}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 903, {{903,904}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 904, {{904,901}}, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<2>(surface_part, skin_part).Execute(); + + // GidIO<> gid_io_fluid("/home/rzorrilla/Desktop/surface_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_fluid.InitializeMesh(0.00); + // gid_io_fluid.WriteMesh(surface_part.GetMesh()); + // gid_io_fluid.FinalizeMesh(); + // gid_io_fluid.InitializeResults(0, surface_part.GetMesh()); + // gid_io_fluid.WriteNodalResults(DISTANCE, surface_part.Nodes(), 0, 0); + // gid_io_fluid.FinalizeResults(); + + // GidIO<> gid_io_skin("/home/rzorrilla/Desktop/skin_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_skin.InitializeMesh(0.00); + // gid_io_skin.WriteMesh(skin_part.GetMesh()); + // gid_io_skin.FinalizeMesh(); + // gid_io_skin.InitializeResults(0, skin_part.GetMesh()); + // gid_io_skin.FinalizeResults(); + + KRATOS_CHECK_NEAR((surface_part.pGetNode(21))->FastGetSolutionStepValue(DISTANCE), -0.457143, 1e-6); + KRATOS_CHECK_NEAR((surface_part.pGetNode(22))->FastGetSolutionStepValue(DISTANCE), 0.542857, 1e-6); + KRATOS_CHECK_NEAR((surface_part.pGetNode(30))->FastGetSolutionStepValue(DISTANCE), 0.542857, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DistanceProcessSquareRing2D, KratosCoreFastSuite) + { + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 10.00, 0.00, 0.00); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 12, + "element_name": "Element2D3N" + })"); + + Model current_model; + ModelPart &surface_part = current_model.CreateModelPart("Volume"); + surface_part.AddNodalSolutionStepVariable(VELOCITY); + surface_part.AddNodalSolutionStepVariable(DISTANCE); + surface_part.AddNodalSolutionStepVariable(EMBEDDED_VELOCITY); + StructuredMeshGeneratorProcess(geometry, surface_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 2.4, 2.4, 0.0); + skin_part.CreateNewNode(902, 7.6, 2.4, 0.0); + skin_part.CreateNewNode(903, 7.6, 7.6, 0.0); + skin_part.CreateNewNode(904, 2.4, 7.6, 0.0); + skin_part.CreateNewNode(905, 3.9, 3.9, 0.0); + skin_part.CreateNewNode(906, 6.1, 3.9, 0.0); + skin_part.CreateNewNode(907, 6.1, 6.1, 0.0); + skin_part.CreateNewNode(908, 3.9, 6.1, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 901, {{901,902}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 902, {{902,903}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 903, {{903,904}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 904, {{904,901}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 905, {{905,906}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 906, {{906,907}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 907, {{907,908}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 908, {{908,905}}, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<2>(surface_part, skin_part).Execute(); + + KRATOS_CHECK_NEAR((surface_part.pGetNode(86))->FastGetSolutionStepValue(DISTANCE), 0.266667, 1e-6); + KRATOS_CHECK_NEAR((surface_part.pGetNode(88))->FastGetSolutionStepValue(DISTANCE), -0.1, 1e-6); + KRATOS_CHECK_NEAR((surface_part.pGetNode(112))->FastGetSolutionStepValue(DISTANCE), -0.566667, 1e-6); + KRATOS_CHECK_NEAR((surface_part.pGetNode(138))->FastGetSolutionStepValue(DISTANCE), 0.733333, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(HorizontalPlaneDistanceProcess, KratosCoreFastSuite) + { + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point2 = Kratos::make_shared>(2, 10.00, 0.00, 0.00); + Node<3>::Pointer p_point3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point4 = Kratos::make_shared>(4, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point5 = Kratos::make_shared>(5, 0.00, 0.00, 10.00); + Node<3>::Pointer p_point6 = Kratos::make_shared>(6, 10.00, 0.00, 10.00); + Node<3>::Pointer p_point7 = Kratos::make_shared>(7, 10.00, 10.00, 10.00); + Node<3>::Pointer p_point8 = Kratos::make_shared>(8, 0.00, 10.00, 10.00); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 1, + "element_name": "Element3D4N" + })"); + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(VELOCITY); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.AddNodalSolutionStepVariable(EMBEDDED_VELOCITY); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 0.0, 0.0, 2.0); + skin_part.CreateNewNode(902, 10.0, 0.0, 2.0); + skin_part.CreateNewNode(903, 10.0, 10.0, 2.0); + skin_part.CreateNewNode(904, 0.0, 10.0, 2.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 901, { 901,902,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 902, { 901,903,904 }, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<3>(volume_part, skin_part).Execute(); + + for (auto& node : volume_part.Nodes()) + if (fabs(node.GetSolutionStepValue(DISTANCE)) < 1.00e16) { // There are no propagation in this version so I avoid numeric_limit::max() one + auto distance = fabs(node.Z() - 2.00); + KRATOS_CHECK_NEAR(node.GetSolutionStepValue(DISTANCE), distance, 1e-6); + } + } + + KRATOS_TEST_CASE_IN_SUITE(HorizontalPlaneZeroDistanceProcess, KratosCoreFastSuite) + { + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point2 = Kratos::make_shared>(2, 10.00, 0.00, 0.00); + Node<3>::Pointer p_point3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point4 = Kratos::make_shared>(4, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point5 = Kratos::make_shared>(5, 0.00, 0.00, 10.00); + Node<3>::Pointer p_point6 = Kratos::make_shared>(6, 10.00, 0.00, 10.00); + Node<3>::Pointer p_point7 = Kratos::make_shared>(7, 10.00, 10.00, 10.00); + Node<3>::Pointer p_point8 = Kratos::make_shared>(8, 0.00, 10.00, 10.00); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 2, + "element_name": "Element3D4N" + })"); + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(VELOCITY); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.AddNodalSolutionStepVariable(EMBEDDED_VELOCITY); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 0.0, 0.0, 5.0); + skin_part.CreateNewNode(902, 10.0, 0.0, 5.0); + skin_part.CreateNewNode(903, 10.0, 10.0, 5.0); + skin_part.CreateNewNode(904, 0.0, 10.0, 5.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 901, { 901,902,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 902, { 901,903,904 }, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<3>(volume_part, skin_part).Execute(); + + for (auto& node : volume_part.Nodes()) + if (fabs(node.GetSolutionStepValue(DISTANCE)) < 1.00e16) { // There are no propagation in this version so I avoid numeric_limit::max() one + auto distance = fabs(node.Z() - 5.00); + KRATOS_CHECK_NEAR(node.GetSolutionStepValue(DISTANCE), distance, 1e-6); + } + + } + + KRATOS_TEST_CASE_IN_SUITE(TetrahedraInCubeDistanceProcess, KratosCoreFastSuite) + { + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point2 = Kratos::make_shared>(2, 10.00, 0.00, 0.00); + Node<3>::Pointer p_point3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point4 = Kratos::make_shared>(4, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point5 = Kratos::make_shared>(5, 0.00, 0.00, 10.00); + Node<3>::Pointer p_point6 = Kratos::make_shared>(6, 10.00, 0.00, 10.00); + Node<3>::Pointer p_point7 = Kratos::make_shared>(7, 10.00, 10.00, 10.00); + Node<3>::Pointer p_point8 = Kratos::make_shared>(8, 0.00, 10.00, 10.00); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 10, + "element_name": "Element3D4N" + })"); + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(VELOCITY); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.AddNodalSolutionStepVariable(EMBEDDED_VELOCITY); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 2.0, 2.0, 2.0); + skin_part.CreateNewNode(902, 6.0, 2.0, 2.0); + skin_part.CreateNewNode(903, 4.0, 6.0, 2.0); + skin_part.CreateNewNode(904, 4.0, 4.0, 7.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 901, { 901,902,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 902, { 901,904,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 903, { 902,903,904 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 904, { 901,902,904 }, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<3>(volume_part, skin_part).Execute(); + + KRATOS_CHECK_NEAR(volume_part.GetNode(135).GetSolutionStepValue(DISTANCE), 1.414213, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(136).GetSolutionStepValue(DISTANCE), 1.414213, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(137).GetSolutionStepValue(DISTANCE), 1.414213, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(256).GetSolutionStepValue(DISTANCE), 1.00, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(257).GetSolutionStepValue(DISTANCE), 1.00, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(258).GetSolutionStepValue(DISTANCE), 1.00, 1e-6); + + //GidIO<> gid_io_fluid("C:/Temp/Tests/distance_test_fluid", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + //gid_io_fluid.InitializeMesh(0.00); + //gid_io_fluid.WriteMesh(volume_part.GetMesh()); + //gid_io_fluid.FinalizeMesh(); + //gid_io_fluid.InitializeResults(0, volume_part.GetMesh()); + //gid_io_fluid.WriteNodalResults(DISTANCE, volume_part.Nodes(), 0, 0); + //gid_io_fluid.FinalizeResults(); + + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra3IntersectionDistanceProcess, KratosCoreFastSuite) + { + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 1.00, 1.00, -10.00); + volume_part.CreateNewNode(2, 1.00, 1.00, 10.00); + volume_part.CreateNewNode(3, 10.00, 0.00, 0.00); + volume_part.CreateNewNode(4, 0.00, 0.00, 0.00); + + Properties::Pointer p_properties(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, { 1,2,3,4 }, p_properties); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(11, 0.0, 0.0, 2.0); + skin_part.CreateNewNode(12, 12.0, 0.0, 2.0); + skin_part.CreateNewNode(13, 0.0, 12.0, 2.0); + skin_part.CreateNewElement("Element3D3N", 1, { 11,12,13 }, p_properties); + + CalculateDistanceToSkinProcess<3>(volume_part, skin_part).Execute(); + + KRATOS_CHECK_NEAR(volume_part.GetNode(1).GetSolutionStepValue(DISTANCE), 12.00, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(2).GetSolutionStepValue(DISTANCE), 8.00, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(3).GetSolutionStepValue(DISTANCE), 2.00, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(4).GetSolutionStepValue(DISTANCE), 2.00, 1e-6); + + + } + + KRATOS_TEST_CASE_IN_SUITE(Tetrahedra5IntersectionDistanceProcess, KratosCoreFastSuite) + { + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.CreateNewNode(1, 2.50, 2.50, 0.00); + volume_part.CreateNewNode(2, 2.50, 2.50, 2.50); + volume_part.CreateNewNode(3, 2.50, 5.00, 2.50); + volume_part.CreateNewNode(4, 5.00, 5.00, 2.50); + + Properties::Pointer p_properties(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 1, { 1,2,3,4 }, p_properties); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 2.0, 2.0, 2.0); + skin_part.CreateNewNode(902, 6.0, 2.0, 2.0); + skin_part.CreateNewNode(903, 4.0, 6.0, 2.0); + skin_part.CreateNewNode(904, 4.0, 4.0, 7.0); + + skin_part.CreateNewElement("Element3D3N", 901, { 901,902,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 902, { 901,904,903 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 903, { 902,903,904 }, p_properties); + skin_part.CreateNewElement("Element3D3N", 904, { 901,902,904 }, p_properties); + + CalculateDistanceToSkinProcess<3>(volume_part, skin_part).Execute(); + + KRATOS_CHECK_NEAR(volume_part.GetNode(1).GetSolutionStepValue(DISTANCE), 2.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(2).GetSolutionStepValue(DISTANCE), -0.132068, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(3).GetSolutionStepValue(DISTANCE), 0.968496, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetNode(4).GetSolutionStepValue(DISTANCE), 0.52827, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DistanceProcessDoubleEmbeddedVariable, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, -0.5, -0.5, 0.0); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, -0.5, 0.5, 0.0); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 0.5, 0.5, 0.0); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 0.5, -0.5, 0.0); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 7, + "element_name": "Element2D3N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + volume_part.AddNodalSolutionStepVariable(TEMPERATURE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the cube skin + const double cube_radious = 0.25; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(TEMPERATURE); + skin_part.CreateNewNode(1, -cube_radious, -cube_radious, 0.0); + skin_part.CreateNewNode(2, -cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(3, cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(4, cube_radious, -cube_radious, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 4, {{4,1}}, p_properties); + + // Set the embedded cube double variable + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(TEMPERATURE) = 1.0; + } + + // Compute the discontinuous distance function + CalculateDistanceToSkinProcess<2> dist_proc(volume_part, skin_part); + dist_proc.Execute(); + dist_proc.CalculateEmbeddedVariableFromSkin(TEMPERATURE, TEMPERATURE); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(TEMPERATURE), 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(TEMPERATURE), 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(TEMPERATURE), 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(TEMPERATURE), 0.0, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(DistanceProcessArrayEmbeddedVariable, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, -0.5, -0.5, 0.0); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, -0.5, 0.5, 0.0); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 0.5, 0.5, 0.0); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 0.5, -0.5, 0.0); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 7, + "element_name": "Element2D3N" + })"); + + ModelPart& volume_part = current_model.CreateModelPart("Volume"); + volume_part.AddNodalSolutionStepVariable(DISTANCE); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + + // Generate the cube skin + const double cube_radious = 0.25; + ModelPart& skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(1, -cube_radious, -cube_radious, 0.0); + skin_part.CreateNewNode(2, -cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(3, cube_radious, cube_radious, 0.0); + skin_part.CreateNewNode(4, cube_radious, -cube_radious, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{1,2}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 2, {{2,3}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 3, {{3,4}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 4, {{4,1}}, p_properties); + + // Set the embedded cube array variable + array_1d velocity = ZeroVector(3); + velocity[0] = 1.0; + velocity[1] = 1.0; + for (auto &i_node : skin_part.Nodes()) { + i_node.FastGetSolutionStepValue(VELOCITY) = velocity; + } + + // Compute the discontinuous distance function + CalculateDistanceToSkinProcess<2> dist_proc(volume_part, skin_part); + dist_proc.Execute(); + dist_proc.CalculateEmbeddedVariableFromSkin(VELOCITY, EMBEDDED_VELOCITY); + + // Check values + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(16).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[0], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[1], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(17).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[0], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[1], 1.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(68).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(volume_part.GetElement(69).GetValue(EMBEDDED_VELOCITY)[2], 0.0, 1e-6); + } + + +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_coarsening_process.cpp b/kratos/tests/cpp_tests/processes/test_coarsening_process.cpp new file mode 100644 index 000000000000..9b2042be2617 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_coarsening_process.cpp @@ -0,0 +1,294 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "processes/mesh_coarsening_process.h" +#include "processes/structured_mesh_generator_process.h" +#include "processes/find_nodal_neighbours_process.h" +#include "geometries/quadrilateral_2d_4.h" +#include "geometries/hexahedra_3d_8.h" +#include "includes/gid_io.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(Structured2DMeshCoarseningProcess, KratosCoreFastSuite) + { + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 10.00, 0.00, 0.00)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + ModelPart& model_part = current_model.CreateModelPart("Test"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":1, + "element_name": "Element2D3N" + } )"); + + std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + + // GidIO<> gid_io("c:/temp/coarsening/coarsening_test", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io.InitializeMesh(0.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + ModelPart& r_skin_model_part = model_part.GetSubModelPart("Skin"); + + for (auto i_node = r_skin_model_part.NodesBegin(); i_node != r_skin_model_part.NodesEnd(); i_node++) + i_node->Set(BOUNDARY); + + FindNodalNeighboursProcess(model_part).Execute(); + + MeshCoarseningProcess(model_part).Execute(); + + // gid_io.InitializeMesh(1.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + + //KRATOS_WATCH(model_part.NumberOfNodes()); + //KRATOS_WATCH(model_part.NumberOfElements()); + //std::size_t number_of_nodes = (number_of_divisions + 1) * (number_of_divisions + 1); + //KRATOS_CHECK_EQUAL(model_part.NumberOfNodes(), number_of_nodes); + //KRATOS_CHECK_EQUAL(model_part.NumberOfElements(), number_of_divisions * number_of_divisions * 2); + + double total_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_area = i_element->GetGeometry().Area(); + KRATOS_CHECK_GREATER(element_area, 1.00/number_of_divisions) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() << "] with area : " << element_area << std::endl << *i_element; + total_area += element_area; + } + KRATOS_CHECK_NEAR(total_area, 100., 1e-6) << " : " << total_area << " != 100" << std::endl; + } + + KRATOS_TEST_CASE_IN_SUITE(PerturbedStructured2DMeshCoarseningProcess, KratosCoreFastSuite) + { + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 10.00, 0.00, 0.00)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + ModelPart& model_part = current_model.CreateModelPart("Test"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":10, + "element_name": "Element2D3N" + } )"); + + std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + for (std::size_t i = 0; i < model_part.NumberOfNodes(); i++) + model_part.GetNode(i + 1).Coordinates()[i % 3] += .1 / number_of_divisions; + + double original_mesh_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) + original_mesh_area += i_element->GetGeometry().Area(); + + // GidIO<> gid_io("c:/temp/coarsening/perturbed_coarsening_test", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io.InitializeMesh(0.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + ModelPart& r_skin_model_part = model_part.GetSubModelPart("Skin"); + + for (auto i_node = r_skin_model_part.NodesBegin(); i_node != r_skin_model_part.NodesEnd(); i_node++) + i_node->Set(BOUNDARY); + + FindNodalNeighboursProcess(model_part).Execute(); + + MeshCoarseningProcess(model_part).Execute(); + + // gid_io.InitializeMesh(1.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + + //std::size_t number_of_nodes = (number_of_divisions + 1) * (number_of_divisions + 1); + //KRATOS_CHECK_EQUAL(model_part.NumberOfNodes(), number_of_nodes); + //KRATOS_CHECK_EQUAL(model_part.NumberOfElements(), number_of_divisions * number_of_divisions * 2); + + double total_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_area = i_element->GetGeometry().Area(); + KRATOS_CHECK_GREATER(element_area, 1.00 / number_of_divisions) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() << "] with area : " << element_area << std::endl << *i_element; + total_area += element_area; + } + KRATOS_CHECK_NEAR(total_area, original_mesh_area, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(RedistributedStructured2DMeshCoarseningProcess, KratosCoreFastSuite) + { + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 10.00, 0.00, 0.00)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + ModelPart& model_part = current_model.CreateModelPart("Test"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":10, + "element_name": "Element2D3N" + } )"); + + std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + for (std::size_t i = 0; i < model_part.NumberOfNodes(); i++) + model_part.GetNode(i + 1).Coordinates()[i % 2] += 4. / number_of_divisions; + + double original_mesh_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) + original_mesh_area += i_element->GetGeometry().Area(); + + // GidIO<> gid_io("c:/temp/coarsening/redistributed_coarsening_test", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io.InitializeMesh(0.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + ModelPart& r_skin_model_part = model_part.GetSubModelPart("Skin"); + + for (auto i_node = r_skin_model_part.NodesBegin(); i_node != r_skin_model_part.NodesEnd(); i_node++) + i_node->Set(BOUNDARY); + + FindNodalNeighboursProcess(model_part).Execute(); + + MeshCoarseningProcess(model_part).Execute(); + + FindNodalNeighboursProcess(model_part).Execute(); + + MeshCoarseningProcess(model_part).Execute(); + + + // gid_io.InitializeMesh(1.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + + //std::size_t number_of_nodes = (number_of_divisions + 1) * (number_of_divisions + 1); + //KRATOS_CHECK_EQUAL(model_part.NumberOfNodes(), number_of_nodes); + //KRATOS_CHECK_EQUAL(model_part.NumberOfElements(), number_of_divisions * number_of_divisions * 2); + + double total_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_area = i_element->GetGeometry().Area(); + KRATOS_CHECK_GREATER(element_area, 0.01 / number_of_divisions) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() << "] with area : " << element_area << std::endl << *i_element; + total_area += element_area; + } + KRATOS_CHECK_NEAR(total_area, original_mesh_area, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(Structured3DMeshCoarseningProcess, KratosCoreFastSuite) + { + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 10.00, 0.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point5(new Node<3>(5, 0.00, 0.00, 10.00)); + Node<3>::Pointer p_point6(new Node<3>(6, 10.00, 0.00, 10.00)); + Node<3>::Pointer p_point7(new Node<3>(7, 10.00, 10.00, 10.00)); + Node<3>::Pointer p_point8(new Node<3>(8, 0.00, 10.00, 10.00)); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + ModelPart& model_part = current_model.CreateModelPart("Test"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":10, + "element_name": "Element3D4N" + } )"); + + //std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + + // GidIO<> gid_io("c:/temp/coarsening/coarsening_3d_test", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io.InitializeMesh(0.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + ModelPart& r_skin_model_part = model_part.GetSubModelPart("Skin"); + + for (auto i_node = r_skin_model_part.NodesBegin(); i_node != r_skin_model_part.NodesEnd(); i_node++) + i_node->Set(BOUNDARY); + + FindNodalNeighboursProcess(model_part).Execute(); + + MeshCoarseningProcess(model_part).Execute(); + + // gid_io.InitializeMesh(1.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + + //KRATOS_WATCH(model_part.NumberOfNodes()); + //KRATOS_WATCH(model_part.NumberOfElements()); + KRATOS_CHECK_NOT_EQUAL(model_part.NumberOfNodes(), 0); + KRATOS_CHECK_NOT_EQUAL(model_part.NumberOfElements(), 0); + + + const double cube_volume = 1000.; + const double avarage_element_volume = cube_volume / model_part.NumberOfElements(); + double total_volume = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_volume = i_element->GetGeometry().Volume(); + KRATOS_CHECK_GREATER(element_volume, avarage_element_volume / 1000) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() << "] with volume : " << element_volume << std::endl << *i_element; + total_volume += element_volume; + } + KRATOS_CHECK_NEAR(total_volume, cube_volume, 1.E-6) << "with total_volume = " << total_volume; + } + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp new file mode 100644 index 000000000000..c997f530d98d --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp @@ -0,0 +1,288 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "testing/testing.h" +#include "includes/kratos_flags.h" +#include "includes/gid_io.h" + +/* Processes */ +#include "processes/compute_nodal_gradient_process.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + void GiDIODebugGradient(ModelPart& ThisModelPart) + { + GidIO<> gid_io("TEST_GRADIENT", GiD_PostBinary, SingleFile, WriteUndeformed, WriteElementsOnly); + const int nl_iter = ThisModelPart.GetProcessInfo()[NL_ITERATION_NUMBER]; + const double label = static_cast(nl_iter); + + gid_io.InitializeMesh(label); + gid_io.WriteMesh(ThisModelPart.GetMesh()); + gid_io.FinalizeMesh(); + gid_io.InitializeResults(label, ThisModelPart.GetMesh()); + gid_io.WriteNodalResults(DISTANCE, ThisModelPart.Nodes(), label, 0); + gid_io.WriteNodalResults(DISTANCE_GRADIENT, ThisModelPart.Nodes(), label, 0); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test triangle + */ + + KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + typedef ComputeNodalGradientProcess<2, Variable, Historical> GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_6->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test tetrahedra + */ + + KRATOS_TEST_CASE_IN_SUITE(NodalGradient2, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_12; + element_nodes_0[1] = p_node_10; + element_nodes_0[2] = p_node_8; + element_nodes_0[3] = p_node_9; + Tetrahedra3D4 tetrahedra_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_4; + element_nodes_1[1] = p_node_6; + element_nodes_1[2] = p_node_9; + element_nodes_1[3] = p_node_7; + Tetrahedra3D4 tetrahedra_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (4); + element_nodes_2[0] = p_node_11; + element_nodes_2[1] = p_node_7; + element_nodes_2[2] = p_node_9; + element_nodes_2[3] = p_node_8; + Tetrahedra3D4 tetrahedra_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (4); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_3; + element_nodes_3[2] = p_node_8; + element_nodes_3[3] = p_node_6; + Tetrahedra3D4 tetrahedra_3( PointerVector{element_nodes_3} ); + + std::vector element_nodes_4 (4); + element_nodes_4[0] = p_node_4; + element_nodes_4[1] = p_node_6; + element_nodes_4[2] = p_node_7; + element_nodes_4[3] = p_node_3; + Tetrahedra3D4 tetrahedra_4( PointerVector{element_nodes_4} ); + + std::vector element_nodes_5 (4); + element_nodes_5[0] = p_node_2; + element_nodes_5[1] = p_node_3; + element_nodes_5[2] = p_node_5; + element_nodes_5[3] = p_node_6; + Tetrahedra3D4 tetrahedra_5( PointerVector{element_nodes_5} ); + + std::vector element_nodes_6 (4); + element_nodes_6[0] = p_node_10; + element_nodes_6[1] = p_node_9; + element_nodes_6[2] = p_node_6; + element_nodes_6[3] = p_node_8; + Tetrahedra3D4 tetrahedra_6( PointerVector{element_nodes_6} ); + + std::vector element_nodes_7 (4); + element_nodes_7[0] = p_node_7; + element_nodes_7[1] = p_node_8; + element_nodes_7[2] = p_node_3; + element_nodes_7[3] = p_node_6; + Tetrahedra3D4 tetrahedra_7( PointerVector{element_nodes_7} ); + + std::vector element_nodes_8 (4); + element_nodes_8[0] = p_node_7; + element_nodes_8[1] = p_node_8; + element_nodes_8[2] = p_node_6; + element_nodes_8[3] = p_node_9; + Tetrahedra3D4 tetrahedra_8( PointerVector{element_nodes_8} ); + + std::vector element_nodes_9 (4); + element_nodes_9[0] = p_node_4; + element_nodes_9[1] = p_node_1; + element_nodes_9[2] = p_node_6; + element_nodes_9[3] = p_node_3; + Tetrahedra3D4 tetrahedra_9( PointerVector{element_nodes_9} ); + + std::vector element_nodes_10 (4); + element_nodes_10[0] = p_node_9; + element_nodes_10[1] = p_node_12; + element_nodes_10[2] = p_node_11; + element_nodes_10[3] = p_node_8; + Tetrahedra3D4 tetrahedra_10( PointerVector{element_nodes_10} ); + + std::vector element_nodes_11 (4); + element_nodes_11[0] = p_node_3; + element_nodes_11[1] = p_node_2; + element_nodes_11[2] = p_node_1; + element_nodes_11[3] = p_node_6; + Tetrahedra3D4 tetrahedra_11( PointerVector{element_nodes_11} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D4N", 1, tetrahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D4N", 2, tetrahedra_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element3D4N", 3, tetrahedra_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element3D4N", 4, tetrahedra_3, p_elem_prop); + Element::Pointer p_elem_4 = this_model_part.CreateNewElement("Element3D4N", 5, tetrahedra_4, p_elem_prop); + Element::Pointer p_elem_5 = this_model_part.CreateNewElement("Element3D4N", 6, tetrahedra_5, p_elem_prop); + Element::Pointer p_elem_6 = this_model_part.CreateNewElement("Element3D4N", 7, tetrahedra_6, p_elem_prop); + Element::Pointer p_elem_7 = this_model_part.CreateNewElement("Element3D4N", 8, tetrahedra_7, p_elem_prop); + Element::Pointer p_elem_8 = this_model_part.CreateNewElement("Element3D4N", 9, tetrahedra_8, p_elem_prop); + Element::Pointer p_elem_9 = this_model_part.CreateNewElement("Element3D4N", 10, tetrahedra_9, p_elem_prop); + Element::Pointer p_elem_10 = this_model_part.CreateNewElement("Element3D4N", 11, tetrahedra_10, p_elem_prop); + Element::Pointer p_elem_11 = this_model_part.CreateNewElement("Element3D4N", 12, tetrahedra_11, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + // Compute gradient + typedef ComputeNodalGradientProcess<3, Variable, Historical> GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_9->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_10->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_11->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_12->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_fast_transfer_between_model_parts_process.cpp b/kratos/tests/cpp_tests/processes/test_fast_transfer_between_model_parts_process.cpp new file mode 100644 index 000000000000..f3743f4fcea2 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_fast_transfer_between_model_parts_process.cpp @@ -0,0 +1,317 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/kratos_flags.h" +#include "geometries/triangle_3d_3.h" + +/* Processes */ +#include "processes/fast_transfer_between_model_parts_process.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + /** + * Checks the correct work of the fast_transfer_between_model_parts_process + * Test 1 + */ + + KRATOS_TEST_CASE_IN_SUITE(FastTransferBetweenModelPartsProcess1, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& origin_model_part = current_model.CreateModelPart("Origin"); + ModelPart& destination_model_part = current_model.CreateModelPart("Destination"); + + Properties::Pointer p_cond_prop = origin_model_part.pGetProperties(0); + + auto& process_info = origin_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = origin_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = origin_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = origin_model_part.CreateNewNode(3, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_4 = origin_model_part.CreateNewNode(4, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_5 = origin_model_part.CreateNewNode(5, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = origin_model_part.CreateNewNode(6, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_3; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_5; + condition_nodes_1[2] = p_node_6; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = origin_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = origin_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + + // This will copy all + FastTransferBetweenModelPartsProcess process = FastTransferBetweenModelPartsProcess(destination_model_part, origin_model_part, FastTransferBetweenModelPartsProcess::EntityTransfered::ALL); + process.Execute(); + + std::size_t count = 0; + for (auto& node : origin_model_part.Nodes()) { + ++count; + KRATOS_CHECK_EQUAL(node.Id(), destination_model_part.GetNode(count).Id()); + } + + count = 0; + for (auto& cond : origin_model_part.Conditions()) { + ++count; + KRATOS_CHECK_EQUAL(cond.Id(), destination_model_part.GetCondition(count).Id()); + } + } + + /** + * Checks the correct work of the fast_transfer_between_model_parts_process + * Test 2 (with flags) + */ + + KRATOS_TEST_CASE_IN_SUITE(FastTransferBetweenModelPartsProcess2, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& origin_model_part = current_model.CreateModelPart("Origin"); + ModelPart& destination_model_part = current_model.CreateModelPart("Destination"); + + Properties::Pointer p_cond_prop = origin_model_part.pGetProperties(0); + + auto& process_info = origin_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = origin_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = origin_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = origin_model_part.CreateNewNode(3, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_4 = origin_model_part.CreateNewNode(4, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_5 = origin_model_part.CreateNewNode(5, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = origin_model_part.CreateNewNode(6, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_3; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_5; + condition_nodes_1[2] = p_node_6; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = origin_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = origin_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + + // Setting flags + // SLAVE + p_node_1->Set(SLAVE, true); + p_node_1->Set(MASTER, false); + p_node_2->Set(SLAVE, true); + p_node_2->Set(MASTER, false); + p_node_3->Set(SLAVE, true); + p_node_3->Set(MASTER, false); + p_cond_0->Set(SLAVE, true); + p_cond_0->Set(MASTER, false); + // MASTER + p_node_4->Set(SLAVE, false); + p_node_4->Set(MASTER, true); + p_node_5->Set(SLAVE, false); + p_node_5->Set(MASTER, true); + p_node_6->Set(SLAVE, false); + p_node_6->Set(MASTER, true); + p_cond_1->Set(SLAVE, false); + p_cond_1->Set(MASTER, true); + + // This will copy all + FastTransferBetweenModelPartsProcess process = FastTransferBetweenModelPartsProcess(destination_model_part, origin_model_part, FastTransferBetweenModelPartsProcess::EntityTransfered::ALL, MASTER); + process.Execute(); + + std::size_t count = 0; + for (auto& node : origin_model_part.Nodes()) { + ++count; + if (node.Is(MASTER)) + KRATOS_CHECK_EQUAL(node.Id(), destination_model_part.GetNode(count).Id()); + } + + count = 0; + for (auto& cond : origin_model_part.Conditions()) { + ++count; + if (cond.Is(MASTER)) + KRATOS_CHECK_EQUAL(cond.Id(), destination_model_part.GetCondition(count).Id()); + } + } + + /** + * Checks the correct work of the fast_transfer_between_model_parts_process + * Test 3 (clone/replicate) + */ + + KRATOS_TEST_CASE_IN_SUITE(FastTransferBetweenModelPartsProcess3, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& origin_model_part = current_model.CreateModelPart("Origin"); + ModelPart& destination_model_part = current_model.CreateModelPart("Destination"); + + Properties::Pointer p_cond_prop = origin_model_part.pGetProperties(0); + + auto& process_info = origin_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = origin_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = origin_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = origin_model_part.CreateNewNode(3, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_4 = origin_model_part.CreateNewNode(4, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_5 = origin_model_part.CreateNewNode(5, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = origin_model_part.CreateNewNode(6, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_3; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_5; + condition_nodes_1[2] = p_node_6; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = origin_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = origin_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + + // This will copy all + FastTransferBetweenModelPartsProcess process = FastTransferBetweenModelPartsProcess(destination_model_part, origin_model_part, FastTransferBetweenModelPartsProcess::EntityTransfered::ALL, Flags(), true); + process.Execute(); + + std::size_t count = 0; + for (auto& node : destination_model_part.Nodes()) { + ++count; + KRATOS_CHECK_EQUAL(node.Id(), origin_model_part.GetNode(count).Id() + 6); + } + + count = 0; + for (auto& cond : destination_model_part.Conditions()) { + ++count; + KRATOS_CHECK_EQUAL(cond.Id(), origin_model_part.GetCondition(count).Id() + 2); + } + } + + /** + * Checks the correct work of the fast_transfer_between_model_parts_process + * Test 4 (clone/replicate with flags) + */ + + KRATOS_TEST_CASE_IN_SUITE(FastTransferBetweenModelPartsProcess4, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& origin_model_part = current_model.CreateModelPart("Origin"); + ModelPart& destination_model_part = current_model.CreateModelPart("Destination"); + + Properties::Pointer p_cond_prop = origin_model_part.pGetProperties(0); + + auto& process_info = origin_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = origin_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = origin_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = origin_model_part.CreateNewNode(3, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_4 = origin_model_part.CreateNewNode(4, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_5 = origin_model_part.CreateNewNode(5, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = origin_model_part.CreateNewNode(6, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_3; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_5; + condition_nodes_1[2] = p_node_6; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = origin_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = origin_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + + // Setting flags + // SLAVE + p_node_1->Set(SLAVE, true); + p_node_1->Set(MASTER, false); + p_node_2->Set(SLAVE, true); + p_node_2->Set(MASTER, false); + p_node_3->Set(SLAVE, true); + p_node_3->Set(MASTER, false); + p_cond_0->Set(SLAVE, true); + p_cond_0->Set(MASTER, false); + // MASTER + p_node_4->Set(SLAVE, false); + p_node_4->Set(MASTER, true); + p_node_5->Set(SLAVE, false); + p_node_5->Set(MASTER, true); + p_node_6->Set(SLAVE, false); + p_node_6->Set(MASTER, true); + p_cond_1->Set(SLAVE, false); + p_cond_1->Set(MASTER, true); + + // This will copy all + FastTransferBetweenModelPartsProcess process = FastTransferBetweenModelPartsProcess(destination_model_part, origin_model_part, FastTransferBetweenModelPartsProcess::EntityTransfered::ALL, MASTER, true); + process.Execute(); + + std::size_t count = 0; + for (auto& node : origin_model_part.Nodes()) { + ++count; + if (node.Is(MASTER)) + KRATOS_CHECK_EQUAL(node.Id() + 6, destination_model_part.GetNode(count + 6).Id()); + } + + count = 0; + for (auto& cond : origin_model_part.Conditions()) { + ++count; + if (cond.Is(MASTER)) + KRATOS_CHECK_EQUAL(cond.Id() + 2, destination_model_part.GetCondition(count + 2).Id()); + } + } + + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_find_intersected_geometrical_objects_process.cpp b/kratos/tests/cpp_tests/processes/test_find_intersected_geometrical_objects_process.cpp new file mode 100644 index 000000000000..948c8bf10578 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_find_intersected_geometrical_objects_process.cpp @@ -0,0 +1,196 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand, Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +// #include "includes/gid_io.h" +#include "containers/model.h" +#include "includes/checks.h" +#include "processes/find_intersected_geometrical_objects_process.h" +#include "processes/structured_mesh_generator_process.h" +#include "geometries/hexahedra_3d_8.h" +#include "geometries/quadrilateral_2d_4.h" + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(FindIntersectedElementsProcess2D, KratosCoreFastSuite) + { + Node<3>::Pointer p_point1(new Node<3>(1, 0.0, 0.0, 0.0)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.0, 1.0, 0.0)); + Node<3>::Pointer p_point3(new Node<3>(3, 1.0, 1.0, 0.0)); + Node<3>::Pointer p_point4(new Node<3>(4, 1.0, 0.0, 0.0)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions" : 3, + "element_name" : "Element2D3N" + } )"); + + Model current_model; + ModelPart &surface_part = current_model.CreateModelPart("Surface"); + ModelPart &skin_part = current_model.CreateModelPart("Boundaries"); + skin_part.CreateNewNode(100, -0.3, 0.5, 0.0); + skin_part.CreateNewNode(200, 0.6, 0.5, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{ 100,200 }}, p_properties); + StructuredMeshGeneratorProcess(geometry, surface_part, mesher_parameters).Execute(); + FindIntersectedGeometricalObjectsProcess find_intersections(surface_part, skin_part); + find_intersections.Execute(); + + // GidIO<> gid_io_fluid("/home/rzorrilla/Desktop/surface_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_fluid.InitializeMesh(0.00); + // gid_io_fluid.WriteMesh(surface_part.GetMesh()); + // gid_io_fluid.FinalizeMesh(); + // gid_io_fluid.InitializeResults(0, surface_part.GetMesh()); + // gid_io_fluid.FinalizeResults(); + + // GidIO<> gid_io_skin("/home/rzorrilla/Desktop/skin_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_skin.InitializeMesh(0.00); + // gid_io_skin.WriteMesh(skin_part.GetMesh()); + // gid_io_skin.FinalizeMesh(); + // gid_io_skin.InitializeResults(0, skin_part.GetMesh()); + // gid_io_skin.FinalizeResults(); + + KRATOS_CHECK((surface_part.Elements()[3]).Is(SELECTED)); + KRATOS_CHECK((surface_part.Elements()[4]).Is(SELECTED)); + KRATOS_CHECK((surface_part.Elements()[9]).Is(SELECTED)); + KRATOS_CHECK((surface_part.Elements()[10]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[0]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[1]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[2]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[5]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[6]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[7]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[8]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[11]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[12]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[13]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[14]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[15]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[16]).Is(SELECTED)); + KRATOS_CHECK_IS_FALSE((surface_part.Elements()[17]).Is(SELECTED)); + } + + KRATOS_TEST_CASE_IN_SUITE(FindIntersectedElementsProcessNoIntersection2D, KratosCoreFastSuite) + { + Node<3>::Pointer p_point1(new Node<3>(1, 0.0, 0.0, 0.0)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.0, 1.0, 0.0)); + Node<3>::Pointer p_point3(new Node<3>(3, 1.0, 1.0, 0.0)); + Node<3>::Pointer p_point4(new Node<3>(4, 1.0, 0.0, 0.0)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions" : 3, + "element_name" : "Element2D3N" + } )"); + + Model current_model; + ModelPart &surface_part = current_model.CreateModelPart("Surface"); + ModelPart &skin_part = current_model.CreateModelPart("Boundaries"); + skin_part.CreateNewNode(100, 0.3, -0.5, 0.0); + skin_part.CreateNewNode(200, 0.6, -0.5, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 1, {{ 100,200 }}, p_properties); + StructuredMeshGeneratorProcess(geometry, surface_part, mesher_parameters).Execute(); + FindIntersectedGeometricalObjectsProcess find_intersections(surface_part, skin_part); + find_intersections.Execute(); + + for (auto it_elem = surface_part.ElementsBegin(); it_elem != surface_part.ElementsEnd(); ++it_elem){ + KRATOS_CHECK_IS_FALSE(it_elem->Is(SELECTED)); + } + } + + KRATOS_TEST_CASE_IN_SUITE(FindIntersectedElementsProcess3D, KratosCoreFastSuite) + { + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 10.00, 0.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point5(new Node<3>(5, 0.00, 0.00, 10.00)); + Node<3>::Pointer p_point6(new Node<3>(6, 10.00, 0.00, 10.00)); + Node<3>::Pointer p_point7(new Node<3>(7, 10.00, 10.00, 10.00)); + Node<3>::Pointer p_point8(new Node<3>(8, 0.00, 10.00, 10.00)); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":2, + "element_name": "Element3D4N" + } )"); + + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + ModelPart &skin_part = current_model.CreateModelPart("Boundaries"); + skin_part.CreateNewNode(1, 1., .2, 0.); + skin_part.CreateNewNode(2, 1., .1, .5); + skin_part.CreateNewNode(3, 1., .1, 0.); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element3D3N", 1, { 1,2,3 }, p_properties); + StructuredMeshGeneratorProcess(geometry, volume_part, mesher_parameters).Execute(); + FindIntersectedGeometricalObjectsProcess(volume_part, skin_part).Execute(); + KRATOS_CHECK(volume_part.GetElement(3).IsNot(SELECTED)); + KRATOS_CHECK(volume_part.GetElement(4).IsNot(SELECTED)); + KRATOS_CHECK(volume_part.GetElement(5).Is(SELECTED)); + KRATOS_CHECK(volume_part.GetElement(6).Is(SELECTED)); + for (std::size_t i = 7; i < volume_part.NumberOfElements(); i++) + KRATOS_CHECK(volume_part.GetElement(i).IsNot(SELECTED)); + } + + KRATOS_TEST_CASE_IN_SUITE(FindIntersectedElementsProcessNoIntersection3D, KratosCoreFastSuite) + { + // Generate the tetrahedron element + Model current_model; + ModelPart &volume_part = current_model.CreateModelPart("Volume"); + volume_part.CreateNewNode(34, 0.865646, 0.657938, 0.222985); + volume_part.CreateNewNode(58, 0.770744, 0.570027, 0.204129); + volume_part.CreateNewNode(73, 0.860052, 0.477371, 0.22713); + volume_part.CreateNewNode(96, 0.803174, 0.485159, 0.326767); + Properties::Pointer p_properties_0(new Properties(0)); + volume_part.CreateNewElement("Element3D4N", 139, {34, 58, 73, 96}, p_properties_0); + + // Generate the skin model part + ModelPart &skin_part = current_model.CreateModelPart("Boundaries"); + skin_part.CreateNewNode(662, 0.766593, 0.532174, 0.275516); + skin_part.CreateNewNode(723, 0.793214, 0.506089, 0.308981); + skin_part.CreateNewNode(737, 0.794158, 0.544627, 0.315665); + skin_part.CreateNewNode(801, 0.81563, 0.518347, 0.349863); + skin_part.CreateNewNode(814, 0.811818, 0.567485, 0.356072); + skin_part.CreateNewNode(777, 0.809491, 0.469669, 0.339392); + skin_part.CreateNewNode(710, 0.7901, 0.455512, 0.309309); + skin_part.CreateNewNode(682, 0.768283, 0.578834, 0.289503); + skin_part.CreateNewNode(741, 0.786372, 0.593624, 0.321883); + skin_part.CreateNewNode(652, 0.766584, 0.482207, 0.273911); + Properties::Pointer p_properties_1(new Properties(1)); + skin_part.CreateNewElement("Element3D3N", 477, {662,723,737}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 478, {737,723,801}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 479, {737,801,814}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 480, {801,723,777}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 510, {777,723,710}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 467, {682,662,737}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 484, {737,741,682}, p_properties_1); + skin_part.CreateNewElement("Element3D3N", 496, {723,652,710}, p_properties_1); + + // Call the intersections process + FindIntersectedGeometricalObjectsProcess(volume_part, skin_part).Execute(); + + // Check that there is no intersection + KRATOS_CHECK(volume_part.GetElement(139).IsNot(SELECTED)); + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_find_nodal_h_process.cpp b/kratos/tests/cpp_tests/processes/test_find_nodal_h_process.cpp new file mode 100644 index 000000000000..82bc134d2713 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_find_nodal_h_process.cpp @@ -0,0 +1,268 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "testing/testing.h" +#include "includes/kratos_flags.h" +#include "includes/gid_io.h" + +/* Processes */ +#include "processes/find_nodal_h_process.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + void GiDIODebugNodalH(ModelPart& ThisModelPart) + { + GidIO<> gid_io("TEST_GRADIENT", GiD_PostBinary, SingleFile, WriteUndeformed, WriteElementsOnly); + const int nl_iter = ThisModelPart.GetProcessInfo()[NL_ITERATION_NUMBER]; + const double label = static_cast(nl_iter); + + gid_io.InitializeMesh(label); + gid_io.WriteMesh(ThisModelPart.GetMesh()); + gid_io.FinalizeMesh(); + gid_io.InitializeResults(label, ThisModelPart.GetMesh()); + gid_io.WriteNodalResults(NODAL_H, ThisModelPart.Nodes(), label, 0); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test triangle + */ + KRATOS_TEST_CASE_IN_SUITE(NodalH1, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(NODAL_H); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); + + // Compute NodalH + auto process = FindNodalHProcess(this_model_part); + process.Execute(); + +// // DEBUG +// GiDIODebugNodalH(this_model_part); + + const double tolerance = 1.0e-4; + KRATOS_CHECK_LESS_EQUAL(p_node_1->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_2->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_5->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_6->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test tetrahedra + */ + KRATOS_TEST_CASE_IN_SUITE(NodalH2, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(NODAL_H); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_12; + element_nodes_0[1] = p_node_10; + element_nodes_0[2] = p_node_8; + element_nodes_0[3] = p_node_9; + Tetrahedra3D4 tetrahedra_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_4; + element_nodes_1[1] = p_node_6; + element_nodes_1[2] = p_node_9; + element_nodes_1[3] = p_node_7; + Tetrahedra3D4 tetrahedra_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (4); + element_nodes_2[0] = p_node_11; + element_nodes_2[1] = p_node_7; + element_nodes_2[2] = p_node_9; + element_nodes_2[3] = p_node_8; + Tetrahedra3D4 tetrahedra_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (4); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_3; + element_nodes_3[2] = p_node_8; + element_nodes_3[3] = p_node_6; + Tetrahedra3D4 tetrahedra_3( PointerVector{element_nodes_3} ); + + std::vector element_nodes_4 (4); + element_nodes_4[0] = p_node_4; + element_nodes_4[1] = p_node_6; + element_nodes_4[2] = p_node_7; + element_nodes_4[3] = p_node_3; + Tetrahedra3D4 tetrahedra_4( PointerVector{element_nodes_4} ); + + std::vector element_nodes_5 (4); + element_nodes_5[0] = p_node_2; + element_nodes_5[1] = p_node_3; + element_nodes_5[2] = p_node_5; + element_nodes_5[3] = p_node_6; + Tetrahedra3D4 tetrahedra_5( PointerVector{element_nodes_5} ); + + std::vector element_nodes_6 (4); + element_nodes_6[0] = p_node_10; + element_nodes_6[1] = p_node_9; + element_nodes_6[2] = p_node_6; + element_nodes_6[3] = p_node_8; + Tetrahedra3D4 tetrahedra_6( PointerVector{element_nodes_6} ); + + std::vector element_nodes_7 (4); + element_nodes_7[0] = p_node_7; + element_nodes_7[1] = p_node_8; + element_nodes_7[2] = p_node_3; + element_nodes_7[3] = p_node_6; + Tetrahedra3D4 tetrahedra_7( PointerVector{element_nodes_7} ); + + std::vector element_nodes_8 (4); + element_nodes_8[0] = p_node_7; + element_nodes_8[1] = p_node_8; + element_nodes_8[2] = p_node_6; + element_nodes_8[3] = p_node_9; + Tetrahedra3D4 tetrahedra_8( PointerVector{element_nodes_8} ); + + std::vector element_nodes_9 (4); + element_nodes_9[0] = p_node_4; + element_nodes_9[1] = p_node_1; + element_nodes_9[2] = p_node_6; + element_nodes_9[3] = p_node_3; + Tetrahedra3D4 tetrahedra_9( PointerVector{element_nodes_9} ); + + std::vector element_nodes_10 (4); + element_nodes_10[0] = p_node_9; + element_nodes_10[1] = p_node_12; + element_nodes_10[2] = p_node_11; + element_nodes_10[3] = p_node_8; + Tetrahedra3D4 tetrahedra_10( PointerVector{element_nodes_10} ); + + std::vector element_nodes_11 (4); + element_nodes_11[0] = p_node_3; + element_nodes_11[1] = p_node_2; + element_nodes_11[2] = p_node_1; + element_nodes_11[3] = p_node_6; + Tetrahedra3D4 tetrahedra_11( PointerVector{element_nodes_11} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D4N", 1, tetrahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D4N", 2, tetrahedra_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element3D4N", 3, tetrahedra_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element3D4N", 4, tetrahedra_3, p_elem_prop); + Element::Pointer p_elem_4 = this_model_part.CreateNewElement("Element3D4N", 5, tetrahedra_4, p_elem_prop); + Element::Pointer p_elem_5 = this_model_part.CreateNewElement("Element3D4N", 6, tetrahedra_5, p_elem_prop); + Element::Pointer p_elem_6 = this_model_part.CreateNewElement("Element3D4N", 7, tetrahedra_6, p_elem_prop); + Element::Pointer p_elem_7 = this_model_part.CreateNewElement("Element3D4N", 8, tetrahedra_7, p_elem_prop); + Element::Pointer p_elem_8 = this_model_part.CreateNewElement("Element3D4N", 9, tetrahedra_8, p_elem_prop); + Element::Pointer p_elem_9 = this_model_part.CreateNewElement("Element3D4N", 10, tetrahedra_9, p_elem_prop); + Element::Pointer p_elem_10 = this_model_part.CreateNewElement("Element3D4N", 11, tetrahedra_10, p_elem_prop); + Element::Pointer p_elem_11 = this_model_part.CreateNewElement("Element3D4N", 12, tetrahedra_11, p_elem_prop); + + // Compute NodalH + auto process = FindNodalHProcess(this_model_part); + process.Execute(); + +// // DEBUG +// GiDIODebugNodalH(this_model_part); + + const double tolerance = 1.0e-4; + KRATOS_CHECK_LESS_EQUAL(p_node_1->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_2->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_3->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_5->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_9->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_10->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_11->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(p_node_12->FastGetSolutionStepValue(NODAL_H) - 1.0, tolerance); + } + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_mortar_mapper_process.cpp b/kratos/tests/cpp_tests/processes/test_mortar_mapper_process.cpp new file mode 100644 index 000000000000..5b11ccd8d85f --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_mortar_mapper_process.cpp @@ -0,0 +1,342 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/kratos_flags.h" +#include "includes/mapping_variables.h" +#include "includes/gid_io.h" + +/* Processes */ +#include "processes/simple_mortar_mapper_process.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + void GiDIODebugMapper(ModelPart& ThisModelPart) + { + GidIO<> gid_io("TEST_MAPPER", GiD_PostBinary, SingleFile, WriteUndeformed, WriteConditionsOnly); + const int nl_iter = ThisModelPart.GetProcessInfo()[NL_ITERATION_NUMBER]; + const double label = static_cast(nl_iter); + + gid_io.InitializeMesh(label); + gid_io.WriteMesh(ThisModelPart.GetMesh()); + gid_io.FinalizeMesh(); + gid_io.InitializeResults(label, ThisModelPart.GetMesh()); + gid_io.WriteNodalResults(TEMPERATURE, ThisModelPart.Nodes(), label, 0); + gid_io.WriteNodalResults(NORMAL, ThisModelPart.Nodes(), label, 0); + } + + /** + * Checks the correct work of the simple mortar mapper + * Test 1 + */ + + KRATOS_TEST_CASE_IN_SUITE(SimpleMortarMapper1, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + this_model_part.CreateSubModelPart("SlaveModelPart"); + ModelPart& slave_model_part = this_model_part.GetSubModelPart("SlaveModelPart"); + this_model_part.CreateSubModelPart("MasterModelPart"); + ModelPart& master_model_part = this_model_part.GetSubModelPart("MasterModelPart"); + + this_model_part.AddNodalSolutionStepVariable(TEMPERATURE); + this_model_part.AddNodalSolutionStepVariable(NORMAL); + + Properties::Pointer p_cond_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_3; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_5; + condition_nodes_1[2] = p_node_6; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = this_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = this_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + + // Adding map + IndexSet this_set; + this_set.AddId(2); + p_cond_0->SetValue(INDEX_SET, Kratos::make_shared(this_set)); + + // SLAVE + slave_model_part.AddNode(p_node_1); + slave_model_part.AddNode(p_node_2); + slave_model_part.AddNode(p_node_3); + slave_model_part.AddCondition(p_cond_0); + // MASTER + master_model_part.AddNode(p_node_4); + master_model_part.AddNode(p_node_5); + master_model_part.AddNode(p_node_6); + master_model_part.AddCondition(p_cond_1); + + // We compute the normals + MortarUtilities::ComputeNodesMeanNormalModelPart(this_model_part); + + p_node_4->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_4->X(), 2) + std::pow(p_node_4->Y(), 2); + p_node_5->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_5->X(), 2) + std::pow(p_node_5->Y(), 2); + p_node_6->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_6->X(), 2) + std::pow(p_node_6->Y(), 2); + + const double tolerance = 1.0e-4; + auto int_util = ExactMortarIntegrationUtility<3, 3>(); + double area; + int_util.GetExactAreaIntegration(p_cond_0->GetGeometry(), p_cond_0->GetValue(NORMAL), p_cond_1->GetGeometry(), p_cond_1->GetValue(NORMAL), area); + KRATOS_CHECK_LESS_EQUAL((area - 0.499925)/0.499925, tolerance); + + typedef SimpleMortarMapperProcess<3, 3, Variable> MapperType; + MapperType process = MapperType(master_model_part, slave_model_part, TEMPERATURE); + process.Execute(); + +// // DEBUG +// GiDIODebugMapper(this_model_part); + + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_1->X(), 2) + std::pow(p_node_1->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_2->X(), 2) + std::pow(p_node_2->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_3->X(), 2) + std::pow(p_node_3->Y(), 2))), tolerance); + } + + /** + * Checks the correct work of the simple mortar mapper + * Test 2 + */ + + KRATOS_TEST_CASE_IN_SUITE(SimpleMortarMapper2, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + this_model_part.CreateSubModelPart("SlaveModelPart"); + ModelPart& slave_model_part = this_model_part.GetSubModelPart("SlaveModelPart"); + this_model_part.CreateSubModelPart("MasterModelPart"); + ModelPart& master_model_part = this_model_part.GetSubModelPart("MasterModelPart"); + + this_model_part.AddNodalSolutionStepVariable(TEMPERATURE); + this_model_part.AddNodalSolutionStepVariable(NORMAL); + + Properties::Pointer p_cond_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.00); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.00); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.01); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.01); + + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 0.0 , 0.0 , 0.01); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 1.0 , 0.0 , 0.01); + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7, 1.0 , 1.0 , 0.02); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8, 0.0 , 1.0 , 0.02); + + // Now we create the "conditions" + std::vector condition_nodes_0 (4); + condition_nodes_0[0] = p_node_1; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_3; + condition_nodes_0[3] = p_node_4; + Quadrilateral3D4 quad_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (4); + condition_nodes_1[0] = p_node_8; + condition_nodes_1[1] = p_node_7; + condition_nodes_1[2] = p_node_6; + condition_nodes_1[3] = p_node_5; + Quadrilateral3D4 quad_1( PointerVector{condition_nodes_1} ); + + Condition::Pointer p_cond_0 = this_model_part.CreateNewCondition("Condition3D4N", 1, quad_0, p_cond_prop); + Condition::Pointer p_cond_1 = this_model_part.CreateNewCondition("Condition3D4N", 2, quad_1, p_cond_prop); + + // Adding map + IndexSet this_set; + this_set.AddId(2); + p_cond_0->SetValue(INDEX_SET, Kratos::make_shared(this_set)); + + // SLAVE + slave_model_part.AddNode(p_node_1); + slave_model_part.AddNode(p_node_2); + slave_model_part.AddNode(p_node_3); + slave_model_part.AddNode(p_node_4); + slave_model_part.AddCondition(p_cond_0); + // MASTER + master_model_part.AddNode(p_node_5); + master_model_part.AddNode(p_node_6); + master_model_part.AddNode(p_node_7); + master_model_part.AddNode(p_node_8); + master_model_part.AddCondition(p_cond_1); + + // We compute the normals + MortarUtilities::ComputeNodesMeanNormalModelPart(this_model_part); + + p_node_5->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_5->X(), 2) + std::pow(p_node_5->Y(), 2); + p_node_6->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_6->X(), 2) + std::pow(p_node_6->Y(), 2); + p_node_7->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_7->X(), 2) + std::pow(p_node_7->Y(), 2); + p_node_8->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_8->X(), 2) + std::pow(p_node_8->Y(), 2); + + typedef SimpleMortarMapperProcess<3, 4, Variable> MapperType; + MapperType process = MapperType(master_model_part, slave_model_part, TEMPERATURE); + process.Execute(); + +// // DEBUG +// GiDIODebugMapper(this_model_part); + + const double tolerance = 1.0e-4; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_1->X(), 2) + std::pow(p_node_1->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_2->X(), 2) + std::pow(p_node_2->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_3->X(), 2) + std::pow(p_node_3->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_4->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_4->X(), 2) + std::pow(p_node_4->Y(), 2))), tolerance); + } + + /** + * Checks the correct work of the simple mortar mapper + * Test 3 + */ + + KRATOS_TEST_CASE_IN_SUITE(SimpleMortarMapper3, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + this_model_part.CreateSubModelPart("SlaveModelPart"); + ModelPart& slave_model_part = this_model_part.GetSubModelPart("SlaveModelPart"); + this_model_part.CreateSubModelPart("MasterModelPart"); + ModelPart& master_model_part = this_model_part.GetSubModelPart("MasterModelPart"); + + this_model_part.AddNodalSolutionStepVariable(TEMPERATURE); + this_model_part.AddNodalSolutionStepVariable(NORMAL); + + Properties::Pointer p_cond_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.000, 0.000, 0.000); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.000, 1.000, 1.000); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.000, 0.000, 1.000); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 1.000, 1.000, 0.000); + + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 1.001, 0.000, 1.000); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 1.001, 1.000, 0.000); + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7, 0.001, 0.000, 0.000); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8, 1.001, 1.000, 1.000); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + std::vector condition_nodes_1 (3); + condition_nodes_0[0] = p_node_4; + condition_nodes_0[1] = p_node_3; + condition_nodes_0[2] = p_node_1; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + condition_nodes_1[0] = p_node_4; + condition_nodes_1[1] = p_node_2; + condition_nodes_1[2] = p_node_3; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + std::vector condition_nodes_2 (3); + std::vector condition_nodes_3 (3); + condition_nodes_2[0] = p_node_7; + condition_nodes_2[1] = p_node_5; + condition_nodes_2[2] = p_node_6; + Triangle3D3 triangle_3( PointerVector{condition_nodes_2} ); + condition_nodes_3[0] = p_node_5; + condition_nodes_3[1] = p_node_8; + condition_nodes_3[2] = p_node_6; + Triangle3D3 triangle_4( PointerVector{condition_nodes_3} ); + + Condition::Pointer p_cond_0 = this_model_part.CreateNewCondition("Condition3D", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = this_model_part.CreateNewCondition("Condition3D", 2, triangle_1, p_cond_prop); + Condition::Pointer p_cond_2 = this_model_part.CreateNewCondition("Condition3D", 3, triangle_3, p_cond_prop); + Condition::Pointer p_cond_3 = this_model_part.CreateNewCondition("Condition3D", 4, triangle_4, p_cond_prop); + + // Adding map + IndexSet this_set0, this_set1; + this_set0.AddId(3); + this_set0.AddId(4); + this_set1.AddId(3); + this_set1.AddId(4); + p_cond_0->SetValue(INDEX_SET, Kratos::make_shared(this_set0)); + p_cond_1->SetValue(INDEX_SET, Kratos::make_shared(this_set1)); + + // SLAVE + slave_model_part.AddNode(p_node_1); + slave_model_part.AddNode(p_node_2); + slave_model_part.AddNode(p_node_3); + slave_model_part.AddNode(p_node_4); + slave_model_part.AddCondition(p_cond_0); + slave_model_part.AddCondition(p_cond_1); + // MASTER + master_model_part.AddNode(p_node_5); + master_model_part.AddNode(p_node_6); + master_model_part.AddNode(p_node_7); + master_model_part.AddNode(p_node_8); + master_model_part.AddCondition(p_cond_2); + master_model_part.AddCondition(p_cond_3); + + // We compute the normals + MortarUtilities::ComputeNodesMeanNormalModelPart(this_model_part); + + p_node_5->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_5->Z(), 2) + std::pow(p_node_5->Y(), 2); + p_node_6->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_6->Z(), 2) + std::pow(p_node_6->Y(), 2); + p_node_7->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_7->Z(), 2) + std::pow(p_node_7->Y(), 2); + p_node_8->FastGetSolutionStepValue(TEMPERATURE) = std::pow(p_node_8->Z(), 2) + std::pow(p_node_8->Y(), 2); + + typedef SimpleMortarMapperProcess<3, 3, Variable> MapperType; + MapperType process = MapperType(master_model_part, slave_model_part, TEMPERATURE); + process.Execute(); + +// // DEBUG +// GiDIODebugMapper(this_model_part); + + const double tolerance = 1.0e-3; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_1->Z(), 2) + std::pow(p_node_1->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_2->Z(), 2) + std::pow(p_node_2->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_3->Z(), 2) + std::pow(p_node_3->Y(), 2))), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_4->FastGetSolutionStepValue(TEMPERATURE) - (std::pow(p_node_4->Z(), 2) + std::pow(p_node_4->Y(), 2))), tolerance); + } + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_replace_elements_and_condition_process.cpp b/kratos/tests/cpp_tests/processes/test_replace_elements_and_condition_process.cpp new file mode 100644 index 000000000000..16cb9d470eec --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_replace_elements_and_condition_process.cpp @@ -0,0 +1,259 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "testing/testing.h" + + +/* Processes */ +#include "processes/replace_elements_and_condition_process.h" +#include "utilities/compare_elements_and_conditions_utility.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + /** + * Checks the correct work of the nodal gradient compute + * Test triangle + */ + KRATOS_TEST_CASE_IN_SUITE(ReplaceElementsAndConditionsProcess1, KratosCoreFastSuite) + { + Model current_model; + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 ::Pointer p_triangle_0 = Kratos::make_shared>( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 ::Pointer p_triangle_1 = Kratos::make_shared>( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 ::Pointer p_triangle_2 = Kratos::make_shared>( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 ::Pointer p_triangle_3 = Kratos::make_shared>( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = Kratos::make_shared(1, p_triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = Kratos::make_shared(2, p_triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = Kratos::make_shared(3, p_triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = Kratos::make_shared(4, p_triangle_3, p_elem_prop); + this_model_part.AddElement(p_elem_0); + this_model_part.AddElement(p_elem_1); + this_model_part.AddElement(p_elem_2); + this_model_part.AddElement(p_elem_3); + + // Compute process + Parameters settings( R"( + { + "element_name":"Element2D3N", + "condition_name": "Condition2D2N" + } )" ); + + ReplaceElementsAndConditionsProcess process = ReplaceElementsAndConditionsProcess(this_model_part, settings); + process.Execute(); + + // Same element type, same geometry type + std::string component_name; + for (auto& r_element : this_model_part.Elements()) { + CompareElementsAndConditionsUtility::GetRegisteredName(r_element, component_name); + KRATOS_CHECK_EQUAL(component_name, "Element2D3N"); + } + } + + /** + * Checks the correct work of the nodal gradient compute + * Test tetrahedra + */ + KRATOS_TEST_CASE_IN_SUITE(ReplaceElementsAndConditionsProcess2, KratosCoreFastSuite) + { + Model current_model; + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_12; + element_nodes_0[1] = p_node_10; + element_nodes_0[2] = p_node_8; + element_nodes_0[3] = p_node_9; + Tetrahedra3D4 ::Pointer p_tetrahedra_0 = Kratos::make_shared>( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_4; + element_nodes_1[1] = p_node_6; + element_nodes_1[2] = p_node_9; + element_nodes_1[3] = p_node_7; + Tetrahedra3D4 ::Pointer p_tetrahedra_1 = Kratos::make_shared>( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (4); + element_nodes_2[0] = p_node_11; + element_nodes_2[1] = p_node_7; + element_nodes_2[2] = p_node_9; + element_nodes_2[3] = p_node_8; + Tetrahedra3D4 ::Pointer p_tetrahedra_2 = Kratos::make_shared>( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (4); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_3; + element_nodes_3[2] = p_node_8; + element_nodes_3[3] = p_node_6; + Tetrahedra3D4 ::Pointer p_tetrahedra_3 = Kratos::make_shared>( PointerVector{element_nodes_3} ); + + std::vector element_nodes_4 (4); + element_nodes_4[0] = p_node_4; + element_nodes_4[1] = p_node_6; + element_nodes_4[2] = p_node_7; + element_nodes_4[3] = p_node_3; + Tetrahedra3D4 ::Pointer p_tetrahedra_4 = Kratos::make_shared>( PointerVector{element_nodes_4} ); + + std::vector element_nodes_5 (4); + element_nodes_5[0] = p_node_2; + element_nodes_5[1] = p_node_3; + element_nodes_5[2] = p_node_5; + element_nodes_5[3] = p_node_6; + Tetrahedra3D4 ::Pointer p_tetrahedra_5 = Kratos::make_shared>( PointerVector{element_nodes_5} ); + + std::vector element_nodes_6 (4); + element_nodes_6[0] = p_node_10; + element_nodes_6[1] = p_node_9; + element_nodes_6[2] = p_node_6; + element_nodes_6[3] = p_node_8; + Tetrahedra3D4 ::Pointer p_tetrahedra_6 = Kratos::make_shared>( PointerVector{element_nodes_6} ); + + std::vector element_nodes_7 (4); + element_nodes_7[0] = p_node_7; + element_nodes_7[1] = p_node_8; + element_nodes_7[2] = p_node_3; + element_nodes_7[3] = p_node_6; + Tetrahedra3D4 ::Pointer p_tetrahedra_7 = Kratos::make_shared>( PointerVector{element_nodes_7} ); + + std::vector element_nodes_8 (4); + element_nodes_8[0] = p_node_7; + element_nodes_8[1] = p_node_8; + element_nodes_8[2] = p_node_6; + element_nodes_8[3] = p_node_9; + Tetrahedra3D4 ::Pointer p_tetrahedra_8 = Kratos::make_shared>( PointerVector{element_nodes_8} ); + + std::vector element_nodes_9 (4); + element_nodes_9[0] = p_node_4; + element_nodes_9[1] = p_node_1; + element_nodes_9[2] = p_node_6; + element_nodes_9[3] = p_node_3; + Tetrahedra3D4 ::Pointer p_tetrahedra_9 = Kratos::make_shared>( PointerVector{element_nodes_9} ); + + std::vector element_nodes_10 (4); + element_nodes_10[0] = p_node_9; + element_nodes_10[1] = p_node_12; + element_nodes_10[2] = p_node_11; + element_nodes_10[3] = p_node_8; + Tetrahedra3D4 ::Pointer p_tetrahedra_10 = Kratos::make_shared>( PointerVector{element_nodes_10} ); + + std::vector element_nodes_11 (4); + element_nodes_11[0] = p_node_3; + element_nodes_11[1] = p_node_2; + element_nodes_11[2] = p_node_1; + element_nodes_11[3] = p_node_6; + Tetrahedra3D4 ::Pointer p_tetrahedra_11 = Kratos::make_shared>( PointerVector{element_nodes_11} ); + + Element::Pointer p_elem_0 = Kratos::make_shared(1, p_tetrahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = Kratos::make_shared(2, p_tetrahedra_1, p_elem_prop); + Element::Pointer p_elem_2 = Kratos::make_shared(3, p_tetrahedra_2, p_elem_prop); + Element::Pointer p_elem_3 = Kratos::make_shared(4, p_tetrahedra_3, p_elem_prop); + Element::Pointer p_elem_4 = Kratos::make_shared(5, p_tetrahedra_4, p_elem_prop); + Element::Pointer p_elem_5 = Kratos::make_shared(6, p_tetrahedra_5, p_elem_prop); + Element::Pointer p_elem_6 = Kratos::make_shared(7, p_tetrahedra_6, p_elem_prop); + Element::Pointer p_elem_7 = Kratos::make_shared(8, p_tetrahedra_7, p_elem_prop); + Element::Pointer p_elem_8 = Kratos::make_shared(9, p_tetrahedra_8, p_elem_prop); + Element::Pointer p_elem_9 = Kratos::make_shared(10, p_tetrahedra_9, p_elem_prop); + Element::Pointer p_elem_10 = Kratos::make_shared(11, p_tetrahedra_10, p_elem_prop); + Element::Pointer p_elem_11 = Kratos::make_shared(12, p_tetrahedra_11, p_elem_prop); + this_model_part.AddElement(p_elem_0); + this_model_part.AddElement(p_elem_1); + this_model_part.AddElement(p_elem_2); + this_model_part.AddElement(p_elem_3); + this_model_part.AddElement(p_elem_4); + this_model_part.AddElement(p_elem_5); + this_model_part.AddElement(p_elem_6); + this_model_part.AddElement(p_elem_7); + this_model_part.AddElement(p_elem_8); + this_model_part.AddElement(p_elem_9); + this_model_part.AddElement(p_elem_10); + this_model_part.AddElement(p_elem_11); + + // Compute process + Parameters settings( R"( + { + "element_name":"Element3D4N", + "condition_name": "SurfaceCondition3D3N" + } )" ); + + ReplaceElementsAndConditionsProcess process = ReplaceElementsAndConditionsProcess(this_model_part, settings); + process.Execute(); + + // Same element type + std::string component_name; + for (auto& r_element : this_model_part.Elements()) { + CompareElementsAndConditionsUtility::GetRegisteredName(r_element, component_name); + KRATOS_CHECK_EQUAL(component_name, "Element3D4N"); + } + } + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/processes/test_skin_detection_process.cpp b/kratos/tests/cpp_tests/processes/test_skin_detection_process.cpp new file mode 100644 index 000000000000..c03712d38c41 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_skin_detection_process.cpp @@ -0,0 +1,81 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Alejandro Cornejo +// Vicente Mataix Ferrandiz +// + +// Project includes +#include "includes/process_info.h" +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/model_part.h" +#include "geometries/triangle_2d_3.h" +#include "processes/skin_detection_process.h" +#include "includes/element.h" + +namespace Kratos +{ +namespace Testing +{ + +typedef Node<3> NodeType; + +KRATOS_TEST_CASE_IN_SUITE(SkinDetectionProcess, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test_model_part",2); + + model_part.AddNodalSolutionStepVariable(TEMPERATURE);; + + NodeType::Pointer p_node_1 = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + NodeType::Pointer p_node_2 = model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + NodeType::Pointer p_node_3 = model_part.CreateNewNode(3, 1.0, 1.0, 0.0); + NodeType::Pointer p_node_4 = model_part.CreateNewNode(4, 0.0, 1.0, 0.0); + + Geometry::PointsArrayType array_nodes1, array_nodes2; + array_nodes1.push_back(p_node_1); + array_nodes1.push_back(p_node_2); + array_nodes1.push_back(p_node_3); + + array_nodes2.push_back(p_node_1); + array_nodes2.push_back(p_node_3); + array_nodes2.push_back(p_node_4); + + Properties::Pointer p_elem_prop = model_part.pGetProperties(0); + Element::Pointer p_elem_1 = model_part.CreateNewElement("Element2D3N", 1,PointerVector{array_nodes1}, p_elem_prop); + Element::Pointer p_elem_2 = model_part.CreateNewElement("Element2D3N", 2,PointerVector{array_nodes2}, p_elem_prop); + + Parameters default_parameters = Parameters(R"( + { + "name_auxiliar_model_part" : "SkinModelPart", + "name_auxiliar_condition" : "Condition", + "list_model_parts_to_assign_conditions" : [], + "echo_level" : 0 + })"); + + SkinDetectionProcess<2> skin_process = SkinDetectionProcess<2>( + model_part, default_parameters); + + // We generate in several iterations to see if it crashes + for (int i = 0; i < 2; i++) { + skin_process.Execute(); + KRATOS_CHECK_EQUAL(model_part.GetSubModelPart("SkinModelPart").NumberOfConditions(), 4); + } + + // Now we remove one element + p_elem_2->Set(TO_ERASE); + model_part.RemoveElementsFromAllLevels(TO_ERASE); + + // We execute again + skin_process.Execute(); + KRATOS_CHECK_EQUAL(model_part.GetSubModelPart("SkinModelPart").NumberOfConditions(), 3); +} +} // namespace Testing +} // namespace Kratos diff --git a/kratos/tests/cpp_tests/processes/test_structured_mesh_generator_process.cpp b/kratos/tests/cpp_tests/processes/test_structured_mesh_generator_process.cpp new file mode 100644 index 000000000000..c9388c8f6896 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_structured_mesh_generator_process.cpp @@ -0,0 +1,128 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/kernel.h" +#include "processes/structured_mesh_generator_process.h" +#include "geometries/quadrilateral_2d_4.h" +#include "geometries/hexahedra_3d_8.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(StructuredMeshGeneratorProcessHexahedra, KratosCoreFastSuite) + { + Kernel kernel; + + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 10.00, 0.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point5(new Node<3>(5, 0.00, 0.00, 10.00)); + Node<3>::Pointer p_point6(new Node<3>(6, 10.00, 0.00, 10.00)); + Node<3>::Pointer p_point7(new Node<3>(7, 10.00, 10.00, 10.00)); + Node<3>::Pointer p_point8(new Node<3>(8, 0.00, 10.00, 10.00)); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + ModelPart& model_part = current_model.CreateModelPart("Generated"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":10, + "element_name": "Element3D4N" + } )"); + + std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + std::size_t number_of_nodes = (number_of_divisions + 1) * (number_of_divisions + 1) * (number_of_divisions + 1); + std::size_t number_of_elements = number_of_divisions * number_of_divisions * number_of_divisions * 6; + KRATOS_CHECK_EQUAL(model_part.NumberOfNodes(), number_of_nodes); + KRATOS_CHECK_EQUAL(model_part.NumberOfElements(), number_of_elements) << " Number of elements = " << model_part.NumberOfElements() ; + + double total_volume = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_volume = i_element->GetGeometry().Volume(); + KRATOS_CHECK_GREATER(element_volume, 0.00) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() + << "," << i_element->GetGeometry()[3].Id() << "] with volume : " << element_volume << std::endl << *i_element; + total_volume += element_volume; + } + KRATOS_CHECK_NEAR(total_volume, 1000., 1.E-6) << "with total_volume = " << total_volume; + + KRATOS_CHECK(model_part.HasSubModelPart("Skin")); + + KRATOS_CHECK_EQUAL(model_part.GetSubModelPart("Skin").NumberOfNodes(), 602); + KRATOS_CHECK_EQUAL(model_part.GetSubModelPart("Skin").NumberOfElements(), 0); + } + + KRATOS_TEST_CASE_IN_SUITE(StructuredMeshGeneratorProcessQuadrilateral, KratosCoreFastSuite) + { + Kernel kernel; + + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 10.00, 0.00, 0.00)); + + Quadrilateral2D4 > geometry(p_point1, p_point2, p_point3, p_point4); + + ModelPart& model_part = current_model.CreateModelPart("Generated"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":10, + "element_name": "Element2D3N", + "create_skin_sub_model_part": false + } )"); + + std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + std::size_t number_of_nodes = (number_of_divisions + 1) * (number_of_divisions + 1); + KRATOS_CHECK_EQUAL(model_part.NumberOfNodes(), number_of_nodes); + KRATOS_CHECK_EQUAL(model_part.NumberOfElements(), number_of_divisions * number_of_divisions * 2); + + double total_area = 0.00; + for (auto i_element = model_part.ElementsBegin(); i_element != model_part.ElementsEnd(); i_element++) { + double element_area = i_element->GetGeometry().Area(); + KRATOS_CHECK_GREATER(element_area, 0.00) << " for element #" << i_element->Id() << " with nodes [" + << i_element->GetGeometry()[0].Id() + << "," << i_element->GetGeometry()[1].Id() + << "," << i_element->GetGeometry()[2].Id() << "] with area : " << element_area << std::endl << *i_element; + total_area += element_area; + } + KRATOS_CHECK_NEAR(total_area, 100., 1.E-6) << "with total_area = " << total_area; + + KRATOS_CHECK_IS_FALSE(model_part.HasSubModelPart("Skin")); + } + } +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/processes/test_tetrahedra_edge_swapping_process.cpp b/kratos/tests/cpp_tests/processes/test_tetrahedra_edge_swapping_process.cpp new file mode 100644 index 000000000000..07c41cce0f80 --- /dev/null +++ b/kratos/tests/cpp_tests/processes/test_tetrahedra_edge_swapping_process.cpp @@ -0,0 +1,83 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "processes/structured_mesh_generator_process.h" +#include "processes/tetrahedra_mesh_edge_swapping_process.h" +#include "processes/find_nodal_neighbours_process.h" +#include "geometries/hexahedra_3d_8.h" +#include "includes/gid_io.h" + + +namespace Kratos { + namespace Testing { + + + KRATOS_TEST_CASE_IN_SUITE(TetrahedraMeshEdgeSwappingProcess, KratosCoreFastSuite) + { + Model current_model; + + Node<3>::Pointer p_point1(new Node<3>(1, 0.00, 0.00, 0.00)); + Node<3>::Pointer p_point2(new Node<3>(2, 10.00, 0.00, 0.00)); + Node<3>::Pointer p_point3(new Node<3>(3, 10.00, 10.00, 0.00)); + Node<3>::Pointer p_point4(new Node<3>(4, 0.00, 10.00, 0.00)); + Node<3>::Pointer p_point5(new Node<3>(5, 0.00, 0.00, 10.00)); + Node<3>::Pointer p_point6(new Node<3>(6, 10.00, 0.00, 10.00)); + Node<3>::Pointer p_point7(new Node<3>(7, 10.00, 10.00, 10.00)); + Node<3>::Pointer p_point8(new Node<3>(8, 0.00, 10.00, 10.00)); + + Hexahedra3D8 > geometry(p_point1, p_point2, p_point3, p_point4, p_point5, p_point6, p_point7, p_point8); + + ModelPart& model_part = current_model.CreateModelPart("Test"); + + Parameters mesher_parameters(R"( + { + "number_of_divisions":1, + "element_name": "Element3D4N" + } )"); + + //std::size_t number_of_divisions = mesher_parameters["number_of_divisions"].GetInt(); + + StructuredMeshGeneratorProcess(geometry, model_part, mesher_parameters).Execute(); + + GidIO<> gid_io("/home/pooyan/kratos/tests/edge_swapping", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + gid_io.InitializeMesh(0.00); + gid_io.WriteMesh(model_part.GetMesh()); + gid_io.FinalizeMesh(); + + ModelPart& r_skin_model_part = model_part.GetSubModelPart("Skin"); + + for (auto i_node = r_skin_model_part.NodesBegin(); i_node != r_skin_model_part.NodesEnd(); i_node++) + i_node->Set(BOUNDARY); + + FindNodalNeighboursProcess(model_part).Execute(); + + TetrahedraMeshEdgeSwappingProcess(model_part).Execute(); + + // gid_io.InitializeMesh(1.00); + // gid_io.WriteMesh(model_part.GetMesh()); + // gid_io.FinalizeMesh(); + + + + } + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/cross_check_shape_functions_values.cpp b/kratos/tests/cpp_tests/sources/cross_check_shape_functions_values.cpp new file mode 100644 index 000000000000..246ee39df969 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/cross_check_shape_functions_values.cpp @@ -0,0 +1,103 @@ +#include "tests/cpp_tests/geometries/cross_check_shape_functions_values.h" + +//#include "containers/array_1d.h" +#include "testing/testing.h" +#include "tests/cpp_tests/geometries/test_geometry.h" + +namespace Kratos { +namespace Testing { + +namespace { +void Check_ShapeFunctionsValues1(Geometry> const& rGeom); +void Check_ShapeFunctionsValues2(Geometry> const& rGeom); +void Check_ShapeFunctionsValues3(Geometry> const& rGeom); +void Check_ShapeFunctionsValues4(Geometry> const& rGeom); +void Check_ShapeFunctionsValues5(Geometry> const& rGeom); +void Check(double N, + Geometry> const& rGeom, + Geometry>::IndexType ShapeFunctionIndex, + array_1d const& rCoord); +} + +void CrossCheckShapeFunctionsValues(Geometry> const& rGeom) +{ + KRATOS_TRY; + Check_ShapeFunctionsValues1(rGeom); + Check_ShapeFunctionsValues2(rGeom); + Check_ShapeFunctionsValues3(rGeom); + Check_ShapeFunctionsValues4(rGeom); + Check_ShapeFunctionsValues5(rGeom); + KRATOS_CATCH(""); +} + +namespace { +void Check_ShapeFunctionsValues1(Geometry> const& rGeom) +{ + KRATOS_TRY; + const Matrix& r_shape_functions_values = rGeom.ShapeFunctionsValues(); + const auto& r_integration_points = rGeom.IntegrationPoints(); + for (std::size_t g = 0; g < rGeom.IntegrationPointsNumber(); ++g) + for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i) + Check(r_shape_functions_values(g, i), rGeom, i, r_integration_points[g]); + KRATOS_CATCH(""); +} + +void Check_ShapeFunctionsValues2(Geometry> const& rGeom) +{ + KRATOS_TRY; + const auto& r_integration_points = rGeom.IntegrationPoints(); + Vector shape_functions_values(rGeom.PointsNumber()); + for (std::size_t g = 0; g < rGeom.IntegrationPointsNumber(); ++g) + { + rGeom.ShapeFunctionsValues(shape_functions_values, r_integration_points[g]); + for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i) + Check(shape_functions_values[i], rGeom, i, r_integration_points[g]); + } + KRATOS_CATCH(""); +} + +void Check_ShapeFunctionsValues3(Geometry> const& rGeom) +{ + KRATOS_TRY; + const Matrix& r_shape_functions_values = + rGeom.ShapeFunctionsValues(GeometryData::GI_GAUSS_1); + const auto& r_integration_points = rGeom.IntegrationPoints(GeometryData::GI_GAUSS_1); + for (std::size_t g = 0; g < rGeom.IntegrationPointsNumber(GeometryData::GI_GAUSS_1); ++g) + for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i) + Check(r_shape_functions_values(g, i), rGeom, i, r_integration_points[g]); + KRATOS_CATCH(""); +} + +void Check_ShapeFunctionsValues4(Geometry> const& rGeom) +{ + KRATOS_TRY; + const auto& r_integration_points = rGeom.IntegrationPoints(); + for (std::size_t g = 0; g < rGeom.IntegrationPointsNumber(); ++g) + for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i) + Check(rGeom.ShapeFunctionValue(g, i), rGeom, i, r_integration_points[g]); + KRATOS_CATCH(""); +} + +void Check_ShapeFunctionsValues5(Geometry> const& rGeom) +{ + KRATOS_TRY; + const auto& r_integration_points = rGeom.IntegrationPoints(GeometryData::GI_GAUSS_1); + for (std::size_t g = 0; g < rGeom.IntegrationPointsNumber(GeometryData::GI_GAUSS_1); ++g) + for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i) + Check(rGeom.ShapeFunctionValue(g, i, GeometryData::GI_GAUSS_1), rGeom, i, r_integration_points[g]); + KRATOS_CATCH(""); +} + +void Check(double N, + Geometry> const& rGeom, + Geometry>::IndexType ShapeFunctionIndex, + array_1d const& rCoord) +{ + KRATOS_TRY; + KRATOS_CHECK_NEAR(N, rGeom.ShapeFunctionValue(ShapeFunctionIndex, rCoord), TOLERANCE); + KRATOS_CATCH(""); +} + +} +} +} diff --git a/kratos/tests/cpp_tests/sources/test_amatrix.cpp b/kratos/tests/cpp_tests/sources/test_amatrix.cpp new file mode 100644 index 000000000000..477c63a6492c --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_amatrix.cpp @@ -0,0 +1,37 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + +#ifdef KRATOS_USE_AMATRIX // This macro definition is for the migration period and to be removed afterward please do not use it + +// Project includes +#include "testing/testing.h" +#include "includes/amatrix_interface.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(AMatrixSum, KratosCoreFastSuite) + { + DenseVector a{ 1.0, 2.0, 3.1 }; + KRATOS_CHECK_EQUAL(sum(a), 6.1); + } + + } +} // namespace Kratos. +#endif // ifdef KRATOS_USE_AMATRIX diff --git a/kratos/tests/cpp_tests/sources/test_amatrix_alias.cpp b/kratos/tests/cpp_tests/sources/test_amatrix_alias.cpp new file mode 100644 index 000000000000..c350dcca0af9 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_amatrix_alias.cpp @@ -0,0 +1,134 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Jordi Cotela +// + +#ifdef KRATOS_USE_AMATRIX +#ifdef KRATOS_DEBUG + +// Project includes +#include "testing/testing.h" +#include "includes/checks.h" +#include "includes/amatrix_interface.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasProd, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Matrix B = ScalarMatrix(2,2,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = prod(A,B), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(A,B), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = A * B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * A, "Aliasing found in assigning Matrix" ); +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasTranspose, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Matrix B = ScalarMatrix(2,2,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = trans(A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = trans(A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,trans(A)), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = trans(A) * B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * trans(A), "Aliasing found in assigning Matrix" ); +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasProdBounded, KratosCoreFastSuite) +{ + BoundedMatrix A = ScalarMatrix(2,2,1.0); + BoundedMatrix B = ScalarMatrix(2,2,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = prod(A,B), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(A,B), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = A * B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * A, "Aliasing found in assigning Matrix" ); +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasTransposeBounded, KratosCoreFastSuite) +{ + BoundedMatrix A = ScalarMatrix(2,2,1.0); + BoundedMatrix B = ScalarMatrix(2,2,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = trans(A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = trans(A), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,trans(A)), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = trans(A) * B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * trans(A), "Aliasing found in assigning Matrix" ); +} + + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasProdVector, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Vector b = ScalarMatrix(2,1,2.0); + Vector c = ScalarMatrix(2,1,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(b) = prod(A,b), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( b = prod(A,b), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( b = A * b, "Aliasing found in assigning Matrix" ); + c = A * b; // This one has no alias, should not throw +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasProdVectorBounded, KratosCoreFastSuite) +{ + BoundedMatrix A = ScalarMatrix(2,2,1.0); + BoundedVector b = ScalarMatrix(2,1,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(b) = prod(A,b), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( b = prod(A,b), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( b = A * b, "Aliasing found in assigning Matrix" ); +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasProdProd, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Matrix B = ScalarMatrix(2,2,2.0); + Matrix C = ScalarMatrix(2,2,3.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = prod(B,prod(C,A)), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,prod(C,A)), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * C * A, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = prod(B,prod(C,trans(A))), "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = B * C * trans(A), "Aliasing found in assigning Matrix" ); +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasSum, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Matrix B = ScalarMatrix(2,2,2.0); + + // These should not throw + A = A + B; + A += A; + A -= A; +} + +KRATOS_TEST_CASE_IN_SUITE(TestAMatrixAliasSumTranspose, KratosCoreFastSuite) +{ + Matrix A = ScalarMatrix(2,2,1.0); + Matrix B = ScalarMatrix(2,2,2.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( noalias(A) = trans(A) + B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A = trans(A) + B, "Aliasing found in assigning Matrix" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A += trans(A), "Aliasing found in += operator" ); + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN( A -= trans(A), "Aliasing found in -= operator" ); +} + +} // namespace Testing. +} // namespace Kratos. + +#endif // KRATOS_DEBUG +#endif // KRATOS_USE_AMATRIX diff --git a/kratos/tests/cpp_tests/sources/test_checks.cpp b/kratos/tests/cpp_tests/sources/test_checks.cpp new file mode 100644 index 000000000000..5ad2facbc124 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_checks.cpp @@ -0,0 +1,102 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/model_part.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(Checks, KratosCoreFastSuite) + { + KRATOS_CHECK(true); + KRATOS_CHECK_IS_FALSE(false); + + KRATOS_CHECK_EQUAL(1.0, 1.0); + KRATOS_CHECK_NOT_EQUAL(1.0, 2.0); + + KRATOS_CHECK_C_STRING_EQUAL("Test", "Test"); + KRATOS_CHECK_C_STRING_NOT_EQUAL("Test ", "Test"); + + KRATOS_CHECK_LESS(1., 2.); + KRATOS_CHECK_LESS_EQUAL(1., 1.); + + KRATOS_CHECK_GREATER(2., 1.); + KRATOS_CHECK_GREATER_EQUAL(2., 2.); + + KRATOS_CHECK_STRING_CONTAIN_SUB_STRING(std::string("Test"), "es"); + } + + KRATOS_TEST_CASE_IN_SUITE(VariableChecks, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(PRESSURE); + model_part.AddNodalSolutionStepVariable(REACTION); + + model_part.SetBufferSize(1); + + model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + for (auto it_node = model_part.NodesBegin(); + it_node != model_part.NodesEnd(); ++it_node) + { + it_node->AddDof(VELOCITY_Y, REACTION_Y); + it_node->AddDof(PRESSURE); + } + + Node<3>& r_node = *(model_part.NodesBegin()); + + // These functions throw an error if the check fails + // Expected passes: test OK if no error is thrown + KRATOS_CHECK_VARIABLE_KEY(VELOCITY); + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY, r_node); + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(PRESSURE, r_node); + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY_X, r_node); + KRATOS_CHECK_DOF_IN_NODE(VELOCITY_Y, r_node); + KRATOS_CHECK_DOF_IN_NODE(PRESSURE, r_node); + + // Expected fails: test failed unless an error is thrown + KRATOS_CHECK_EXCEPTION_IS_THROWN( + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(BODY_FORCE, r_node), + "Missing BODY_FORCE variable in solution step data for node " + "1."); + KRATOS_CHECK_EXCEPTION_IS_THROWN( + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(BODY_FORCE_X, r_node), + "Missing BODY_FORCE_X variable in solution step data for node " + "1."); + KRATOS_CHECK_EXCEPTION_IS_THROWN( + KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(TEMPERATURE, r_node), + "Missing TEMPERATURE variable in solution step data for node " + "1."); + KRATOS_CHECK_EXCEPTION_IS_THROWN( + KRATOS_CHECK_DOF_IN_NODE(TEMPERATURE, r_node), + "Missing Degree of Freedom for TEMPERATURE in node 1."); + KRATOS_CHECK_EXCEPTION_IS_THROWN( + KRATOS_CHECK_DOF_IN_NODE(VELOCITY_X, r_node), + "Missing Degree of Freedom for VELOCITY_X in node 1."); + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_chunk.cpp b/kratos/tests/cpp_tests/sources/test_chunk.cpp new file mode 100644 index 000000000000..a7b6e4a48936 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_chunk.cpp @@ -0,0 +1,164 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes +#include + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "includes/chunk.h" +#include "utilities/openmp_utils.h" + + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(ChunkInitialize, KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + + std::size_t block_size_in_bytes = 5; // the aligned block size is 8 + std::size_t header_size = 2 * max_threads * sizeof(Chunk::SizeType); + std::size_t chunk_size_in_bytes = header_size + 5; + Chunk too_small_chunk(block_size_in_bytes, chunk_size_in_bytes); + too_small_chunk.Initialize(); + KRATOS_CHECK_EQUAL(too_small_chunk.GetNumberOfAvailableBlocks(), 0) << " Available block :" << too_small_chunk.GetNumberOfAvailableBlocks(); + + chunk_size_in_bytes = header_size + 1024; + Chunk chunk(block_size_in_bytes, chunk_size_in_bytes); + chunk.Initialize(); + std::size_t block_size_after_alignment = 8; + std::size_t available_blocks_should_be = (chunk_size_in_bytes - 2* max_threads * sizeof(Chunk::SizeType)) / block_size_after_alignment; + KRATOS_CHECK_EQUAL(chunk.GetNumberOfAvailableBlocks(), available_blocks_should_be) << " Available block :" << chunk.GetNumberOfAvailableBlocks() << " vs " << available_blocks_should_be; + + } + + KRATOS_TEST_CASE_IN_SUITE(ChunkAllocateDeallocate, KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + std::size_t block_size_in_bytes = 5; + std::size_t header_size = 2 * max_threads * sizeof(Chunk::SizeType); + std::size_t chunk_size_in_bytes = header_size + 1024; + Chunk chunk(block_size_in_bytes, chunk_size_in_bytes); + + chunk.Initialize(); + + std::set pointer_set; + while (chunk.HasAvailableBlock()) + { + void* p = chunk.Allocate(); + KRATOS_ERROR_IF(pointer_set.find(p) != pointer_set.end()) << "The allocated position #" << pointer_set.size() + 1 << " was allocated before"; + pointer_set.insert(p); + } + KRATOS_CHECK_EQUAL(pointer_set.size(), chunk.GetNumberOfBlocks()) << " (pointer set size : " << pointer_set.size() << ")" << std::endl; + + for (auto i_pointer = pointer_set.begin(); i_pointer != pointer_set.end(); i_pointer++) { + chunk.Deallocate(*i_pointer); + } + KRATOS_CHECK_EQUAL(chunk.GetNumberOfAvailableBlocks(), chunk.GetNumberOfBlocks()); + } + + KRATOS_TEST_CASE_IN_SUITE(ChunkParallelAllocate, KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + std::size_t block_size_in_bytes = 5; + std::size_t header_size = 2 * max_threads * sizeof(Chunk::SizeType); + std::size_t chunk_size_in_bytes = header_size + 1024; + + auto repeat_number = 10; + std::stringstream buffer; +#pragma omp parallel for + for (auto i_repeat = 0; i_repeat < repeat_number; i_repeat++) + { + try { + Chunk chunk(block_size_in_bytes, chunk_size_in_bytes); + chunk.Initialize(); + std::size_t size = 100; + + for (std::size_t i = 0; i < size; i++) + { + if (chunk.HasAvailableBlock()) { + void* p = chunk.Allocate(); + KRATOS_CHECK_NOT_EQUAL(p, nullptr); + } + } + } + catch (Exception& e) { + + buffer << e; + } + catch (...) { + + buffer << "UknownError"; + } + } + if (!buffer.str().empty()) + KRATOS_ERROR << buffer.str(); + + } + + + KRATOS_TEST_CASE_IN_SUITE(ChunkParallelAllocateDeallocate, EXCLUDED_KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + std::size_t block_size_in_bytes = 5; + std::size_t header_size = 2 * max_threads * sizeof(Chunk::SizeType); + std::size_t chunk_size_in_bytes = header_size + 1024; + + auto repeat_number = 100; + std::stringstream buffer; + +#pragma omp parallel for + for (auto i_repeat = 0; i_repeat < repeat_number; i_repeat++) + { + try { + Chunk chunk(block_size_in_bytes, chunk_size_in_bytes); + chunk.Initialize(); + std::size_t size = 100; + std::vector the_vector(size); + + + for (std::size_t i = 0; i < size; i++) + { + the_vector[i] = chunk.Allocate(); + KRATOS_CHECK_NOT_EQUAL(the_vector[i], nullptr) << " for i = " << i << " and repeat = " << i_repeat; + + } + + for (std::size_t i = 0; i < size; i++) + chunk.Deallocate(the_vector[i]); + } + catch (Exception& e) { +#pragma omp critical + buffer << e; + + } + catch (...) { +#pragma omp critical + buffer << "UknownError"; + + } + } + if (!buffer.str().empty()) + KRATOS_ERROR << buffer.str(); + + } + + + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_code_location.cpp b/kratos/tests/cpp_tests/sources/test_code_location.cpp new file mode 100644 index 000000000000..6a7ad60fcb39 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_code_location.cpp @@ -0,0 +1,63 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" + + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(CodeLocation, KratosCoreFastSuite) + { + CodeLocation location1(R"string([C:\kratos\kratos\sources\model_part_io.cpp)string", + R"string(iterators::indirect_iterator< std::_Vector_iterator< std::_Vector_val > > >, struct iterators::use_default, struct iterators::use_default, struct iterators::use_default, struct iterators::use_default> ModelPartIO::FindKey< PointerVectorSet< Element, IndexedObject, struct std::less, struct std::equal_to, shared_ptr< Element>, std::vector< shared_ptr< Element>, std::allocator< shared_ptr< Element> > > >, unsigned __int64>(PointerVectorSet< Element, IndexedObject, struct std::less, struct std::equal_to, shared_ptr< Element>, std::vector< shared_ptr< Element>, std::allocator< shared_ptr< Element> > > > &, unsigned __int64, std::basic_string, std::allocator >))string", 3552); + KRATOS_CHECK_LESS(location1.CleanFunctionName().size(), 240); // the original size was 826 + KRATOS_CHECK_C_STRING_EQUAL(location1.CleanFileName().c_str(), "kratos/sources/model_part_io.cpp"); + + std::string functions = R"string(void ResidualBasedBlockBuilderAndSolver< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, LinearSolver< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, Reorderer< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > > > > >::SystemSolveWithPhysics( ublas::compressed_matrix,0, ublas::unbounded_array >, ublas::unbounded_array > &, ublas::vector > &, ublas::vector > &, ModelPart &) +void ResidualBasedBlockBuilderAndSolver< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, LinearSolver< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, Reorderer< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > > > > >::BuildAndSolve( shared_ptr< Scheme< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > > > >, ModelPart &, ublas::compressed_matrix,0, ublas::unbounded_array >, ublas::unbounded_array > &, ublas::vector > &, ublas::vector > &) [ C:\KratosSource\kratos\solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h , Line 610 ] + +double ResidualBasedLinearStrategy< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, LinearSolver< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > >, Reorderer< UblasSpace,0, ublas::unbounded_array >, ublas::unbounded_array >, ublas::vector > >, UblasSpace, ublas::unbounded_array >, ublas::vector > > > > >::Solve(void) [ C:\KratosSource\kratos\solving_strategies/strategies/residualbased_linear_strategy.h , Line 465 ] + +)string"; + CodeLocation location2(R"string(C:\KratosSource\kratos\solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h)string", functions, 559); + KRATOS_CHECK_LESS(location2.CleanFunctionName().size(), 1000); // the original size was 5858 + //std::cout << location2.GetFunctionName() << std::endl; + std::cout << "size: " << location2.GetFunctionName().size() << std::endl; + //std::cout << " ERROR -------------------------------------------------------------------------------------------------------------------------" << std::endl; + //std::cout << location2.CleanFunctionName() << std::endl; + //std::cout << " -------------------------------------------------------------------------------------------------------------------------------" << std::endl; + //std::cout << "size: " << location2.CleanFunctionName().size() << std::endl; + } + + KRATOS_TEST_CASE_IN_SUITE(CodeLocationTemplateParameterReduction, KratosCoreFastSuite) + { + CodeLocation location1("", "ublas::vector >", 0); + KRATOS_CHECK_C_STRING_EQUAL(location1.CleanFunctionName().c_str(), "Vector"); + CodeLocation location2("", "iterators::indirect_iterator< std::_Vector_iterator< std::_Vector_val > > >, struct iterators::use_default, struct iterators::use_default, struct iterators::use_default, struct iterators::use_default>", 0); + KRATOS_CHECK_C_STRING_EQUAL(location2.CleanFunctionName().c_str(), "iterators::indirect_iterator< _Vector_iterator< _Vector_val > > >,...>"); + + } + + } +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/sources/test_compare_elements_and_conditions_utility.cpp b/kratos/tests/cpp_tests/sources/test_compare_elements_and_conditions_utility.cpp new file mode 100644 index 000000000000..f75bc5e23b76 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_compare_elements_and_conditions_utility.cpp @@ -0,0 +1,152 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// +// + +// System includes + +// External includes + +// Project includes +#include "testing/testing.h" +#include "utilities/compare_elements_and_conditions_utility.h" + +#include "includes/element.h" +#include "includes/condition.h" +#include "includes/kratos_components.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/quadrilateral_2d_4.h" + +namespace Kratos { +namespace Testing { + +class CustomElement : public Element +{ + public: + CustomElement(Element::IndexType NewId, Element::GeometryType::Pointer pGeometry) : + Element(NewId, pGeometry) + {} +}; + +class CustomCondition : public Condition +{ + public: + CustomCondition(Condition::IndexType NewId, Condition::GeometryType::Pointer pGeometry) : + Condition(NewId, pGeometry) + {} +}; + +Element::Pointer CreateCustomElement2D3N(Element::IndexType Id) +{ + Element::GeometryType::Pointer p_geom(new Triangle2D3(Element::GeometryType::PointsArrayType(3))); + return Element::Pointer(new CustomElement(Id, p_geom)); +} + +Element::Pointer CreateCustomElement2D4N(Element::IndexType Id) +{ + Element::GeometryType::Pointer p_geom(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4))); + return Element::Pointer(new CustomElement(Id, p_geom)); +} + +Condition::Pointer CreateCustomCondition2D3N(Condition::IndexType Id) +{ + Condition::GeometryType::Pointer p_geom(new Triangle2D3(Condition::GeometryType::PointsArrayType(3))); + return Condition::Pointer(new CustomCondition(Id, p_geom)); +} + +Condition::Pointer CreateCustomCondition2D4N(Condition::IndexType Id) +{ + Condition::GeometryType::Pointer p_geom(new Quadrilateral2D4(Condition::GeometryType::PointsArrayType(4))); + return Condition::Pointer(new CustomCondition(Id, p_geom)); +} + +KRATOS_TEST_CASE_IN_SUITE(IsSame_Element_Element, KratosCoreFastSuite) +{ + auto p_custom_element_2d_3n_1 = CreateCustomElement2D3N(1); + const Element& r_custom_element_2d_3n_1 = *p_custom_element_2d_3n_1; + auto p_custom_element_2d_3n_2 = CreateCustomElement2D3N(2); + // same element type, same geometry type. + KRATOS_CHECK(GeometricalObject::IsSame(r_custom_element_2d_3n_1, *p_custom_element_2d_3n_2)); + KRATOS_CHECK(GeometricalObject::IsSame(&r_custom_element_2d_3n_1, &(*p_custom_element_2d_3n_2))); + KRATOS_CHECK(GeometricalObject::IsSame(*p_custom_element_2d_3n_2, r_custom_element_2d_3n_1)); + KRATOS_CHECK(GeometricalObject::IsSame(&(*p_custom_element_2d_3n_2), &r_custom_element_2d_3n_1)); + // different element type, same geometry type. + const Element& r_element_2d_3n = KratosComponents::Get("Element2D3N"); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_element_2d_3n, *p_custom_element_2d_3n_1)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_element_2d_3n, &(*p_custom_element_2d_3n_1))); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(*p_custom_element_2d_3n_1, r_element_2d_3n)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&(*p_custom_element_2d_3n_1), &r_element_2d_3n)); + // same element type, different geometry type. + auto p_custom_element_2d_4n_3 = CreateCustomElement2D4N(3); + const Element& r_custom_element_2d_4n_3 = *p_custom_element_2d_4n_3; + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_custom_element_2d_3n_1, r_custom_element_2d_4n_3)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_custom_element_2d_3n_1, &r_custom_element_2d_4n_3)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_custom_element_2d_4n_3, r_custom_element_2d_3n_1)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_custom_element_2d_4n_3, &r_custom_element_2d_3n_1)); +} + +KRATOS_TEST_CASE_IN_SUITE(IsSame_Condition_Condition, KratosCoreFastSuite) +{ + auto p_custom_condition_2d_3n_1 = CreateCustomCondition2D3N(1); + const Condition& r_custom_condition_2d_3n_1 = *p_custom_condition_2d_3n_1; + auto p_custom_condition_2d_3n_2 = CreateCustomCondition2D3N(2); + // same condition type, same geometry type. + KRATOS_CHECK(GeometricalObject::IsSame(r_custom_condition_2d_3n_1, *p_custom_condition_2d_3n_2)); + KRATOS_CHECK(GeometricalObject::IsSame(&r_custom_condition_2d_3n_1, &(*p_custom_condition_2d_3n_2))); + KRATOS_CHECK(GeometricalObject::IsSame(*p_custom_condition_2d_3n_2, r_custom_condition_2d_3n_1)); + KRATOS_CHECK(GeometricalObject::IsSame(&(*p_custom_condition_2d_3n_2), &r_custom_condition_2d_3n_1)); + // different condition type, same geometry type. + const Condition& r_condition_2d_3n = KratosComponents::Get("Condition2D3N"); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_condition_2d_3n, *p_custom_condition_2d_3n_1)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_condition_2d_3n, &(*p_custom_condition_2d_3n_1))); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(*p_custom_condition_2d_3n_1, r_condition_2d_3n)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&(*p_custom_condition_2d_3n_1), &r_condition_2d_3n)); + // same condition type, different geometry type. + auto p_custom_condition_2d_4n_3 = CreateCustomCondition2D4N(3); + const Condition& r_custom_condition_2d_4n_3 = *p_custom_condition_2d_4n_3; + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_custom_condition_2d_3n_1, r_custom_condition_2d_4n_3)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_custom_condition_2d_3n_1, &r_custom_condition_2d_4n_3)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(r_custom_condition_2d_4n_3, r_custom_condition_2d_3n_1)); + KRATOS_CHECK_IS_FALSE(GeometricalObject::IsSame(&r_custom_condition_2d_4n_3, &r_custom_condition_2d_3n_1)); +} + +KRATOS_TEST_CASE_IN_SUITE(GetRegisteredNameElement, KratosCoreFastSuite) +{ + // Element name + const Element& r_element_2d_3n = KratosComponents::Get("Element2D3N"); + std::string component_name; + CompareElementsAndConditionsUtility::GetRegisteredName(r_element_2d_3n, component_name); + KRATOS_CHECK_EQUAL(component_name, "Element2D3N"); + CompareElementsAndConditionsUtility::GetRegisteredName(&r_element_2d_3n, component_name); + KRATOS_CHECK_EQUAL(component_name, "Element2D3N"); + CompareElementsAndConditionsUtility::GetRegisteredName(r_element_2d_3n, component_name); + KRATOS_CHECK_NOT_EQUAL(component_name, "Element"); + CompareElementsAndConditionsUtility::GetRegisteredName(&r_element_2d_3n, component_name); + KRATOS_CHECK_NOT_EQUAL(component_name, "Element"); +} + +KRATOS_TEST_CASE_IN_SUITE(GetRegisteredNameCondition, KratosCoreFastSuite) +{ + // Condition name + const Condition& r_condition_2d_3n = KratosComponents::Get("Condition2D3N"); + std::string component_name; + CompareElementsAndConditionsUtility::GetRegisteredName(r_condition_2d_3n, component_name); + KRATOS_CHECK_EQUAL(component_name, "Condition2D3N"); + CompareElementsAndConditionsUtility::GetRegisteredName(&r_condition_2d_3n, component_name); + KRATOS_CHECK_EQUAL(component_name, "Condition2D3N"); + CompareElementsAndConditionsUtility::GetRegisteredName(r_condition_2d_3n, component_name); + KRATOS_CHECK_NOT_EQUAL(component_name, "Condition"); + CompareElementsAndConditionsUtility::GetRegisteredName(&r_condition_2d_3n, component_name); + KRATOS_CHECK_NOT_EQUAL(component_name, "Condition"); +} + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_condition.cpp b/kratos/tests/cpp_tests/sources/test_condition.cpp new file mode 100644 index 000000000000..df735bbc619f --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_condition.cpp @@ -0,0 +1,63 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// +// + +// Project includes +#include "testing/testing.h" +#include "includes/model_part.h" +#include "containers/model.h" + + +namespace Kratos { + namespace Testing { + typedef Node<3> NodeType; + typedef std::size_t IndexType; + + /** + * Here the clone operator is test + */ + KRATOS_TEST_CASE_IN_SUITE(ConditionCloneOperator, KratosCoreFastSuite) + { + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test"); + + // Definition of nodes + auto p_node1 = model_part.CreateNewNode(1, 1.0, 0.0, 0.0); + auto p_node2 = model_part.CreateNewNode(2, 1.0, 1.0, 0.0); + auto p_node3 = model_part.CreateNewNode(3, 1.0, 1.0, 0.0); + + // Definition of properties + auto p_prop = model_part.pGetProperties(1); + + // List onf nodes + std::vector list_nodes(3); + list_nodes[0] = p_node1; + list_nodes[1] = p_node2; + list_nodes[2] = p_node3; + + auto p_cond = model_part.CreateNewCondition("Condition3D", 1, PointerVector{list_nodes}, p_prop); + + p_cond->SetValue(DISTANCE, 12.1); + p_cond->SetValue(VELOCITY_X, 32.4); + p_cond->Set(ACTIVE, true); + + Condition::Pointer p_clone_of_cond = p_cond->Clone(2, PointerVector{list_nodes}); + + KRATOS_CHECK_EQUAL(p_clone_of_cond->Id(), 2); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_cond->GetValue(DISTANCE), 12.1); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_cond->GetValue(VELOCITY_X), 32.4); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_cond->GetValue(VELOCITY_Y), 0.00); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_cond->GetValue(VELOCITY_Z), 0.00); + KRATOS_CHECK(p_clone_of_cond->Is(ACTIVE)); + } + } // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_dof.cpp b/kratos/tests/cpp_tests/sources/test_dof.cpp new file mode 100644 index 000000000000..b87fa1bd3a1f --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_dof.cpp @@ -0,0 +1,151 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "includes/model_part.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(DofConstructorWtihoutVariableInVariablesList, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.SetBufferSize(1); + + auto p_node = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN(p_node->AddDof(VELOCITY_Y), + "Error: The Dof-Variable VELOCITY_Y is not in the list of variables"); +} + +KRATOS_TEST_CASE_IN_SUITE(DofConstructorWtihoutReactionInVariablesList, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + + model_part.SetBufferSize(1); + + auto p_node = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + KRATOS_DEBUG_CHECK_EXCEPTION_IS_THROWN(p_node->AddDof(VELOCITY_Y, REACTION_Y), + "Error: The Reaction-Variable REACTION_Y is not in the list of variables"); +} + +KRATOS_TEST_CASE_IN_SUITE(DofFixing, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(REACTION); + + model_part.SetBufferSize(1); + + auto p_node = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + auto p_dof = p_node->pAddDof(VELOCITY_Y, REACTION_Y); + + // Checking default fixities + KRATOS_CHECK(p_dof->IsFree()); + KRATOS_CHECK_IS_FALSE(p_dof->IsFixed()); + + // Checking after fixing the dof + p_dof->FixDof(); + KRATOS_CHECK_IS_FALSE(p_dof->IsFree()); + KRATOS_CHECK(p_dof->IsFixed()); + + // Checking after freeing the dof + p_dof->FreeDof(); + KRATOS_CHECK(p_dof->IsFree()); + KRATOS_CHECK_IS_FALSE(p_dof->IsFixed()); +} + +KRATOS_TEST_CASE_IN_SUITE(DofVariables, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(REACTION); + + model_part.SetBufferSize(1); + + auto p_node = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + auto p_dof = p_node->pAddDof(VELOCITY_Y, REACTION_Y); + auto p_dof_2 = p_node->pAddDof(VELOCITY_Z); + + KRATOS_CHECK_EQUAL(VELOCITY_Y, p_dof->GetVariable()); + KRATOS_CHECK_EQUAL(REACTION_Y, p_dof->GetReaction()); + + KRATOS_CHECK_IS_FALSE(p_dof_2->HasReaction()); +} + +KRATOS_TEST_CASE_IN_SUITE(DofEquationId, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(REACTION); + + model_part.SetBufferSize(1); + + auto p_node = model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + + auto p_dof = p_node->pAddDof(VELOCITY_Y, REACTION_Y); + + const std::size_t eq_id= 569; + + p_dof->SetEquationId(eq_id); + + KRATOS_CHECK_EQUAL(eq_id, p_dof->EquationId()); +} + +KRATOS_TEST_CASE_IN_SUITE(DofId, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("TestModelPart"); + + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(REACTION); + + model_part.SetBufferSize(1); + + const std::size_t my_id = 4322; + + auto p_node = model_part.CreateNewNode(my_id, 0.0, 0.0, 0.0); + + auto p_dof = p_node->pAddDof(VELOCITY_Y, REACTION_Y); + + KRATOS_CHECK_EQUAL(my_id, p_dof->GetId()); + + const std::size_t my_id_new= 5609; + p_dof->SetId(my_id_new); + + KRATOS_CHECK_EQUAL(my_id_new, p_dof->Id()); + + KRATOS_CHECK_EQUAL(p_dof->GetId(), p_dof->Id()); +} +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_element.cpp b/kratos/tests/cpp_tests/sources/test_element.cpp new file mode 100644 index 000000000000..c0e5e708b29b --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_element.cpp @@ -0,0 +1,62 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// +// + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "includes/model_part.h" + +namespace Kratos { + namespace Testing { + typedef Node<3> NodeType; + typedef std::size_t IndexType; + + /** + * Here the clone operator is test + */ + KRATOS_TEST_CASE_IN_SUITE(ElementCloneOperator, KratosCoreFastSuite) + { + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test"); + + // Definition of nodes + auto p_node1 = model_part.CreateNewNode(1, 1.0, 0.0, 0.0); + auto p_node2 = model_part.CreateNewNode(2, 1.0, 1.0, 0.0); + auto p_node3 = model_part.CreateNewNode(3, 1.0, 1.0, 0.0); + + // Definition of properties + auto p_prop = model_part.pGetProperties(1); + + // List onf nodes + std::vector list_nodes(3); + list_nodes[0] = p_node1; + list_nodes[1] = p_node2; + list_nodes[2] = p_node3; + + auto p_elem = model_part.CreateNewElement("Element2D3N", 1, PointerVector{list_nodes}, p_prop); + + p_elem->SetValue(DISTANCE, 12.1); + p_elem->SetValue(VELOCITY_X, 32.4); + p_elem->Set(ACTIVE, true); + + Element::Pointer p_clone_of_elem = p_elem->Clone(2, PointerVector{list_nodes}); + + KRATOS_CHECK_EQUAL(p_clone_of_elem->Id(), 2); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_elem->GetValue(DISTANCE), 12.1); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_elem->GetValue(VELOCITY_X), 32.4); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_elem->GetValue(VELOCITY_Y), 0.00); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_elem->GetValue(VELOCITY_Z), 0.00); + KRATOS_CHECK(p_clone_of_elem->Is(ACTIVE)); + } + } // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_exceptions.cpp b/kratos/tests/cpp_tests/sources/test_exceptions.cpp new file mode 100644 index 000000000000..0389cb55a642 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_exceptions.cpp @@ -0,0 +1,42 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(ExceptionDefaultConstruction, KratosCoreFastSuite) + { + try { + throw Exception(); + } + catch (Exception& e) { + KRATOS_CHECK_C_STRING_EQUAL(e.what(), "Unknown Error\nin Unknown Location"); + KRATOS_CHECK_EQUAL(e.where().CleanFileName(), "Unknown File"); + KRATOS_CHECK_EQUAL(e.where().CleanFunctionName(), "Unknown Location"); + KRATOS_CHECK_EQUAL(e.where().GetLineNumber(), 0); + } + } + + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_linear_master_slave_constraint.cpp b/kratos/tests/cpp_tests/sources/test_linear_master_slave_constraint.cpp new file mode 100644 index 000000000000..d311467fad06 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_linear_master_slave_constraint.cpp @@ -0,0 +1,67 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Aditya Ghantasala / Philipp Bucher +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/model_part.h" +#include "includes/linear_master_slave_constraint.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(LinearMasterSlaveConstraintTests, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test_model_part",2); + model_part.AddNodalSolutionStepVariable(PRESSURE); + auto n1 = model_part.CreateNewNode(1, 0.00,0.00,0.00); + auto n2 = model_part.CreateNewNode(2, 1.00,0.00,0.00); + n1->AddDof(PRESSURE); + n2->AddDof(PRESSURE); + + auto c1 = model_part.CreateNewMasterSlaveConstraint("LinearMasterSlaveConstraint", 1, *n1, PRESSURE, *n2, PRESSURE, 1.0, 0.0); + + ProcessInfo& process_info = model_part.GetProcessInfo(); + LinearMasterSlaveConstraint::EquationIdVectorType master_vector; + LinearMasterSlaveConstraint::EquationIdVectorType slave_vector; + + c1->EquationIdVector(master_vector, slave_vector, process_info); + + LinearMasterSlaveConstraint::MatrixType transformation_matrix; + LinearMasterSlaveConstraint::VectorType constant_vector; + + c1->CalculateLocalSystem(transformation_matrix, constant_vector, process_info); + + + KRATOS_CHECK_EQUAL(master_vector.size(), 1); + KRATOS_CHECK_EQUAL(slave_vector.size(), 1); + + KRATOS_CHECK_EQUAL(transformation_matrix.size1(), 1); + KRATOS_CHECK_EQUAL(transformation_matrix.size2(), 1); + KRATOS_CHECK_EQUAL(constant_vector.size(), 1); + + KRATOS_CHECK_DOUBLE_EQUAL(transformation_matrix(0,0), 1.0); // TODO: Check -> comparison between two doubles ?? + KRATOS_CHECK_DOUBLE_EQUAL(constant_vector(0), 0.0); +} + +} +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/sources/test_memory_pool.cpp b/kratos/tests/cpp_tests/sources/test_memory_pool.cpp new file mode 100644 index 000000000000..364fdb1b8bcf --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_memory_pool.cpp @@ -0,0 +1,163 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes +#include +// External includes + + +// Project includes +#include "testing/testing.h" +#include "includes/pool_object.h" + + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(FixedSizeMemoryPoolConstruction, KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + std::size_t block_size = 5; + std::size_t default_chunk_size = 1024 * 1024; // 1M + FixedSizeMemoryPool fixed_size_memory_pool(block_size); + std::size_t empty_size = sizeof(ThreadFixedSizeMemoryPool) * max_threads + sizeof(FixedSizeMemoryPool); + KRATOS_CHECK_EQUAL(fixed_size_memory_pool.GetNumberOfAllocatedChunks(), 0); + KRATOS_CHECK_EQUAL(fixed_size_memory_pool.ChunkSize(), default_chunk_size); + KRATOS_CHECK_EQUAL(fixed_size_memory_pool.MemoryUsed(), empty_size); + } + + KRATOS_TEST_CASE_IN_SUITE(FixedSizeMemoryPoolAllocationDeallocation, KratosCoreFastSuite) + { + int max_threads = LockObject::GetNumberOfThreads(); + std::size_t block_size = 15; + std::size_t default_chunk_size = 1024 * 1024; // 1M + std::size_t number_of_blocks = (default_chunk_size - 2 * max_threads * sizeof(Chunk::SizeType)) / 16; + FixedSizeMemoryPool fixed_size_memory_pool(block_size); + + + std::size_t repeat_number = 2; + for (std::size_t i_repeat = 1; i_repeat <= repeat_number; i_repeat++) + { + std::set pointer_set; + for (std::size_t i_chunk = 0; i_chunk < i_repeat; i_chunk++) + for (std::size_t i_block = 0; i_block < number_of_blocks; i_block++) + { + void* p = fixed_size_memory_pool.Allocate(); + KRATOS_ERROR_IF(pointer_set.find(p) != pointer_set.end()) + << "The allocated position #" << pointer_set.size() + 1 << " was allocated before"; + pointer_set.insert(p); + } + + for (auto i_pointer = pointer_set.begin(); i_pointer != pointer_set.end(); i_pointer++) { + fixed_size_memory_pool.Deallocate(*i_pointer); + } + std::size_t number_of_chunks = i_repeat;// ((i_repeat / OpenMPUtils::GetNumThreads()) + 1) * OpenMPUtils::GetNumThreads(); + KRATOS_CHECK_EQUAL(fixed_size_memory_pool.GetNumberOfAllocatedChunks(), number_of_chunks) << " (number_of_chunks = " << number_of_chunks << ")"; + KRATOS_CHECK_EQUAL(fixed_size_memory_pool.ChunkSize(), default_chunk_size); + } + } + + //KRATOS_TEST_CASE_IN_SUITE(FixedSizeMemoryPoolStressTest, KratosCoreStressSuite) + //{ + // int max_threads = LockObject::GetNumberOfThreads(); + // std::size_t block_size = 64; + // std::size_t default_chunk_size = 1024 * 1024;// 1M + // std::size_t number_of_blocks = (default_chunk_size - 2 * max_threads * sizeof(Chunk::SizeType)) / 64; + // FixedSizeMemoryPool fixed_size_memory_pool(block_size); + + // auto repeat_number = 100; + // for (auto i_repeat = 1; i_repeat <= repeat_number; i_repeat++) + // { + // KRATOS_WATCH(i_repeat); + // std::vector pointer_vector; + // for (auto i_chunk = 0; i_chunk < i_repeat; i_chunk++) + // for (std::size_t i_block = 0; i_block < number_of_blocks; i_block++) + // { + // void* p = fixed_size_memory_pool.Allocate(); + // KRATOS_CHECK_NOT_EQUAL(p, nullptr) << " i_repeat : " << i_repeat << " , i_chunk : " << i_chunk << " , i_block : " << i_block; + // pointer_vector.push_back(p); + + // } + + // for (auto i_pointer = pointer_vector.begin(); i_pointer != pointer_vector.end(); i_pointer++) { + // fixed_size_memory_pool.Deallocate(*i_pointer); + // } + // } + + //} + + //KRATOS_TEST_CASE_IN_SUITE(MemoryPool, KratosCoreFastSuite) + //{ + // std::size_t block_size = 61; + // auto number_of_blocks = 4096; + // MemoryPool::AddPool("TestPool", new FixedSizeMemoryPool(block_size, number_of_blocks)); + + // KRATOS_ERROR << MemoryPool::Info() << std::endl; + //} + + class Block64byte : public PoolObject{ + public: + Block64byte() {Block[0] = 0;}; + private: + double Block[8]; + }; + + KRATOS_DISABLED_TEST_CASE_IN_SUITE(PoolObjectParallelNewDelete, KratosCoreFastSuite) + { + std::cout << MemoryPool::Info() << std::endl; + auto repeat_number = 120; +#pragma omp parallel for + for (auto i_repeat = 0; i_repeat < repeat_number; i_repeat++) + { + try { + std::size_t size = 1024 * 1024; + std::vector the_vector(size); + + for (std::size_t i = 0; i < size; i++) + the_vector[i] = new Block64byte; + + for (std::size_t i = 0; i < size; i++) + delete the_vector[i]; + } + catch(Exception& e){ + std::cout << e << std::endl; + } + catch (...) { + std::cout << "Unknown Error" << std::endl; + } + } + + std::cout << MemoryPool::Info() << std::endl; + } + + //KRATOS_TEST_CASE_IN_SUITE(NormalNewDelete, KratosCoreStressSuite) + //{ + // auto repeat_number = 128; + // for (auto i_repeat = 1; i_repeat <= repeat_number; i_repeat++) + // { + // std::vector the_vector; + + // for (auto i_chunk = 0; i_chunk < i_repeat; i_chunk++) + // for (auto i_block = 0; i_block < 4096; i_block++) + // the_vector.push_back(new Block64byte); + + // for (std::size_t i = 0; i < the_vector.size(); i++) { + // delete the_vector[i]; + // } + // } + + //} + + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_model_part.cpp b/kratos/tests/cpp_tests/sources/test_model_part.cpp new file mode 100644 index 000000000000..00396d6ceed9 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_model_part.cpp @@ -0,0 +1,253 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// Philipp Bucher +// Vicente Mataix Ferrandiz +// + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "includes/model_part.h" +#include "utilities/auxiliar_model_part_utilities.h" + +namespace Kratos { + namespace Testing { + + typedef Node<3> NodeType; + + void GenerateGenericModelPart(ModelPart& rModelPart) + { + Properties::Pointer p_elem_prop = rModelPart.pGetProperties(0); + + // First we create the nodes + NodeType::Pointer p_node_1 = rModelPart.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = rModelPart.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = rModelPart.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = rModelPart.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = rModelPart.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = rModelPart.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector condition_nodes_0 (2); + condition_nodes_0[0] = p_node_1; + condition_nodes_0[1] = p_node_2; + + std::vector condition_nodes_1 (2); + condition_nodes_1[0] = p_node_1; + condition_nodes_1[1] = p_node_4; + + std::vector condition_nodes_2 (2); + condition_nodes_2[0] = p_node_2; + condition_nodes_2[1] = p_node_5; + + std::vector condition_nodes_3 (2); + condition_nodes_3[0] = p_node_5; + condition_nodes_3[1] = p_node_6; + + Condition::Pointer p_cond_0 = rModelPart.CreateNewCondition("Condition2D2N", 1, PointerVector{condition_nodes_0}, p_elem_prop); + Condition::Pointer p_cond_1 = rModelPart.CreateNewCondition("Condition2D2N", 2, PointerVector{condition_nodes_1}, p_elem_prop); + Condition::Pointer p_cond_2 = rModelPart.CreateNewCondition("Condition2D2N", 3, PointerVector{condition_nodes_2}, p_elem_prop); + Condition::Pointer p_cond_3 = rModelPart.CreateNewCondition("Condition2D2N", 4, PointerVector{condition_nodes_3}, p_elem_prop); + + // Now we create the "elements" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + + Element::Pointer p_elem_0 = rModelPart.CreateNewElement("Element2D3N", 1, PointerVector{element_nodes_0}, p_elem_prop); + Element::Pointer p_elem_1 = rModelPart.CreateNewElement("Element2D3N", 2, PointerVector{element_nodes_1}, p_elem_prop); + Element::Pointer p_elem_2 = rModelPart.CreateNewElement("Element2D3N", 3, PointerVector{element_nodes_2}, p_elem_prop); + Element::Pointer p_elem_3 = rModelPart.CreateNewElement("Element2D3N", 4, PointerVector{element_nodes_3}, p_elem_prop); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartSubModelPartsIterator, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + r_model_part.CreateSubModelPart("Inlet1"); + r_model_part.CreateSubModelPart("Inlet2"); + r_model_part.CreateSubModelPart("Outlet"); + r_model_part.CreateSubModelPart("AnotherOutlet"); + + std::size_t id = 1; + for(auto i_SubModelPart = r_model_part.SubModelPartsBegin() ; i_SubModelPart != r_model_part.SubModelPartsEnd() ; i_SubModelPart++){ + i_SubModelPart->CreateNewNode(id++, 0.00,0.00,0.00); + } + + KRATOS_CHECK_EQUAL(r_model_part.NumberOfNodes(), 4); + KRATOS_CHECK_EQUAL(r_model_part.GetSubModelPart("Inlet1").NumberOfNodes(), 1); + KRATOS_CHECK_EQUAL(r_model_part.GetSubModelPart("Outlet").NumberOfNodes(), 1); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartAddNodalSolutionStepVariable, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + r_model_part.AddNodalSolutionStepVariable(VELOCITY); + + r_model_part.CreateNewNode(123, 0.00,0.00,0.00); + + KRATOS_CHECK_EXCEPTION_IS_THROWN(r_model_part.AddNodalSolutionStepVariable(PRESSURE), + "Error: Attempting to add the variable \"PRESSURE\" to the model part with name \"Main\" which is not empty"); + + r_model_part.AddNodalSolutionStepVariable(VELOCITY); // Adding the same Variable twice is fine bcs it wont do anything + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartHasNodalSolutionStepVariable, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + + r_model_part.AddNodalSolutionStepVariable(VELOCITY); + + KRATOS_CHECK(r_model_part.HasNodalSolutionStepVariable(VELOCITY)); + KRATOS_CHECK_IS_FALSE(r_model_part.HasNodalSolutionStepVariable(PRESSURE)); + } + + + KRATOS_TEST_CASE_IN_SUITE(ModelPartEmptyName, KratosCoreFastSuite) + { + Model current_model; + + // Constructor with name + KRATOS_CHECK_EXCEPTION_IS_THROWN(current_model.CreateModelPart(""), + "Error: Please don't use empty names (\"\") when creating a ModelPart"); + + // Constructor with name and bufferSize + KRATOS_CHECK_EXCEPTION_IS_THROWN(current_model.CreateModelPart("", 2), + "Error: Please don't use empty names (\"\") when creating a ModelPart"); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartNameContainingPoint, KratosCoreFastSuite) + { + Model current_model; + + // Constructor with name + KRATOS_CHECK_EXCEPTION_IS_THROWN(current_model.CreateModelPart("name.other"), + "Error: Please don't use names containing (\".\") when creating a ModelPart"); + + // Constructor with name and bufferSize + KRATOS_CHECK_EXCEPTION_IS_THROWN(current_model.CreateModelPart("name.other", 2), + "Error: Please don't use names containing (\".\") when creating a ModelPart"); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartRemoveElements, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + // Fill model part + GenerateGenericModelPart(r_model_part); + + // Set flags + r_model_part.pGetElement(1)->Set(TO_ERASE, true); + r_model_part.pGetElement(2)->Set(TO_ERASE, true); + + // Call method + r_model_part.RemoveElements(TO_ERASE); + + // Check results + KRATOS_CHECK(r_model_part.NumberOfNodes() == 6); + KRATOS_CHECK(r_model_part.NumberOfElements() == 2); + KRATOS_CHECK(r_model_part.NumberOfConditions() == 4); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartRemoveElementsAndBelongings, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + // Fill model part + GenerateGenericModelPart(r_model_part); + + // Set flags + r_model_part.pGetElement(1)->Set(TO_ERASE, true); + r_model_part.pGetElement(2)->Set(TO_ERASE, true); + + // Call method + auto aux_util = AuxiliarModelPartUtilities(r_model_part); + aux_util.RemoveElementsAndBelongings(TO_ERASE); + + // Check results + KRATOS_CHECK(r_model_part.NumberOfNodes() == 4); + KRATOS_CHECK(r_model_part.NumberOfElements() == 2); + KRATOS_CHECK(r_model_part.NumberOfConditions() == 2); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartRemoveConditions, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + // Fill model part + GenerateGenericModelPart(r_model_part); + + // Set flags + r_model_part.pGetCondition(1)->Set(TO_ERASE, true); + r_model_part.pGetCondition(2)->Set(TO_ERASE, true); + + // Call method + r_model_part.RemoveConditions(TO_ERASE); + + // Check results + KRATOS_CHECK(r_model_part.NumberOfNodes() == 6); + KRATOS_CHECK(r_model_part.NumberOfConditions() == 2); + KRATOS_CHECK(r_model_part.NumberOfElements() == 4); + } + + KRATOS_TEST_CASE_IN_SUITE(ModelPartRemoveConditionsAndBelongings, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& r_model_part = current_model.CreateModelPart("Main"); + + // Fill model part + GenerateGenericModelPart(r_model_part); + + // Set flags + r_model_part.pGetCondition(1)->Set(TO_ERASE, true); + r_model_part.pGetCondition(2)->Set(TO_ERASE, true); + + // Call method + auto aux_util = AuxiliarModelPartUtilities(r_model_part); + aux_util.RemoveConditionsAndBelongings(TO_ERASE); + + // Check results + KRATOS_CHECK(r_model_part.NumberOfNodes() == 3); + KRATOS_CHECK(r_model_part.NumberOfConditions() == 2); + KRATOS_CHECK(r_model_part.NumberOfElements() == 2); + } + } // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_model_part_io.cpp b/kratos/tests/cpp_tests/sources/test_model_part_io.cpp new file mode 100644 index 000000000000..e90b15c76333 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_model_part_io.cpp @@ -0,0 +1,380 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "includes/model_part_io.h" +#include "includes/kratos_application.h" +#include "includes/kernel.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE( + ModelPartIOSubModelPartsDivision, KratosCoreFastSuite) { + Kratos::shared_ptr p_input(new std::stringstream( + R"input( + Begin ModelPartData + DENSITY 2700.000000 + BODY_FORCE [3] (0.000000,0.000000,0.000000) + End ModelPartData + + + Begin Properties 1 + DENSITY 2700.000000 + YOUNG_MODULUS 7000000.000000 + POISSON_RATIO 0.300000 + BODY_FORCE [3] (0.000000,0.000000,0.000000) + THICKNESS 1.000000 + End Properties + + Begin Nodes + 1 0.0 0.0 0.0 //node number, coord x, cord y, coord z + 2 1.0 0.0 0.0 //node number, coord x, cord y, coord z + 3 1.0 1.0 0.0 //node number, coord x, cord y, coord z + 4 0.0 1.0 0.0 //node number, coord x, cord y, coord z + End Nodes + + Begin Elements Element2D3N + 1 1 1 2 4 //the first column is the property + 2 1 3 4 2 + End Elements + + Begin NodalData DISPLACEMENT_X //be careful, variables are case sensitive! + 1 1 100.0 // pos1 is the node, pos2 (a 1) means that the DOF is fixed, then (position 3) we write the fixed displacement (in this case, temperature) + End NodalData + + Begin NodalData DISPLACEMENT_Y + 1 1 100.0 + End NodalData + + Begin NodalData FORCE_Y + 3 0 5.0 //fixing it or not does not change anything since it is not a degree of freedom, it's just info that will be used by the condition + End NodalData + + Begin Conditions Condition2D2N + 1 1 1 2 + 2 1 3 4 + End Conditions + + Begin SubModelPart BasePart // Note that this would be a sub sub modelpart + Begin SubModelPartData + DENSITY 1700.000000 + BODY_FORCE [3] (1.000000,1.000000,1.000000) + End SubModelPartData + Begin SubModelPartNodes + 1 + 2 + End SubModelPartNodes + Begin SubModelPart inner_part + Begin SubModelPartNodes + 1 + End SubModelPartNodes + Begin SubModelPartConditions + 1 + End SubModelPartConditions + End SubModelPart + End SubModelPart + )input")); + + Kernel kernel; + KratosApplication application(std::string("Kratos")); + application.Register(); + kernel.Initialize(); + + Model current_model; + + ModelPartIO model_part_io(p_input); + + Kratos::shared_ptr p_output_0(new std::stringstream); + Kratos::shared_ptr p_output_1(new std::stringstream); + Kratos::shared_ptr streams[2] = {p_output_0, p_output_1}; + + std::size_t number_of_partitions = 2; + std::size_t number_of_colors = 1; + IO::GraphType domains_colored_graph(number_of_partitions, number_of_colors); + domains_colored_graph(0, 0) = 1; + domains_colored_graph(1, 0) = 0; + IO::PartitionIndicesType nodes_partitions = {0, 0, 1, 1}; + IO::PartitionIndicesType elements_partitions = {0, 1}; + IO::PartitionIndicesType conditions_partitions = {0, 1}; + IO::PartitionIndicesContainerType nodes_all_partitions = { + {0}, {0, 1}, {1}, {0, 1}}; + IO::PartitionIndicesContainerType elements_all_partitions = {{0}, {1}}; + IO::PartitionIndicesContainerType conditions_all_partitions = {{0}, {1}}; + + model_part_io.DivideInputToPartitions(streams, number_of_partitions, + domains_colored_graph, nodes_partitions, elements_partitions, + conditions_partitions, nodes_all_partitions, elements_all_partitions, + conditions_all_partitions); + + ModelPart& model_part_0 = current_model.CreateModelPart("Partition 0"); + model_part_0.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_0.AddNodalSolutionStepVariable(FORCE); + model_part_0.AddNodalSolutionStepVariable(PARTITION_INDEX); + model_part_0.GetCommunicator().SetNumberOfColors(number_of_colors); + + ModelPartIO * model_part_io_0 = new ModelPartIO(p_output_0); + model_part_io_0->ReadModelPart(model_part_0); + + KRATOS_CHECK_EQUAL(model_part_0.NumberOfNodes(), 3); + KRATOS_CHECK_EQUAL(model_part_0.NumberOfElements(), 1); + KRATOS_CHECK_EQUAL(model_part_0.NumberOfConditions(), 1); + KRATOS_CHECK_EQUAL(model_part_0.NumberOfSubModelParts(), 1); + KRATOS_CHECK(model_part_0.HasSubModelPart("BasePart")); + KRATOS_CHECK_EQUAL( + model_part_0.GetSubModelPart("BasePart").NumberOfNodes(), 2); + KRATOS_CHECK_EQUAL( + model_part_0.GetSubModelPart("BasePart").NumberOfElements(), 0); + KRATOS_CHECK_EQUAL( + model_part_0.GetSubModelPart("BasePart").NumberOfConditions(), 1); + + ModelPart& model_part_1 = current_model.CreateModelPart("Partition 1"); + model_part_1.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_1.AddNodalSolutionStepVariable(FORCE); + model_part_1.AddNodalSolutionStepVariable(PARTITION_INDEX); + model_part_1.GetCommunicator().SetNumberOfColors(number_of_colors + 1); + + ModelPartIO * model_part_io_1 = new ModelPartIO(p_output_1); + model_part_io_1->ReadModelPart(model_part_1); + + KRATOS_CHECK_EQUAL(model_part_1.NumberOfNodes(), 3); + KRATOS_CHECK_EQUAL(model_part_1.NumberOfElements(), 1); + KRATOS_CHECK_EQUAL(model_part_1.NumberOfConditions(), 1); + KRATOS_CHECK_EQUAL(model_part_1.NumberOfSubModelParts(), 1); + KRATOS_CHECK(model_part_1.HasSubModelPart("BasePart")); + KRATOS_CHECK_EQUAL( + model_part_1.GetSubModelPart("BasePart").NumberOfNodes(), 1); + KRATOS_CHECK_EQUAL( + model_part_1.GetSubModelPart("BasePart").NumberOfElements(), 0); + KRATOS_CHECK_EQUAL( + model_part_1.GetSubModelPart("BasePart").NumberOfConditions(), 0); + + // Free the modelparts to prevent files still being opened + delete model_part_io_0; + delete model_part_io_1; + + //KRATOS_CHECK_STRING_CONTAIN_SUB_STRING(p_output_1->str(), R"/(Begin SubModelPart BaseNodes + //Begin SubModelPartNodes + //2 + //End SubModelPartNodes + //End Mesh)/"); +} + +KRATOS_TEST_CASE_IN_SUITE(ModelPartIOWriteModelPart, KratosCoreFastSuite) { + + Model current_model; + + // Create a model part to write + ModelPart& main_model_part = current_model.CreateModelPart("MainModelPart"); + main_model_part.SetBufferSize(1); + Properties::Pointer p_properties_1(new Properties(1)); + p_properties_1->SetValue(DENSITY, 1000.0); + p_properties_1->SetValue(VISCOSITY, 1E-05); + main_model_part.AddProperties(p_properties_1); + + main_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + main_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + main_model_part.CreateNewNode(3, 1.0, 1.0, 0.0); + main_model_part.CreateNewNode(4, 0.0, 1.0, 0.0); + + std::vector elem_nodes_1 = {1,2,4}; + std::vector elem_nodes_2 = {3,4,2}; + main_model_part.CreateNewElement("Element2D3N", 1, elem_nodes_1, p_properties_1); + main_model_part.CreateNewElement("Element2D3N", 2, elem_nodes_2, p_properties_1); + + //elemental data + Matrix stress = ScalarMatrix(2,2, 1.00); + main_model_part.GetMesh().GetElement(1).SetValue(CAUCHY_STRESS_TENSOR,stress); + bool is_restarted = true; + main_model_part.GetMesh().GetElement(1).SetValue(IS_RESTARTED,is_restarted); + int domain_size =2; + main_model_part.GetMesh().GetElement(1).SetValue(DOMAIN_SIZE,domain_size); + double temperature = 34.7; + main_model_part.GetMesh().GetElement(1).SetValue(TEMPERATURE, temperature); + double displacement_x = 1.2; + main_model_part.GetMesh().GetElement(1).SetValue(DISPLACEMENT_X, displacement_x); + + + std::vector cond_nodes_1 = {1,2}; + std::vector cond_nodes_2 = {3,4}; + std::vector cond_nodes_3 = {4}; + main_model_part.CreateNewCondition("Condition2D2N", 1, cond_nodes_1, p_properties_1); + main_model_part.CreateNewCondition("Condition2D2N", 2, cond_nodes_2, p_properties_1); + main_model_part.CreateNewCondition("PointCondition2D1N", 3, cond_nodes_3, p_properties_1); + + //conditional data + main_model_part.GetMesh().GetCondition(1).SetValue(CAUCHY_STRESS_TENSOR,stress); + main_model_part.GetMesh().GetCondition(1).SetValue(IS_RESTARTED,is_restarted); + main_model_part.GetMesh().GetCondition(1).SetValue(DOMAIN_SIZE,domain_size); + main_model_part.GetMesh().GetCondition(1).SetValue(TEMPERATURE, temperature); + main_model_part.GetMesh().GetCondition(1).SetValue(DISPLACEMENT_X, displacement_x); + + ModelPart* p_sub_model_part = &main_model_part.CreateSubModelPart("SubModelPart"); + std::vector sub_model_part_nodes = {1,2,4}; + std::vector sub_model_part_elems = {1}; + std::vector sub_model_part_conds = {1,3}; + p_sub_model_part->AddNodes(sub_model_part_nodes); + p_sub_model_part->AddElements(sub_model_part_elems); + p_sub_model_part->AddConditions(sub_model_part_conds); + + // Create the output .mdpa file + std::string output_file_name = "main_model_part_output"; + std::fstream output_file; + output_file.open(output_file_name + ".mdpa", std::fstream::out); + output_file.close(); + + // Fill the output .mdpa file + ModelPartIO * model_part_io_write = new ModelPartIO(output_file_name, IO::WRITE); + model_part_io_write->WriteModelPart(main_model_part); + + // Read and check the written .mdpa file + ModelPartIO * model_part_io_output = new ModelPartIO(output_file_name); + ModelPart& main_model_part_output = current_model.CreateModelPart("MainModelPartOutput"); + model_part_io_output->ReadModelPart(main_model_part_output); + + // Assert results + KRATOS_CHECK_EQUAL(main_model_part_output.NumberOfProperties(), 1); + KRATOS_CHECK_EQUAL(main_model_part_output.NumberOfSubModelParts() ,1); + KRATOS_CHECK_EQUAL(main_model_part_output.NumberOfNodes(), 4); + KRATOS_CHECK_EQUAL(main_model_part_output.NumberOfElements(), 2); + KRATOS_CHECK_EQUAL(main_model_part_output.NumberOfConditions(), 3); + KRATOS_CHECK_EQUAL(main_model_part_output.GetSubModelPart("SubModelPart").NumberOfNodes(), 3); + KRATOS_CHECK_EQUAL(main_model_part_output.GetSubModelPart("SubModelPart").NumberOfElements(), 1); + KRATOS_CHECK_EQUAL(main_model_part_output.GetSubModelPart("SubModelPart").NumberOfConditions(), 2); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetElement(1).GetValue(CAUCHY_STRESS_TENSOR)(1,1),1); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetElement(1).GetValue(IS_RESTARTED),is_restarted); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetElement(1).GetValue(DOMAIN_SIZE),domain_size); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetElement(1).GetValue(TEMPERATURE), temperature); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetElement(1).GetValue(DISPLACEMENT_X), displacement_x); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetCondition(1).GetValue(CAUCHY_STRESS_TENSOR)(1,1),1); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetCondition(1).GetValue(IS_RESTARTED),is_restarted); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetCondition(1).GetValue(DOMAIN_SIZE),domain_size); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetCondition(1).GetValue(TEMPERATURE), temperature); + KRATOS_CHECK_EQUAL(main_model_part_output.GetMesh().GetCondition(1).GetValue(DISPLACEMENT_X), displacement_x); + + // Free the modelparts to prevent files still being opened + delete model_part_io_write; + delete model_part_io_output; + + // Remove the generated files + std::string aux_string_mdpa = output_file_name + ".mdpa"; + std::string aux_string_time = output_file_name + ".time"; + const char *mdpa_to_remove = aux_string_mdpa.c_str(); + const char *time_to_remove = aux_string_time.c_str(); + std::string error_msg = "Error deleting test output file: " + output_file_name; + if (remove(mdpa_to_remove) != 0) { + KRATOS_ERROR << error_msg + ".mdpa"; + } + if (remove(time_to_remove) != 0) { + KRATOS_ERROR << error_msg + ".time"; + } +} + + +KRATOS_TEST_CASE_IN_SUITE(ModelPartIOVariableNotInSolutionStepData, KratosCoreFastSuite) { + Kratos::shared_ptr p_input(new std::stringstream( + R"input( + Begin Properties 0 + End Properties + + Begin Nodes + 1 0.0 0.0 0.0 + 2 1.0 0.0 0.0 + 3 1.0 1.0 0.0 + 4 0.0 1.0 0.0 + End Nodes + + Begin Elements Element2D3N + 1 0 1 2 4 + 2 0 3 4 2 + End Elements + + Begin NodalData DISPLACEMENT_X + 1 1 100.0 + End NodalData + + Begin NodalData DISPLACEMENT_Y + 1 1 100.0 + End NodalData + + Begin NodalData PRESSURE + 2 0 50.0 + End NodalData + + Begin NodalData TEMPERATURE + 4 0 33.0 + End NodalData + + Begin NodalData FORCE_Y + 3 0 5.0 + End NodalData + )input")); + + Kernel kernel; + KratosApplication application(std::string("Kratos")); + application.Register(); + kernel.Initialize(); + + Model current_model; + + // 1. Reading without IGNORE flag -> Error + ModelPartIO default_model_part_io(p_input); + + ModelPart& model_part_0 = current_model.CreateModelPart("ErrorForce"); + model_part_0.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_0.AddNodalSolutionStepVariable(PRESSURE); + model_part_0.AddNodalSolutionStepVariable(TEMPERATURE); + + KRATOS_CHECK_EXCEPTION_IS_THROWN( + default_model_part_io.ReadModelPart(model_part_0), + "The nodal solution step container does not have this variable: FORCE_Y"); + + ModelPart& model_part_1 = current_model.CreateModelPart("ErrorTemperature"); + model_part_1.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_1.AddNodalSolutionStepVariable(FORCE); + model_part_1.AddNodalSolutionStepVariable(PRESSURE); + + KRATOS_CHECK_EXCEPTION_IS_THROWN( + default_model_part_io.ReadModelPart(model_part_1), + "The nodal solution step container does not have this variable: TEMPERATURE"); + + // 2. Reading with IGNORE flag -> Not set + ModelPartIO ignore_model_part_io(p_input,ModelPartIO::READ|ModelPartIO::IGNORE_VARIABLES_ERROR); + + ModelPart& model_part_2 = current_model.CreateModelPart("IgnoreForce"); + model_part_0.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_0.AddNodalSolutionStepVariable(PRESSURE); + model_part_0.AddNodalSolutionStepVariable(TEMPERATURE); + + ignore_model_part_io.ReadModelPart(model_part_2); + KRATOS_CHECK_EQUAL(model_part_2.NumberOfNodes(), 4); + KRATOS_CHECK_EQUAL(model_part_2.NodesBegin()->Has(FORCE), false); + + ModelPart& model_part_3 = current_model.CreateModelPart("IgnoreTemperature"); + model_part_1.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part_1.AddNodalSolutionStepVariable(FORCE); + model_part_1.AddNodalSolutionStepVariable(PRESSURE); + + ignore_model_part_io.ReadModelPart(model_part_3); + KRATOS_CHECK_EQUAL(model_part_3.NumberOfNodes(), 4); + KRATOS_CHECK_EQUAL(model_part_3.NodesBegin()->Has(TEMPERATURE), false); +} + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_nodal_data.cpp b/kratos/tests/cpp_tests/sources/test_nodal_data.cpp new file mode 100644 index 000000000000..33ee457bc5b7 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_nodal_data.cpp @@ -0,0 +1,94 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/prime_numbers.h" +#include "includes/model_part.h" + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(NodalSolutionStepData, KratosCoreFastSuite) + { + Model current_model; + + const int repeat = 10; + ModelPart& model_part = current_model.CreateModelPart("test"); + model_part.AddNodalSolutionStepVariable(DISTANCE); + model_part.AddNodalSolutionStepVariable(VELOCITY); + + const std::size_t size = 10; + for (std::size_t i = 0; i < size; i++) + model_part.CreateNewNode(i, i, 0, 0); + + for (int i = 0; i < repeat; i++) { + for (auto i_node = model_part.NodesBegin(); i_node != model_part.NodesEnd(); i_node++) { + i_node->FastGetSolutionStepValue(DISTANCE) = static_cast(i); + i_node->FastGetSolutionStepValue(VELOCITY_X) = static_cast(i); + } + double distance_sum = 0; + double velocity_x_sum = 0; + for (auto i_node = model_part.NodesBegin(); i_node != model_part.NodesEnd(); i_node++) { + distance_sum += i_node->FastGetSolutionStepValue(DISTANCE); + velocity_x_sum += i_node->FastGetSolutionStepValue(VELOCITY_X) * 2; + } + KRATOS_CHECK_DOUBLE_EQUAL(distance_sum, i * size); + KRATOS_CHECK_DOUBLE_EQUAL(velocity_x_sum, i * size * 2); + } + } + + KRATOS_TEST_CASE_IN_SUITE(FluidNodalSolutionStepData, KratosCoreFastSuite) + { + Model current_model; + + const int repeat = 10; + ModelPart& model_part = current_model.CreateModelPart("test"); + model_part.AddNodalSolutionStepVariable(PRESSURE); + model_part.AddNodalSolutionStepVariable(VELOCITY); + model_part.AddNodalSolutionStepVariable(FRACT_VEL); + model_part.AddNodalSolutionStepVariable(MESH_VELOCITY); + model_part.AddNodalSolutionStepVariable(NODAL_AREA); + model_part.AddNodalSolutionStepVariable(BODY_FORCE); + model_part.AddNodalSolutionStepVariable(DENSITY); + model_part.AddNodalSolutionStepVariable(VISCOSITY); + model_part.AddNodalSolutionStepVariable(FLAG_VARIABLE); + model_part.AddNodalSolutionStepVariable(DISPLACEMENT); + model_part.AddNodalSolutionStepVariable(REACTION); + model_part.AddNodalSolutionStepVariable(NORMAL); + std::size_t size = 10; + for (std::size_t i = 0; i < size; i++) + model_part.CreateNewNode(i, i, 0, 0); + + for (int i = 0; i < repeat; i++) { + for (auto i_node = model_part.NodesBegin(); i_node != model_part.NodesEnd(); i_node++) { + i_node->FastGetSolutionStepValue(PRESSURE) = static_cast(i); + i_node->FastGetSolutionStepValue(VELOCITY_X) = static_cast(2*i); + } + double pressure_sum = 0; + double velocity_x_sum = 0; + double velocity_y_sum = 0; + for (auto i_node = model_part.NodesBegin(); i_node != model_part.NodesEnd(); i_node++) { + pressure_sum += i_node->FastGetSolutionStepValue(PRESSURE); + velocity_x_sum += i_node->FastGetSolutionStepValue(VELOCITY_X); + velocity_y_sum += i_node->FastGetSolutionStepValue(VELOCITY_Y); + } + KRATOS_CHECK_DOUBLE_EQUAL(pressure_sum, i * size); + KRATOS_CHECK_DOUBLE_EQUAL(velocity_x_sum, 2*i * size); + KRATOS_CHECK_DOUBLE_EQUAL(velocity_y_sum, 0.00); + } + } + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_node.cpp b/kratos/tests/cpp_tests/sources/test_node.cpp new file mode 100644 index 000000000000..fde493ab3d18 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_node.cpp @@ -0,0 +1,79 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// Vicente Mataix Ferrandiz +// +// + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "includes/model_part.h" + +namespace Kratos { + namespace Testing { + + typedef Node<3> NodeType; + + /** + * Here the assigment operator is test + */ + + KRATOS_TEST_CASE_IN_SUITE(NodeAssignOperator, KratosCoreFastSuite) + { + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test"); + model_part.AddNodalSolutionStepVariable(DISTANCE); + model_part.AddNodalSolutionStepVariable(VELOCITY); + + auto p_node = model_part.CreateNewNode(1, 1., 0, 0); + + p_node->FastGetSolutionStepValue(DISTANCE) = 12.1; + p_node->FastGetSolutionStepValue(VELOCITY_X) = 32.4; + p_node->Set(ACTIVE, true); + + NodeType copy_of_node(2,1,0,0); + copy_of_node = *p_node; + + KRATOS_CHECK_EQUAL(copy_of_node.Id(), 1); + KRATOS_CHECK_DOUBLE_EQUAL(copy_of_node.FastGetSolutionStepValue(DISTANCE), 12.1); + KRATOS_CHECK_DOUBLE_EQUAL(copy_of_node.FastGetSolutionStepValue(VELOCITY_X), 32.4); + KRATOS_CHECK_DOUBLE_EQUAL(copy_of_node.FastGetSolutionStepValue(VELOCITY_Y), 0.00); + KRATOS_CHECK_DOUBLE_EQUAL(copy_of_node.FastGetSolutionStepValue(VELOCITY_Z), 0.00); + KRATOS_CHECK(copy_of_node.Is(ACTIVE)); + } + + /** + * Here the clone operator is test + */ + KRATOS_TEST_CASE_IN_SUITE(NodeCloneOperator, KratosCoreFastSuite) + { + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test"); + model_part.AddNodalSolutionStepVariable(DISTANCE); + model_part.AddNodalSolutionStepVariable(VELOCITY); + + auto p_node = model_part.CreateNewNode(1, 1., 0, 0); + + p_node->FastGetSolutionStepValue(DISTANCE) = 12.1; + p_node->FastGetSolutionStepValue(VELOCITY_X) = 32.4; + p_node->Set(ACTIVE, true); + + NodeType::Pointer p_clone_of_node = p_node->Clone(); + + KRATOS_CHECK_EQUAL(p_clone_of_node->Id(), 1); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_node->FastGetSolutionStepValue(DISTANCE), 12.1); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_node->FastGetSolutionStepValue(VELOCITY_X), 32.4); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_node->FastGetSolutionStepValue(VELOCITY_Y), 0.00); + KRATOS_CHECK_DOUBLE_EQUAL(p_clone_of_node->FastGetSolutionStepValue(VELOCITY_Z), 0.00); + KRATOS_CHECK(p_clone_of_node->Is(ACTIVE)); + } +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_parameters.cpp b/kratos/tests/cpp_tests/sources/test_parameters.cpp new file mode 100644 index 000000000000..d9ae5bb0ee84 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_parameters.cpp @@ -0,0 +1,100 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes + + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "includes/kratos_parameters.h" + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(ParametersIterator, KratosCoreFastSuite) + { + Parameters parameters(R"input( + { + "int_value" : 10, "double_value": 2.0, "bool_value" : true, "string_value" : "hello", + "level1": + { + "list_value":[ 3, "hi", false], + "tmp" : 5.0 + } + } + )input"); + + auto i_parameter = parameters.begin(); + KRATOS_CHECK_EQUAL(i_parameter.name(), std::string("int_value")); + KRATOS_CHECK(i_parameter->IsInt()); + KRATOS_CHECK_EQUAL(i_parameter->GetInt(), 10); + KRATOS_CHECK((++i_parameter)->IsDouble()); + KRATOS_CHECK_EQUAL((i_parameter++)->GetDouble(), 2.0); + KRATOS_CHECK((*i_parameter).IsBool()); + KRATOS_CHECK_EQUAL((*i_parameter).GetBool(), true); + + unsigned int size = 0; + + for(auto i = parameters.begin() ; i != parameters.end() ; i++) + size++; + + KRATOS_CHECK_EQUAL(size, 5); + + + } + + KRATOS_TEST_CASE_IN_SUITE(Parameters_Constructor1, KratosCoreFastSuite) + { + Parameters p; + KRATOS_CHECK_EQUAL(p.WriteJsonString(), "{}"); + } + + KRATOS_TEST_CASE_IN_SUITE(Parameters_Swap1, KratosCoreFastSuite) + { + Parameters p1{R"({"foo": 1.0})"}; + Parameters p2{R"({"bar": false})"}; + p1.swap(p2); + KRATOS_CHECK(p1.Has("bar")); + KRATOS_CHECK(p1["bar"].GetBool() == false); + KRATOS_CHECK(p2.Has("foo")); + KRATOS_CHECK(p2["foo"].GetDouble() == 1.0); + } + + KRATOS_TEST_CASE_IN_SUITE(Parameters_Reset1, KratosCoreFastSuite) + { + Parameters p{R"({"foo": {"bar": 1.0}})"}; + p.Reset(); + KRATOS_CHECK_EQUAL(p.WriteJsonString(), "{}"); + } + + KRATOS_TEST_CASE_IN_SUITE(Parameters_MoveConstructor1, KratosCoreFastSuite) + { + Parameters p1{R"({"foo": {"bar": 1.0}})"}; + Parameters p2{std::move(p1)}; + KRATOS_CHECK_EQUAL(p1.WriteJsonString(), "{}"); + KRATOS_CHECK_EQUAL(p2.WriteJsonString(), R"({"foo":{"bar":1.0}})"); + } + + KRATOS_TEST_CASE_IN_SUITE(Parameters_MoveAssignment1, KratosCoreFastSuite) + { + Parameters p1{R"({"foo": {"bar": 1.0}})"}; + Parameters p2{}; + p2 = std::move(p1); + KRATOS_CHECK_EQUAL(p1.WriteJsonString(), "{}"); + KRATOS_CHECK_EQUAL(p2.WriteJsonString(), R"({"foo":{"bar":1.0}})"); + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_properties.cpp b/kratos/tests/cpp_tests/sources/test_properties.cpp new file mode 100644 index 000000000000..de7868d2b02f --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_properties.cpp @@ -0,0 +1,85 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// Project includes +#include "testing/testing.h" +#include "includes/properties.h" +#include "includes/checks.h" +#include "includes/variables.h" + +namespace Kratos { + namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(PropertiesHasTable, KratosCoreFastSuite) + { + Properties properties(0); + KRATOS_CHECK_IS_FALSE(properties.HasTable(TEMPERATURE, VISCOSITY)); + + Table table; + properties.SetTable(TEMPERATURE, VISCOSITY, table); + + KRATOS_CHECK(properties.HasTable(TEMPERATURE, VISCOSITY)); + KRATOS_CHECK_IS_FALSE(properties.HasTable(TEMPERATURE, DISPLACEMENT_X)); + KRATOS_CHECK_IS_FALSE(properties.HasTable(VISCOSITY, TEMPERATURE)); + } + + KRATOS_TEST_CASE_IN_SUITE(PropertiesHasVariables, KratosCoreFastSuite) + { + Properties property(0); + KRATOS_CHECK_IS_FALSE(property.HasVariables()); + + property.SetValue(TEMPERATURE, 1.0); + + KRATOS_CHECK(property.HasVariables()); + } + + KRATOS_TEST_CASE_IN_SUITE(PropertiesHasTables, KratosCoreFastSuite) + { + Properties property(0); + KRATOS_CHECK_IS_FALSE(property.HasTables()); + + Table table; + property.SetTable(TEMPERATURE, VISCOSITY, table); + + KRATOS_CHECK(property.HasTables()); + } + + KRATOS_TEST_CASE_IN_SUITE(PropertiesIsEmpty, KratosCoreFastSuite) + { + Properties property(0); + KRATOS_CHECK(property.IsEmpty()); + + Table table; + property.SetTable(TEMPERATURE, VISCOSITY, table); + + KRATOS_CHECK_IS_FALSE(property.IsEmpty()); + + Properties property1(1); + KRATOS_CHECK(property1.IsEmpty()); + + property1.SetValue(TEMPERATURE, 1.0); + + KRATOS_CHECK_IS_FALSE(property1.IsEmpty()); + + Properties property2(2); + KRATOS_CHECK(property2.IsEmpty()); + + property2.SetTable(TEMPERATURE, VISCOSITY, table); + + property2.SetValue(TEMPERATURE, 1.0); + + KRATOS_CHECK_IS_FALSE(property2.IsEmpty()); + } + + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_serializer.cpp b/kratos/tests/cpp_tests/sources/test_serializer.cpp new file mode 100644 index 000000000000..1c5acdf03052 --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_serializer.cpp @@ -0,0 +1,307 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// +// + +// Project includes +#include "testing/testing.h" +#include "includes/serializer.h" +#include "includes/file_serializer.h" +#include "includes/stream_serializer.h" +#include "geometries/point.h" + +namespace Kratos { + namespace Testing { + + /*********************************************************************/ + /* Helper Functions */ + /*********************************************************************/ + template + void SaveAndLoadObjects(const TObjectType& rObjectToBeSaved, TObjectType& rObjectToBeLoaded) + { + StreamSerializer serializer; + + const std::string tag_string("TestString"); + + serializer.save(tag_string, rObjectToBeSaved); + serializer.load(tag_string, rObjectToBeLoaded); + } + + template + void TestObjectSerialization(const TObjectType& rObjectToBeSaved, TObjectType& rObjectToBeLoaded) + { + SaveAndLoadObjects(rObjectToBeSaved, rObjectToBeLoaded); + KRATOS_CHECK_EQUAL(rObjectToBeLoaded, rObjectToBeSaved); + } + + template + void TestObjectSerializationComponentwise1D(const TObjectType& rObjectToBeSaved, TObjectType& rObjectToBeLoaded) + { + SaveAndLoadObjects(rObjectToBeSaved, rObjectToBeLoaded); + + KRATOS_CHECK_EQUAL(rObjectToBeLoaded.size(), rObjectToBeSaved.size()); + + for (std::size_t i=0; i< rObjectToBeSaved.size(); ++i) + KRATOS_CHECK_EQUAL(rObjectToBeLoaded[i], rObjectToBeSaved[i]); + } + + template + void TestObjectSerializationComponentwise2D(const TObjectType& rObjectToBeSaved, TObjectType& rObjectToBeLoaded) + { + SaveAndLoadObjects(rObjectToBeSaved, rObjectToBeLoaded); + + KRATOS_CHECK_EQUAL(rObjectToBeLoaded.size1(), rObjectToBeSaved.size1()); + KRATOS_CHECK_EQUAL(rObjectToBeLoaded.size2(), rObjectToBeSaved.size2()); + + for (std::size_t i=0; i + void FillVectorWithValues(TObjectType& rObject) + { + for (std::size_t i = 0; i < rObject.size(); ++i) + rObject[i] = i*i*0.2 + 5.333; + } + + template + void FillMatrixWithValues(TObjectType& rObject) + { + for (std::size_t i=0; i(-0.25, 3.5, 8.55); + Kratos::shared_ptr> p_array = p_point; + + Point::Pointer p_loaded_point; + Kratos::shared_ptr> p_loaded_array; + + serializer.save(tag_string, p_array); + serializer.save(tag_string_2, p_point); + + serializer.load(tag_string, p_loaded_array); + serializer.load(tag_string_2, p_loaded_point); + + KRATOS_CHECK_EQUAL(*p_point, *p_loaded_point); + for (std::size_t i=0; i<(*p_array).size(); ++i) + KRATOS_CHECK_EQUAL((*p_loaded_array)[i], (*p_array)[i]); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerStdArray, KratosCoreFastSuite) + { + using Array5Dbl = std::array; + using Array7Int = std::array; + + Array5Dbl object_to_be_saved_1; + Array5Dbl object_to_be_loaded_1; + Array7Int object_to_be_saved_2; + Array7Int object_to_be_loaded_2; + + FillVectorWithValues(object_to_be_saved_1); + FillVectorWithValues(object_to_be_saved_2); + + TestObjectSerializationComponentwise1D(object_to_be_saved_1, object_to_be_loaded_1); + TestObjectSerializationComponentwise1D(object_to_be_saved_2, object_to_be_loaded_2); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerStdVector, KratosCoreFastSuite) + { + std::vector object_to_be_saved(5); + std::vector object_to_be_loaded(3); // initialized smaller to check if resizing works + + FillVectorWithValues(object_to_be_saved); + + TestObjectSerializationComponentwise1D(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerUblasVector, KratosCoreFastSuite) + { + Vector object_to_be_saved(5); + Vector object_to_be_loaded(3); // initialized smaller to check if resizing works + + FillVectorWithValues(object_to_be_saved); + + TestObjectSerializationComponentwise1D(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerMap, KratosCoreFastSuite) + { + std::map object_to_be_saved { + { "42", -30.556 }, + { "3", 10.258 } + }; + std::map object_to_be_loaded; + + TestObjectSerialization(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerUnorderedMap, KratosCoreFastSuite) + { + std::unordered_map object_to_be_saved { + { "42", -30.556 }, + { "3", 10.258 } + }; + std::unordered_map object_to_be_loaded; + + TestObjectSerialization(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerArray1D, KratosCoreFastSuite) + { + constexpr std::size_t size_object = 5; + array_1d object_to_be_saved; + array_1d object_to_be_loaded; + + FillVectorWithValues(object_to_be_saved); + + TestObjectSerializationComponentwise1D(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerPair, KratosCoreFastSuite) + { + std::pair object_to_be_saved(42, 0.123); + std::pair object_to_be_loaded(42, 0.123); + + TestObjectSerialization(object_to_be_saved, object_to_be_loaded); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerBoundedVector, KratosCoreFastSuite) + { + using Vector5Double = BoundedVector; + using Vector6Int = BoundedVector; + + Vector5Double object_to_be_saved_1; + Vector5Double object_to_be_loaded_1; + Vector6Int object_to_be_saved_2; + Vector6Int object_to_be_loaded_2; + + FillVectorWithValues(object_to_be_saved_1); + FillVectorWithValues(object_to_be_saved_2); + + TestObjectSerializationComponentwise1D(object_to_be_saved_1, object_to_be_loaded_1); + TestObjectSerializationComponentwise1D(object_to_be_saved_2, object_to_be_loaded_2); + } + + KRATOS_TEST_CASE_IN_SUITE(SerializerBoundedMatrix, KratosCoreFastSuite) + { + using Matrix53Double = BoundedMatrix; + using Matrix26Int = BoundedMatrix; + + Matrix53Double object_to_be_saved_1; + Matrix53Double object_to_be_loaded_1; + Matrix26Int object_to_be_saved_2; + Matrix26Int object_to_be_loaded_2; + + FillMatrixWithValues(object_to_be_saved_1); + FillMatrixWithValues(object_to_be_saved_2); + + TestObjectSerializationComponentwise2D(object_to_be_saved_1, object_to_be_loaded_1); + TestObjectSerializationComponentwise2D(object_to_be_saved_2, object_to_be_loaded_2); + } + + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/sources/test_shape_function_derivatives.cpp b/kratos/tests/cpp_tests/sources/test_shape_function_derivatives.cpp new file mode 100644 index 000000000000..9c81fbd9c9ae --- /dev/null +++ b/kratos/tests/cpp_tests/sources/test_shape_function_derivatives.cpp @@ -0,0 +1,135 @@ +#include "tests/cpp_tests/geometries/test_shape_function_derivatives.h" + +#include +#include "containers/array_1d.h" +#include "testing/testing.h" +#include "tests/cpp_tests/geometries/test_geometry.h" + +namespace Kratos { +namespace Testing { + +void TestShapeFunctionsLocalGradients(Geometry> const& rGeom) +{ + KRATOS_TRY; + auto local_gradients = rGeom.ShapeFunctionsLocalGradients(); + auto integration_points = rGeom.IntegrationPoints(); + for (unsigned g = 0; g < rGeom.IntegrationPointsNumber(); ++g) + TestShapeFunctionsLocalGradient(rGeom, integration_points[g], local_gradients[g]); + KRATOS_CATCH(""); +} + +void TestShapeFunctionsLocalGradients(Geometry> const& rGeom, + GeometryData::IntegrationMethod ThisMethod) +{ + KRATOS_TRY; + auto local_gradients = rGeom.ShapeFunctionsLocalGradients(ThisMethod); + auto integration_points = rGeom.IntegrationPoints(ThisMethod); + for (unsigned g = 0; g < rGeom.IntegrationPointsNumber(ThisMethod); ++g) + TestShapeFunctionsLocalGradient(rGeom, integration_points[g], local_gradients[g]); + KRATOS_CATCH(""); +} + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex(Geometry> const& rGeom) +{ + KRATOS_TRY; + auto integration_points = rGeom.IntegrationPoints(); + for (std::size_t i = 0; i < integration_points.size(); ++i) + TestShapeFunctionsLocalGradient(rGeom, integration_points[i], + rGeom.ShapeFunctionLocalGradient(i)); + KRATOS_CATCH(""); +} + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex( + Geometry> const& rGeom, GeometryData::IntegrationMethod ThisMethod) +{ + KRATOS_TRY; + auto integration_points = rGeom.IntegrationPoints(ThisMethod); + for (std::size_t i = 0; i < integration_points.size(); ++i) + TestShapeFunctionsLocalGradient(rGeom, integration_points[i], + rGeom.ShapeFunctionLocalGradient(i, ThisMethod)); + KRATOS_CATCH(""); +} + + +void TestShapeFunctionsLocalGradients_IntegrationPointIndex_ShapeFunctionIndex( + Geometry> const& rGeom, GeometryData::IntegrationMethod ThisMethod) +{ + KRATOS_TRY; + auto integration_points = rGeom.IntegrationPoints(ThisMethod); + for (std::size_t i = 0; i < integration_points.size(); ++i) + for (std::size_t j = 0; j < rGeom.PointsNumber(); ++j) + TestShapeFunctionsLocalGradient( + rGeom, integration_points[i], + rGeom.ShapeFunctionLocalGradient(i, j, ThisMethod)); + KRATOS_CATCH(""); +} + +void TestShapeFunctionsLocalGradients_Point(Geometry> const& rGeom) +{ + KRATOS_TRY; + Matrix local_gradient; + auto integration_points = rGeom.IntegrationPoints(); + for (auto point : integration_points) + TestShapeFunctionsLocalGradient( + rGeom, point, rGeom.ShapeFunctionsLocalGradients(local_gradient, point)); + KRATOS_CATCH(""); +} + +void TestAllShapeFunctionsLocalGradients(Geometry> const& rGeom) +{ + KRATOS_TRY; + TestShapeFunctionsLocalGradients(rGeom); + TestShapeFunctionsLocalGradients(rGeom, GeometryData::GI_GAUSS_1); + TestShapeFunctionsLocalGradients(rGeom, GeometryData::GI_GAUSS_2); + TestShapeFunctionsLocalGradients_IntegrationPointIndex(rGeom); + TestShapeFunctionsLocalGradients_IntegrationPointIndex( + rGeom, rGeom.GetDefaultIntegrationMethod()); + TestShapeFunctionsLocalGradients_IntegrationPointIndex_ShapeFunctionIndex( + rGeom, rGeom.GetDefaultIntegrationMethod()); + TestShapeFunctionsLocalGradients_Point(rGeom); + KRATOS_CATCH(""); +} + +namespace +{ +double FiniteDifference4(std::function f, double delta=1e-3); +} + +void TestShapeFunctionsLocalGradient(Geometry> const& rGeom, + Geometry>::IntegrationPointType Point, + Matrix const& rLocalGradient) +{ + KRATOS_TRY; + KRATOS_CHECK(rLocalGradient.size1() == rGeom.PointsNumber()); + KRATOS_CHECK(rLocalGradient.size2() == rGeom.LocalSpaceDimension()); + for (unsigned i = 0; i < rGeom.PointsNumber(); ++i) + for (unsigned j = 0; j < rGeom.LocalSpaceDimension(); ++j) + { + auto f = [&](double delta) { + array_1d point = Point; + point[j] += delta; + return rGeom.ShapeFunctionValue(i, point); + }; + KRATOS_CHECK_NEAR(FiniteDifference4(f), rLocalGradient(i, j), TOLERANCE); + } + KRATOS_CATCH(""); +} + +namespace { +/** +* @brief Compute finite difference for polynomial of degree k = 4. +* @details The finite difference approximation should be exact for polynomials +* up to degree k = 4. See e.g., Mech. Struct. & Mach. 21(1), 1-66 (1993). +* @param f Scalar function of perturbation to be differentiated. +* @param delta Perturbation size. +* @return Finite difference approximation. +*/ +// +double FiniteDifference4(std::function f, double delta) +{ + return (-f(2.0 * delta) + 8.0 * f(delta) - 8.0 * f(-delta) + f(-2.0 * delta)) / + (12.0 * delta); +} +} +} +} diff --git a/kratos/tests/cpp_tests/spatial_containers/test_bins_dynamic.cpp b/kratos/tests/cpp_tests/spatial_containers/test_bins_dynamic.cpp new file mode 100644 index 000000000000..595318026282 --- /dev/null +++ b/kratos/tests/cpp_tests/spatial_containers/test_bins_dynamic.cpp @@ -0,0 +1,336 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos Roig +// +// + +// System includes + + +// External includes + + +// Project includes +#include "includes/node.h" +#include "testing/testing.h" +#include "spatial_containers/bins_dynamic.h" + + +namespace Kratos { +namespace Testing { + +typedef Node<3> PointType; +typedef Node<3>::Pointer PointTypePointer; +typedef std::vector PointVector; +typedef std::vector::iterator PointIterator; +typedef std::vector DistanceVector; +typedef std::vector::iterator DistanceIterator; + +typedef BinsDynamic<3, PointType, PointVector, PointTypePointer, PointIterator, DistanceIterator> DynamicBins; + +typedef DynamicBins::CoordinateType CoordinateType; +typedef DynamicBins::PointerType PointerType; +typedef DynamicBins::SearchStructureType SearchStructureType; + +/** + * @brief Test that the bins is constructed correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsDefaultConstructorBoundigBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + DynamicBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], 0.0); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], 9.0); +} + +/** + * @brief Test that the number of cells is calculated correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsDefaultConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + DynamicBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsDefaultConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + DynamicBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], 3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], 3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], 3.0); +} + +/** + * @brief Test that the bins is constructed correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsBBConstructorBoundingBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + DynamicBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], testMinPoint[0]); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], testMinPoint[1]); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], testMinPoint[2]); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], testMaxPoint[0]); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], testMaxPoint[1]); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], testMaxPoint[2]); +} + +/** + * @brief Test that the number of cells is calculated correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsBBConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + DynamicBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsBBConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + DynamicBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], 20.0/3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], 20.0/3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], 20.0/3.0); +} + +/** + * @brief Test that the bins is constructed correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsCellSizeConstructorBoundingBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + DynamicBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], 0.0); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], 9.0); +} + +/** + * @brief Test that the number of cells is calculated correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsCellSizeConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + DynamicBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsCellSizeConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + DynamicBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], testCellSize); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], testCellSize); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], testCellSize); +} + +/** + * @brief Searches the nearest point + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsExistPoint, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + DynamicBins testBins(points.begin(), points.end()); + + PointerType nearestPoint = testBins.ExistPoint(PointerType(new PointType(0, 4.1, 4.1, 4.1))); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); +} + +/** + * @brief Searches the nearest point (excluding the input) + * + */ +// Missing function / does not exists yet. + +/** + * @brief Searches the nearest point with (including the input) + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsNearestPoint, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + points.push_back(pointToSearch); + + DynamicBins testBins(points.begin(), points.end()); + + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 10); +} + +/** + * @brief Searches the nearest point (including the input) with distance + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsNearestPointWithDistance, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + + DynamicBins testBins(points.begin(), points.end()); + + double squaredDistance = 0.0; + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch, squaredDistance); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); + KRATOS_CHECK_EQUAL(squaredDistance, 0.1875); +} + +/** + * @brief Searches the nearest point (including the input) with distance (threadsafe) + * + */ +KRATOS_TEST_CASE_IN_SUITE(DynamicBinsNearestPointWithDistanceThreadsafe, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + + DynamicBins testBins(points.begin(), points.end()); + SearchStructureType searchBox; + + double squaredDistance = 0.0; + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch, squaredDistance, searchBox); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); + KRATOS_CHECK_EQUAL(squaredDistance, 0.1875); +} + + +} // namespace Testesing +} // namespace Kratos \ No newline at end of file diff --git a/kratos/tests/cpp_tests/spatial_containers/test_bins_static.cpp b/kratos/tests/cpp_tests/spatial_containers/test_bins_static.cpp new file mode 100644 index 000000000000..b2ca2190ee2d --- /dev/null +++ b/kratos/tests/cpp_tests/spatial_containers/test_bins_static.cpp @@ -0,0 +1,352 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Carlos Roig +// +// + +// System includes + + +// External includes + + +// Project includes +#include "includes/node.h" +#include "testing/testing.h" +#include "spatial_containers/bins_static.h" + + +namespace Kratos { +namespace Testing { + +typedef Node<3> PointType; +typedef Node<3>::Pointer PointTypePointer; +typedef std::vector PointVector; +typedef std::vector::iterator PointIterator; +typedef std::vector DistanceVector; +typedef std::vector::iterator DistanceIterator; + +typedef Bins<3, PointType, PointVector, PointTypePointer, PointIterator, DistanceIterator> StaticBins; + +typedef StaticBins::CoordinateType CoordinateType; +typedef StaticBins::PointerType PointerType; +typedef StaticBins::SearchStructureType SearchStructureType; + +/** + * @brief Test that the bins is constructed correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsDefaultConstructorBoundigBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + StaticBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], 0.0); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], 9.0); +} + +/** + * @brief Test that the number of cells is calculated correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsDefaultConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + StaticBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsDefaultConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + StaticBins testBins(points.begin(), points.end()); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], 3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], 3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], 3.0); +} + +/** + * @brief Test that the bins is constructed correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsBBConstructorBoundingBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + StaticBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], testMinPoint[0]); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], testMinPoint[1]); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], testMinPoint[2]); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], testMaxPoint[0]); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], testMaxPoint[1]); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], testMaxPoint[2]); +} + +/** + * @brief Test that the number of cells is calculated correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsBBConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + StaticBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly with the bounding box constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsBBConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointType testMinPoint(10, -10.0, -10.0, -10.0); + PointType testMaxPoint(11, 10.0, 10.0, 10.0); + + StaticBins testBins(points.begin(), points.end(), testMinPoint, testMaxPoint); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], 20.0/3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], 20.0/3.0); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], 20.0/3.0); +} + +/** + * @brief Test that the bins is constructed correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsCellSizeConstructorBoundingBox, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + StaticBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[0], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[1], 0.0); + KRATOS_CHECK_EQUAL(testBins.GetMinPoint()[2], 0.0); + + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[0], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[1], 9.0); + KRATOS_CHECK_EQUAL(testBins.GetMaxPoint()[2], 9.0); +} + +/** + * @brief Test that the number of cells is calculated correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsCellSizeConstructorCellNumber, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + StaticBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[0], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[1], 3); + KRATOS_CHECK_EQUAL(testBins.GetDivisions()[2], 3); +} + +/** + * @brief Test that the size of the cells is calculated correctly with the cell size constructor + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsCellSizeConstructorCellSize, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + CoordinateType testCellSize = 3.2244; + + StaticBins testBins(points.begin(), points.end(), testCellSize); + + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[0], testCellSize); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[1], testCellSize); + KRATOS_CHECK_EQUAL(testBins.GetCellSize()[2], testCellSize); +} + +/** + * @brief Searches the nearest point + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsExistPoint, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + StaticBins testBins(points.begin(), points.end()); + + PointerType nearestPoint = testBins.ExistPoint(PointerType(new PointType(0, 4.1, 4.1, 4.1))); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); +} + +/** + * @brief Searches the nearest point (excluding the input) + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsNearestPointInner, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + points.push_back(pointToSearch); + + StaticBins testBins(points.begin(), points.end()); + + PointerType nearestPoint = testBins.SearchNearestPointInner(pointToSearch); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); +} + +/** + * @brief Searches the nearest point with (including the input) + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsNearestPoint, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + points.push_back(pointToSearch); + + StaticBins testBins(points.begin(), points.end()); + + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 10); +} + +/** + * @brief Searches the nearest point (including the input) with distance + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsNearestPointWithDistance, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + + StaticBins testBins(points.begin(), points.end()); + + double squaredDistance = 0.0; + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch, squaredDistance); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); + KRATOS_CHECK_EQUAL(squaredDistance, 0.1875); +} + +/** + * @brief Searches the nearest point (including the input) with distance (threadsafe) + * + */ +KRATOS_TEST_CASE_IN_SUITE(StaticBinsNearestPointWithDistanceThreadsafe, KratosCoreFastSuite) +{ + PointVector points; + + for(std::size_t i = 0; i < 10; i++) { + points.push_back(PointTypePointer(new PointType(i, i, i, i))); + } + + PointerType pointToSearch = PointerType(new PointType(10, 4.25, 4.25, 4.25)); + + StaticBins testBins(points.begin(), points.end()); + SearchStructureType searchBox; + + double squaredDistance = 0.0; + PointerType nearestPoint = testBins.SearchNearestPoint(*pointToSearch, squaredDistance, searchBox); + + KRATOS_CHECK_EQUAL(nearestPoint->Id(), 4); + KRATOS_CHECK_EQUAL(squaredDistance, 0.1875); +} + + +} // namespace Testesing +} // namespace Kratos \ No newline at end of file diff --git a/kratos/tests/cpp_tests/strategies/builder_and_solvers/test_builder_and_solver.cpp b/kratos/tests/cpp_tests/strategies/builder_and_solvers/test_builder_and_solver.cpp new file mode 100755 index 000000000000..26073a633c9c --- /dev/null +++ b/kratos/tests/cpp_tests/strategies/builder_and_solvers/test_builder_and_solver.cpp @@ -0,0 +1,786 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include +#include + +/* External includes */ + +/* Project includes */ +#include "testing/testing.h" + +/* Utility includes */ +#include "includes/define.h" +#include "containers/model.h" +#include "includes/model_part.h" +#include "spaces/ublas_space.h" + +/* Element include */ +#include "geometries/line_2d_2.h" +#include "tests/cpp_tests/auxiliar_files/test_bar_element.h" + +// Linear solvers +#include "linear_solvers/reorderer.h" +#include "linear_solvers/direct_solver.h" +#include "linear_solvers/linear_solver.h" +#include "linear_solvers/skyline_lu_factorization_solver.h" + +// The most basic scheme (static) +#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" + +// The builder and solvers +#include "solving_strategies/builder_and_solvers/residualbased_elimination_builder_and_solver.h" +#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h" +#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver_with_constraints.h" + +namespace Kratos +{ + namespace Testing + { + /// Tests + // TODO: Create test for the other components + typedef Node<3> NodeType; + typedef Geometry GeometryType; + typedef UblasSpace SparseSpaceType; + typedef UblasSpace LocalSpaceType; + + // The direct solver + typedef Reorderer ReordererType; + typedef DirectSolver DirectSolverType; + typedef LinearSolver LinearSolverType; + typedef SkylineLUFactorizationSolver SkylineLUFactorizationSolverType; + + // The builder ans solver type + typedef BuilderAndSolver< SparseSpaceType, LocalSpaceType, LinearSolverType > BuilderAndSolverType; + typedef ResidualBasedBlockBuilderAndSolver< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedBlockBuilderAndSolverType; + typedef ResidualBasedBlockBuilderAndSolverWithConstraints< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedBlockBuilderAndSolverWithConstraintsType; + typedef ResidualBasedEliminationBuilderAndSolver< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedEliminationBuilderAndSolverType; + + // The time scheme + typedef Scheme< SparseSpaceType, LocalSpaceType > SchemeType; + typedef ResidualBasedIncrementalUpdateStaticScheme< SparseSpaceType, LocalSpaceType> ResidualBasedIncrementalUpdateStaticSchemeType; + + /** + * @brief It generates a truss structure with an expected solution + */ + static inline void BasicTestBuilderAndSolverDisplacement(ModelPart& rModelPart, const bool WithConstraint = false) + { + rModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + rModelPart.AddNodalSolutionStepVariable(VELOCITY); + rModelPart.AddNodalSolutionStepVariable(ACCELERATION); + rModelPart.AddNodalSolutionStepVariable(REACTION); + rModelPart.AddNodalSolutionStepVariable(VOLUME_ACCELERATION); + + NodeType::Pointer pnode1 = rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); + NodeType::Pointer pnode2 = rModelPart.CreateNewNode(2, 1.0, 0.0, 0.0); + NodeType::Pointer pnode3 = rModelPart.CreateNewNode(3, 2.0, 0.0, 0.0); + + auto p_prop = rModelPart.pGetProperties(1, 0); + p_prop->SetValue(YOUNG_MODULUS, 206900000000.0); + p_prop->SetValue(NODAL_AREA, 0.01); + + GeometryType::Pointer pgeom1 = Kratos::make_shared>(PointerVector{std::vector({pnode1, pnode2})}); + rModelPart.AddElement(Kratos::make_shared( 1, pgeom1, p_prop)); + GeometryType::Pointer pgeom2 = Kratos::make_shared>(PointerVector{std::vector({pnode2, pnode3})}); + rModelPart.AddElement(Kratos::make_shared( 2, pgeom2, p_prop)); + + /// Add dof + for (auto& node : rModelPart.Nodes()) { + node.AddDof(DISPLACEMENT_X, REACTION_X); + node.AddDof(DISPLACEMENT_Y, REACTION_Y); + node.AddDof(DISPLACEMENT_Z, REACTION_Z); + } + + /// Initialize elements + auto& r_process_info = rModelPart.GetProcessInfo(); + for (auto& elem : rModelPart.Elements()) { + elem.Initialize(); + elem.InitializeSolutionStep(r_process_info); + } + + // Set initial solution + for (auto& node : rModelPart.Nodes()) { + (node.FastGetSolutionStepValue(DISPLACEMENT)).clear(); + (node.FastGetSolutionStepValue(DISPLACEMENT, 1)).clear(); + (node.FastGetSolutionStepValue(DISPLACEMENT, 2)).clear(); + } + + // Fix dofs + for (auto& node : rModelPart.Nodes()) { + node.Fix(DISPLACEMENT_Y); + node.Fix(DISPLACEMENT_Z); + } + pnode1->Fix(DISPLACEMENT_X); + + if (WithConstraint) { + rModelPart.CreateNewMasterSlaveConstraint("LinearMasterSlaveConstraint", 1, *pnode2, DISPLACEMENT_X, *pnode3, DISPLACEMENT_X, 1.0, 0.0); + } + } + + /** + * @brief It generates a truss structure with an expected solution + */ + static inline void ExtendedTestBuilderAndSolverDisplacement(ModelPart& rModelPart, const bool WithConstraint = false) + { + rModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + rModelPart.AddNodalSolutionStepVariable(VELOCITY); + rModelPart.AddNodalSolutionStepVariable(ACCELERATION); + rModelPart.AddNodalSolutionStepVariable(REACTION); + rModelPart.AddNodalSolutionStepVariable(VOLUME_ACCELERATION); + + NodeType::Pointer pnode1 = rModelPart.CreateNewNode(1, 10.0, -5.0, 0.0); + NodeType::Pointer pnode2 = rModelPart.CreateNewNode(2, 8.0, -4.0, 0.0); + NodeType::Pointer pnode3 = rModelPart.CreateNewNode(3, 6.0, -3.0, 0.0); + NodeType::Pointer pnode4 = rModelPart.CreateNewNode(4,10.0, 0.0, 0.0); + NodeType::Pointer pnode5 = rModelPart.CreateNewNode(5, 8.0, 0.0, 0.0); + NodeType::Pointer pnode6 = rModelPart.CreateNewNode(6, 6.0, 0.0, 0.0); + NodeType::Pointer pnode7 = rModelPart.CreateNewNode(7, 4.0, -2.0, 0.0); + NodeType::Pointer pnode8 = rModelPart.CreateNewNode(8, 4.0, 0.0, 0.0); + NodeType::Pointer pnode9 = rModelPart.CreateNewNode(9, 2.0, -1.0, 0.0); + NodeType::Pointer pnode10 = rModelPart.CreateNewNode(10, 2.0, 0.0, 0.0); + NodeType::Pointer pnode11 = rModelPart.CreateNewNode(11, 0.0, 0.0, 0.0); + + auto p_prop = rModelPart.pGetProperties(1, 0); + p_prop->SetValue(YOUNG_MODULUS, 206900000000.0); + p_prop->SetValue(NODAL_AREA, 0.01); + + GeometryType::Pointer pgeom1 = Kratos::make_shared>(PointerVector{std::vector({pnode11, pnode10})}); + rModelPart.AddElement(Kratos::make_shared( 1, pgeom1, p_prop)); + GeometryType::Pointer pgeom2 = Kratos::make_shared>(PointerVector{std::vector({pnode10, pnode8})}); + rModelPart.AddElement(Kratos::make_shared( 2, pgeom2, p_prop)); + GeometryType::Pointer pgeom3 = Kratos::make_shared>(PointerVector{std::vector({pnode8, pnode6})}); + rModelPart.AddElement(Kratos::make_shared( 3, pgeom3, p_prop)); + GeometryType::Pointer pgeom4 = Kratos::make_shared>(PointerVector{std::vector({pnode6, pnode5})}); + rModelPart.AddElement(Kratos::make_shared( 4, pgeom4, p_prop)); + GeometryType::Pointer pgeom5 = Kratos::make_shared>(PointerVector{std::vector({pnode5, pnode4})}); + rModelPart.AddElement(Kratos::make_shared( 5, pgeom5, p_prop)); + GeometryType::Pointer pgeom6 = Kratos::make_shared>(PointerVector{std::vector({pnode4, pnode1})}); + rModelPart.AddElement(Kratos::make_shared( 6, pgeom6, p_prop)); + GeometryType::Pointer pgeom7 = Kratos::make_shared>(PointerVector{std::vector({pnode1, pnode2})}); + rModelPart.AddElement(Kratos::make_shared( 7, pgeom7, p_prop)); + GeometryType::Pointer pgeom8 = Kratos::make_shared>(PointerVector{std::vector({pnode2, pnode3})}); + rModelPart.AddElement(Kratos::make_shared( 8, pgeom8, p_prop)); + GeometryType::Pointer pgeom9 = Kratos::make_shared>(PointerVector{std::vector({pnode3, pnode7})}); + rModelPart.AddElement(Kratos::make_shared( 9, pgeom9, p_prop)); + GeometryType::Pointer pgeom10 = Kratos::make_shared>(PointerVector{std::vector({pnode7, pnode9})}); + rModelPart.AddElement(Kratos::make_shared( 10, pgeom10, p_prop)); + GeometryType::Pointer pgeom11 = Kratos::make_shared>(PointerVector{std::vector({pnode9, pnode11})}); + rModelPart.AddElement(Kratos::make_shared( 11, pgeom11, p_prop)); + GeometryType::Pointer pgeom12 = Kratos::make_shared>(PointerVector{std::vector({pnode10, pnode9})}); + rModelPart.AddElement(Kratos::make_shared( 12, pgeom12, p_prop)); + GeometryType::Pointer pgeom13 = Kratos::make_shared>(PointerVector{std::vector({pnode9, pnode8})}); + rModelPart.AddElement(Kratos::make_shared( 13, pgeom13, p_prop)); + GeometryType::Pointer pgeom14 = Kratos::make_shared>(PointerVector{std::vector({pnode8, pnode7})}); + rModelPart.AddElement(Kratos::make_shared( 14, pgeom14, p_prop)); + GeometryType::Pointer pgeom15 = Kratos::make_shared>(PointerVector{std::vector({pnode7, pnode6})}); + rModelPart.AddElement(Kratos::make_shared( 15, pgeom15, p_prop)); + GeometryType::Pointer pgeom16 = Kratos::make_shared>(PointerVector{std::vector({pnode6, pnode3})}); + rModelPart.AddElement(Kratos::make_shared( 16, pgeom16, p_prop)); + GeometryType::Pointer pgeom17 = Kratos::make_shared>(PointerVector{std::vector({pnode3, pnode5})}); + rModelPart.AddElement(Kratos::make_shared( 17, pgeom17, p_prop)); + GeometryType::Pointer pgeom18 = Kratos::make_shared>(PointerVector{std::vector({pnode5, pnode2})}); + rModelPart.AddElement(Kratos::make_shared( 18, pgeom18, p_prop)); + GeometryType::Pointer pgeom19 = Kratos::make_shared>(PointerVector{std::vector({pnode2, pnode4})}); + rModelPart.AddElement(Kratos::make_shared( 19, pgeom19, p_prop)); + + /// Add dof + for (auto& node : rModelPart.Nodes()) { + node.AddDof(DISPLACEMENT_X, REACTION_X); + node.AddDof(DISPLACEMENT_Y, REACTION_Y); + node.AddDof(DISPLACEMENT_Z, REACTION_Z); + } + + /// Initialize elements + auto& r_process_info = rModelPart.GetProcessInfo(); + for (auto& elem : rModelPart.Elements()) { + elem.Initialize(); + elem.InitializeSolutionStep(r_process_info); + } + + // Set initial solution + for (auto& node : rModelPart.Nodes()) { + (node.FastGetSolutionStepValue(DISPLACEMENT)).clear(); + (node.FastGetSolutionStepValue(DISPLACEMENT, 1)).clear(); + (node.FastGetSolutionStepValue(DISPLACEMENT, 2)).clear(); + } + + // Fix dofs + for (auto& node : rModelPart.Nodes()) { + node.Fix(DISPLACEMENT_Z); + } + pnode1->Fix(DISPLACEMENT_X); + pnode4->Fix(DISPLACEMENT_X); + pnode4->Fix(DISPLACEMENT_Y); + + if (WithConstraint) { + rModelPart.CreateNewMasterSlaveConstraint("LinearMasterSlaveConstraint", 1, *pnode1, DISPLACEMENT_Y, *pnode2, DISPLACEMENT_Y, 1.0, 0.0); + } + } + + static SparseSpaceType::MatrixType BuildSystem( + ModelPart& rModelPart, + SchemeType::Pointer pScheme, + BuilderAndSolverType::Pointer pBuilderAndSolver + ) + { + pBuilderAndSolver->SetDofSetIsInitializedFlag(false); + pBuilderAndSolver->Clear(); + pScheme->Clear(); + + SparseSpaceType::VectorPointerType pDx; /// The incremement in the solution + SparseSpaceType::VectorPointerType pb; /// The RHS vector of the system of equations + SparseSpaceType::MatrixPointerType pA; /// The LHS matrix of the system of equations + + pBuilderAndSolver->SetUpDofSet(pScheme, rModelPart); + pBuilderAndSolver->SetUpSystem(rModelPart); + pBuilderAndSolver->ResizeAndInitializeVectors(pScheme, pA, pDx, pb, rModelPart); + + SparseSpaceType::MatrixType& rA = *pA; + SparseSpaceType::VectorType& rDx = *pDx; + SparseSpaceType::VectorType& rb = *pb; + + pBuilderAndSolver->InitializeSolutionStep(rModelPart, rA, rDx, rb); + pScheme->InitializeSolutionStep(rModelPart, rA, rDx, rb); + pScheme->InitializeNonLinIteration(rModelPart, rA, rDx, rb); + + pBuilderAndSolver->Build(pScheme, rModelPart, rA, rb); + pBuilderAndSolver->ApplyDirichletConditions(pScheme, rModelPart, rA, rDx, rb); + + return rA; + } + +// static void DebugLHS(const SparseSpaceType::MatrixType& rA) +// { +// for (int i = 0; i < rA.size1(); ++i) { +// for (int j = 0; j < rA.size2(); ++j) { +// if (std::abs(rA(i, j)) > 0.99) { +// std::cout << " KRATOS_CHECK_LESS_EQUAL(std::abs((rA(" << i << "," << j << ") - "; +// std::cout << std::fixed; +// std::cout << std::setprecision(16); +// std::cout << rA(i, j); +// std::cout << ")/rA(" << i << "," << j << ")), tolerance);" << std::endl; +// } +// } +// } +// } + + /** + * Checks if the block builder and solver performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(BasicDisplacementBlockBuilderAndSolver, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + BasicTestBuilderAndSolverDisplacement(r_model_part); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 6); + KRATOS_CHECK(rA.size2() == 6); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 2069000000.000000000)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 1.000000000)/rA(1,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,2) - 4138000000.000000000)/rA(2,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,4) - -2069000000.000000000)/rA(2,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,3) - 1.000000000)/rA(3,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,2) - -2069000000.000000000)/rA(4,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,4) - 2069000000.000000000)/rA(4,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,5) - 1.000000000)/rA(5,5)), tolerance); + + } + + /** + * Checks if the block builder and solver with constraints performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(BasicDisplacementBlockBuilderAndSolverWithConstraints, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + BasicTestBuilderAndSolverDisplacement(r_model_part, true); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverWithConstraintsType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 6); + KRATOS_CHECK(rA.size2() == 6); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 2069000000.0000000000000000)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 1.0000000000000000)/rA(1,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,2) - 2069000000.0000000000000000)/rA(2,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,3) - 1.0000000000000000)/rA(3,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,4) - 2069000000.0000000000000000)/rA(4,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,5) - 1.0000000000000000)/rA(5,5)), tolerance); + + + } + + /** + * Checks if the elimination builder and solver performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(BasicDisplacementEliminationBuilderAndSolver, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + BasicTestBuilderAndSolverDisplacement(r_model_part); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedEliminationBuilderAndSolverType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 2); + KRATOS_CHECK(rA.size2() == 2); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 4138000000.000000000)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,1) - -2069000000.000000000)/rA(0,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,0) - -2069000000.000000000)/rA(1,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 2069000000.000000000)/rA(1,1)), tolerance); + + } + + /** + * Checks if the block builder and solver performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(ExtendedDisplacementBlockBuilderAndSolver, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + ExtendedTestBuilderAndSolverDisplacement(r_model_part); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 22); + KRATOS_CHECK(rA.size2() == 22); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 740227943.2715302705764771)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 598856985.8178827762603760)/rA(1,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,2) - 370113971.6357653141021729)/rA(1,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,3) - -185056985.8178827166557312)/rA(1,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,1) - 370113971.6357653141021729)/rA(2,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,2) - 1572984379.4520018100738525)/rA(2,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,3) - -555170957.4536480903625488)/rA(2,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,4) - -740227943.2715302705764771)/rA(2,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,5) - 370113971.6357653141021729)/rA(2,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,1) - -185056985.8178827166557312)/rA(3,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,2) - -555170957.4536479711532593)/rA(3,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,3) - 1257477943.2715306282043457)/rA(3,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,4) - 370113971.6357653141021729)/rA(3,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,5) - -185056985.8178827166557312)/rA(3,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,9) - -517250000.0000000000000000)/rA(3,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,2) - -740227943.2715302705764771)/rA(4,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,3) - 370113971.6357653141021729)/rA(4,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,4) - 1657021225.9261374473571777)/rA(4,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,5) - -475379934.1969153881072998)/rA(4,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,8) - -176565339.3830768167972565)/rA(4,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,9) - -264848009.0746152102947235)/rA(4,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,12) - -740227943.2715302705764771)/rA(4,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,13) - 370113971.6357653141021729)/rA(4,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,2) - 370113971.6357652544975281)/rA(5,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,3) - -185056985.8178827166557312)/rA(5,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,4) - -475379934.1969153881072998)/rA(5,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,5) - 1457052651.9143548011779785)/rA(5,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,8) - -264848009.0746152102947235)/rA(5,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,9) - -397272013.6119228005409241)/rA(5,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,11) - -689666666.6666666269302368)/rA(5,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,12) - 370113971.6357653141021729)/rA(5,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,13) - -185056985.8178827166557312)/rA(5,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,6) - 1127028492.9089412689208984)/rA(6,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,7) - 783913971.6357650756835938)/rA(7,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,4) - -176565339.3830768167972565)/rA(8,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,5) - -264848009.0746152102947235)/rA(8,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,8) - 2245565339.3830766677856445)/rA(8,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,9) - 264848009.0746151804924011)/rA(8,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,10) - -1034500000.0000000000000000)/rA(8,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,3) - -517250000.0000000000000000)/rA(9,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,4) - -264848009.0746152102947235)/rA(9,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,5) - -397272013.6119228005409241)/rA(9,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,8) - 264848009.0746151804924011)/rA(9,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,9) - 914522013.6119227409362793)/rA(9,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,8) - -1034500000.0000000000000000)/rA(10,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,10) - 2434750982.5687417984008789)/rA(10,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,11) - 365750982.5687416195869446)/rA(10,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,12) - -365750982.5687417387962341)/rA(10,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,13) - -365750982.5687416791915894)/rA(10,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,14) - -1034500000.0000000000000000)/rA(10,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,5) - -689666666.6666666269302368)/rA(11,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,10) - 365750982.5687416195869446)/rA(11,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,11) - 1055417649.2354083061218262)/rA(11,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,12) - -365750982.5687416791915894)/rA(11,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,13) - -365750982.5687416195869446)/rA(11,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,4) - -740227943.2715302705764771)/rA(12,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,5) - 370113971.6357653141021729)/rA(12,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,10) - -365750982.5687417387962341)/rA(12,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,11) - -365750982.5687416791915894)/rA(12,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,12) - 1846206869.1118023395538330)/rA(12,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,13) - -374476960.7027890682220459)/rA(12,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,16) - -740227943.2715302705764771)/rA(12,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,17) - 370113971.6357653141021729)/rA(12,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,4) - 370113971.6357652544975281)/rA(13,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,5) - -185056985.8178827166557312)/rA(13,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,10) - -365750982.5687416791915894)/rA(13,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,11) - -365750982.5687416195869446)/rA(13,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,12) - -374476960.7027890682220459)/rA(13,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,13) - 1770364954.2045071125030518)/rA(13,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,15) - -1034500000.0000000000000000)/rA(13,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,16) - 370113971.6357653141021729)/rA(13,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,17) - -185056985.8178827166557312)/rA(13,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,10) - -1034500000.0000000000000000)/rA(14,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,14) - 2809227943.2715301513671875)/rA(14,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,15) - 370113971.6357650756835938)/rA(14,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,16) - -740227943.2715302705764771)/rA(14,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,17) - -370113971.6357651352882385)/rA(14,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,18) - -1034500000.0000000000000000)/rA(14,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,13) - -1034500000.0000000000000000)/rA(15,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,14) - 370113971.6357650756835938)/rA(15,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,15) - 1219556985.8178825378417969)/rA(15,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,16) - -370113971.6357651352882385)/rA(15,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,17) - -185056985.8178825676441193)/rA(15,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,12) - -740227943.2715302705764771)/rA(16,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,13) - 370113971.6357653141021729)/rA(16,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,14) - -740227943.2715302705764771)/rA(16,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,15) - -370113971.6357651352882385)/rA(16,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,16) - 2220683829.8145909309387207)/rA(16,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,17) - -370113971.6357656121253967)/rA(16,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,20) - -740227943.2715302705764771)/rA(16,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,21) - 370113971.6357653141021729)/rA(16,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,12) - 370113971.6357652544975281)/rA(17,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,13) - -185056985.8178827166557312)/rA(17,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,14) - -370113971.6357651352882385)/rA(17,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,15) - -185056985.8178825676441193)/rA(17,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,16) - -370113971.6357656121253967)/rA(17,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,17) - 2624170957.4536480903625488)/rA(17,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,19) - -2069000000.0000000000000000)/rA(17,19)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,20) - 370113971.6357653141021729)/rA(17,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,21) - -185056985.8178827166557312)/rA(17,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,14) - -1034500000.0000000000000000)/rA(18,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,18) - 2069000000.0000000000000000)/rA(18,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,20) - -1034500000.0000000000000000)/rA(18,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(19,17) - -2069000000.0000000000000000)/rA(19,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(19,19) - 2069000000.0000000000000000)/rA(19,19)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,16) - -740227943.2715302705764771)/rA(20,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,17) - 370113971.6357653141021729)/rA(20,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,18) - -1034500000.0000000000000000)/rA(20,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,20) - 1774727943.2715301513671875)/rA(20,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,21) - -370113971.6357653141021729)/rA(20,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,16) - 370113971.6357652544975281)/rA(21,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,17) - -185056985.8178827166557312)/rA(21,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,20) - -370113971.6357653141021729)/rA(21,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,21) - 185056985.8178827166557312)/rA(21,21)), tolerance); + } + + /** + * Checks if the block builder and solver with constraints performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(ExtendedDisplacementBlockBuilderAndSolverWithConstraints, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + ExtendedTestBuilderAndSolverDisplacement(r_model_part, true); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverWithConstraintsType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 22); + KRATOS_CHECK(rA.size2() == 22); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 740227943.2715302705764771)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 1486220957.4536478519439697)/rA(1,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,2) - -185056985.8178826868534088)/rA(1,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,4) - 370113971.6357653141021729)/rA(1,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,5) - -185056985.8178827166557312)/rA(1,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,9) - -517250000.0000000000000000)/rA(1,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,1) - -185056985.8178827762603760)/rA(2,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,2) - 1572984379.4520018100738525)/rA(2,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,4) - -740227943.2715302705764771)/rA(2,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,5) - 370113971.6357653141021729)/rA(2,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,3) - 1257477943.2715306282043457)/rA(3,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,1) - 370113971.6357653141021729)/rA(4,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,2) - -740227943.2715302705764771)/rA(4,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,4) - 1657021225.9261374473571777)/rA(4,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,5) - -475379934.1969153881072998)/rA(4,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,8) - -176565339.3830768167972565)/rA(4,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,9) - -264848009.0746152102947235)/rA(4,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,12) - -740227943.2715302705764771)/rA(4,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,13) - 370113971.6357653141021729)/rA(4,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,1) - -185056985.8178827166557312)/rA(5,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,2) - 370113971.6357652544975281)/rA(5,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,4) - -475379934.1969153881072998)/rA(5,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,5) - 1457052651.9143548011779785)/rA(5,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,8) - -264848009.0746152102947235)/rA(5,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,9) - -397272013.6119228005409241)/rA(5,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,11) - -689666666.6666666269302368)/rA(5,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,12) - 370113971.6357653141021729)/rA(5,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,13) - -185056985.8178827166557312)/rA(5,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,6) - 1127028492.9089412689208984)/rA(6,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,7) - 783913971.6357650756835938)/rA(7,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,4) - -176565339.3830768167972565)/rA(8,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,5) - -264848009.0746152102947235)/rA(8,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,8) - 2245565339.3830766677856445)/rA(8,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,9) - 264848009.0746151804924011)/rA(8,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,10) - -1034500000.0000000000000000)/rA(8,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,1) - -517250000.0000000000000000)/rA(9,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,4) - -264848009.0746152102947235)/rA(9,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,5) - -397272013.6119228005409241)/rA(9,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,8) - 264848009.0746151804924011)/rA(9,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,9) - 914522013.6119227409362793)/rA(9,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,8) - -1034500000.0000000000000000)/rA(10,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,10) - 2434750982.5687417984008789)/rA(10,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,11) - 365750982.5687416195869446)/rA(10,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,12) - -365750982.5687417387962341)/rA(10,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,13) - -365750982.5687416791915894)/rA(10,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,14) - -1034500000.0000000000000000)/rA(10,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,5) - -689666666.6666666269302368)/rA(11,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,10) - 365750982.5687416195869446)/rA(11,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,11) - 1055417649.2354083061218262)/rA(11,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,12) - -365750982.5687416791915894)/rA(11,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,13) - -365750982.5687416195869446)/rA(11,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,4) - -740227943.2715302705764771)/rA(12,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,5) - 370113971.6357653141021729)/rA(12,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,10) - -365750982.5687417387962341)/rA(12,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,11) - -365750982.5687416791915894)/rA(12,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,12) - 1846206869.1118023395538330)/rA(12,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,13) - -374476960.7027890682220459)/rA(12,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,16) - -740227943.2715302705764771)/rA(12,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,17) - 370113971.6357653141021729)/rA(12,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,4) - 370113971.6357652544975281)/rA(13,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,5) - -185056985.8178827166557312)/rA(13,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,10) - -365750982.5687416791915894)/rA(13,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,11) - -365750982.5687416195869446)/rA(13,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,12) - -374476960.7027890682220459)/rA(13,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,13) - 1770364954.2045071125030518)/rA(13,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,15) - -1034500000.0000000000000000)/rA(13,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,16) - 370113971.6357653141021729)/rA(13,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,17) - -185056985.8178827166557312)/rA(13,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,10) - -1034500000.0000000000000000)/rA(14,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,14) - 2809227943.2715301513671875)/rA(14,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,15) - 370113971.6357650756835938)/rA(14,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,16) - -740227943.2715302705764771)/rA(14,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,17) - -370113971.6357651352882385)/rA(14,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,18) - -1034500000.0000000000000000)/rA(14,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,13) - -1034500000.0000000000000000)/rA(15,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,14) - 370113971.6357650756835938)/rA(15,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,15) - 1219556985.8178825378417969)/rA(15,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,16) - -370113971.6357651352882385)/rA(15,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,17) - -185056985.8178825676441193)/rA(15,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,12) - -740227943.2715302705764771)/rA(16,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,13) - 370113971.6357653141021729)/rA(16,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,14) - -740227943.2715302705764771)/rA(16,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,15) - -370113971.6357651352882385)/rA(16,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,16) - 2220683829.8145909309387207)/rA(16,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,17) - -370113971.6357656121253967)/rA(16,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,20) - -740227943.2715302705764771)/rA(16,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,21) - 370113971.6357653141021729)/rA(16,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,12) - 370113971.6357652544975281)/rA(17,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,13) - -185056985.8178827166557312)/rA(17,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,14) - -370113971.6357651352882385)/rA(17,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,15) - -185056985.8178825676441193)/rA(17,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,16) - -370113971.6357656121253967)/rA(17,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,17) - 2624170957.4536480903625488)/rA(17,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,19) - -2069000000.0000000000000000)/rA(17,19)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,20) - 370113971.6357653141021729)/rA(17,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,21) - -185056985.8178827166557312)/rA(17,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,14) - -1034500000.0000000000000000)/rA(18,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,18) - 2069000000.0000000000000000)/rA(18,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,20) - -1034500000.0000000000000000)/rA(18,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(19,17) - -2069000000.0000000000000000)/rA(19,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(19,19) - 2069000000.0000000000000000)/rA(19,19)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,16) - -740227943.2715302705764771)/rA(20,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,17) - 370113971.6357653141021729)/rA(20,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,18) - -1034500000.0000000000000000)/rA(20,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,20) - 1774727943.2715301513671875)/rA(20,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(20,21) - -370113971.6357653141021729)/rA(20,21)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,16) - 370113971.6357652544975281)/rA(21,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,17) - -185056985.8178827166557312)/rA(21,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,20) - -370113971.6357653141021729)/rA(21,20)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(21,21) - 185056985.8178827166557312)/rA(21,21)), tolerance); + } + + /** + * Checks if the elimination builder and solver performs correctly the assemble of the system + */ + KRATOS_TEST_CASE_IN_SUITE(ExtendedDisplacementEliminationBuilderAndSolver, KratosCoreFastSuite) + { + Model current_model; + ModelPart& r_model_part = current_model.CreateModelPart("Main", 3); + + ExtendedTestBuilderAndSolverDisplacement(r_model_part); + + SchemeType::Pointer p_scheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer p_solver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer p_builder_and_solver = BuilderAndSolverType::Pointer( new ResidualBasedEliminationBuilderAndSolverType(p_solver) ); + + const SparseSpaceType::MatrixType& rA = BuildSystem(r_model_part, p_scheme, p_builder_and_solver); + + // To create the solution of reference +// DebugLHS(rA); + + // The solution check + constexpr double tolerance = 1e-8; + KRATOS_CHECK(rA.size1() == 19); + KRATOS_CHECK(rA.size2() == 19); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,0) - 598856985.8178827762603760)/rA(0,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,1) - 370113971.6357653141021729)/rA(0,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(0,2) - -185056985.8178827166557312)/rA(0,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,0) - 370113971.6357653141021729)/rA(1,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,1) - 1572984379.4520018100738525)/rA(1,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,2) - -555170957.4536480903625488)/rA(1,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,3) - -740227943.2715302705764771)/rA(1,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(1,4) - 370113971.6357653141021729)/rA(1,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,0) - -185056985.8178827166557312)/rA(2,0)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,1) - -555170957.4536479711532593)/rA(2,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,2) - 1257477943.2715306282043457)/rA(2,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,3) - 370113971.6357653141021729)/rA(2,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,4) - -185056985.8178827166557312)/rA(2,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(2,6) - -517250000.0000000000000000)/rA(2,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,1) - -740227943.2715302705764771)/rA(3,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,2) - 370113971.6357653141021729)/rA(3,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,3) - 1657021225.9261374473571777)/rA(3,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,4) - -475379934.1969153881072998)/rA(3,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,5) - -176565339.3830768167972565)/rA(3,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,6) - -264848009.0746152102947235)/rA(3,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,9) - -740227943.2715302705764771)/rA(3,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(3,10) - 370113971.6357653141021729)/rA(3,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,1) - 370113971.6357652544975281)/rA(4,1)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,2) - -185056985.8178827166557312)/rA(4,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,3) - -475379934.1969153881072998)/rA(4,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,4) - 1457052651.9143548011779785)/rA(4,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,5) - -264848009.0746152102947235)/rA(4,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,6) - -397272013.6119228005409241)/rA(4,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,8) - -689666666.6666666269302368)/rA(4,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,9) - 370113971.6357653141021729)/rA(4,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(4,10) - -185056985.8178827166557312)/rA(4,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,3) - -176565339.3830768167972565)/rA(5,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,4) - -264848009.0746152102947235)/rA(5,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,5) - 2245565339.3830766677856445)/rA(5,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,6) - 264848009.0746151804924011)/rA(5,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(5,7) - -1034500000.0000000000000000)/rA(5,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,2) - -517250000.0000000000000000)/rA(6,2)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,3) - -264848009.0746152102947235)/rA(6,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,4) - -397272013.6119228005409241)/rA(6,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,5) - 264848009.0746151804924011)/rA(6,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(6,6) - 914522013.6119227409362793)/rA(6,6)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,5) - -1034500000.0000000000000000)/rA(7,5)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,7) - 2434750982.5687417984008789)/rA(7,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,8) - 365750982.5687416195869446)/rA(7,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,9) - -365750982.5687417387962341)/rA(7,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,10) - -365750982.5687416791915894)/rA(7,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(7,11) - -1034500000.0000000000000000)/rA(7,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,4) - -689666666.6666666269302368)/rA(8,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,7) - 365750982.5687416195869446)/rA(8,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,8) - 1055417649.2354083061218262)/rA(8,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,9) - -365750982.5687416791915894)/rA(8,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(8,10) - -365750982.5687416195869446)/rA(8,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,3) - -740227943.2715302705764771)/rA(9,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,4) - 370113971.6357653141021729)/rA(9,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,7) - -365750982.5687417387962341)/rA(9,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,8) - -365750982.5687416791915894)/rA(9,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,9) - 1846206869.1118023395538330)/rA(9,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,10) - -374476960.7027890682220459)/rA(9,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,13) - -740227943.2715302705764771)/rA(9,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(9,14) - 370113971.6357653141021729)/rA(9,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,3) - 370113971.6357652544975281)/rA(10,3)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,4) - -185056985.8178827166557312)/rA(10,4)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,7) - -365750982.5687416791915894)/rA(10,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,8) - -365750982.5687416195869446)/rA(10,8)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,9) - -374476960.7027890682220459)/rA(10,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,10) - 1770364954.2045071125030518)/rA(10,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,12) - -1034500000.0000000000000000)/rA(10,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,13) - 370113971.6357653141021729)/rA(10,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(10,14) - -185056985.8178827166557312)/rA(10,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,7) - -1034500000.0000000000000000)/rA(11,7)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,11) - 2809227943.2715301513671875)/rA(11,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,12) - 370113971.6357650756835938)/rA(11,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,13) - -740227943.2715302705764771)/rA(11,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,14) - -370113971.6357651352882385)/rA(11,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(11,15) - -1034500000.0000000000000000)/rA(11,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,10) - -1034500000.0000000000000000)/rA(12,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,11) - 370113971.6357650756835938)/rA(12,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,12) - 1219556985.8178825378417969)/rA(12,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,13) - -370113971.6357651352882385)/rA(12,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(12,14) - -185056985.8178825676441193)/rA(12,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,9) - -740227943.2715302705764771)/rA(13,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,10) - 370113971.6357653141021729)/rA(13,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,11) - -740227943.2715302705764771)/rA(13,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,12) - -370113971.6357651352882385)/rA(13,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,13) - 2220683829.8145909309387207)/rA(13,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,14) - -370113971.6357656121253967)/rA(13,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,17) - -740227943.2715302705764771)/rA(13,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(13,18) - 370113971.6357653141021729)/rA(13,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,9) - 370113971.6357652544975281)/rA(14,9)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,10) - -185056985.8178827166557312)/rA(14,10)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,11) - -370113971.6357651352882385)/rA(14,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,12) - -185056985.8178825676441193)/rA(14,12)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,13) - -370113971.6357656121253967)/rA(14,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,14) - 2624170957.4536480903625488)/rA(14,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,16) - -2069000000.0000000000000000)/rA(14,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,17) - 370113971.6357653141021729)/rA(14,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(14,18) - -185056985.8178827166557312)/rA(14,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,11) - -1034500000.0000000000000000)/rA(15,11)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,15) - 2069000000.0000000000000000)/rA(15,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(15,17) - -1034500000.0000000000000000)/rA(15,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,14) - -2069000000.0000000000000000)/rA(16,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(16,16) - 2069000000.0000000000000000)/rA(16,16)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,13) - -740227943.2715302705764771)/rA(17,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,14) - 370113971.6357653141021729)/rA(17,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,15) - -1034500000.0000000000000000)/rA(17,15)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,17) - 1774727943.2715301513671875)/rA(17,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(17,18) - -370113971.6357653141021729)/rA(17,18)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,13) - 370113971.6357652544975281)/rA(18,13)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,14) - -185056985.8178827166557312)/rA(18,14)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,17) - -370113971.6357653141021729)/rA(18,17)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs((rA(18,18) - 185056985.8178827166557312)/rA(18,18)), tolerance); + } + + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/strategies/schemes/test_residual_based_adjoint_bossak_scheme.cpp b/kratos/tests/cpp_tests/strategies/schemes/test_residual_based_adjoint_bossak_scheme.cpp new file mode 100644 index 000000000000..51e7861a2206 --- /dev/null +++ b/kratos/tests/cpp_tests/strategies/schemes/test_residual_based_adjoint_bossak_scheme.cpp @@ -0,0 +1,704 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// + +#include +#include +#include + +#include "testing/testing.h" +#include "containers/model.h" + +#include "includes/define.h" +#include "includes/shared_pointers.h" +#include "includes/model_part.h" +#include "containers/pointer_vector.h" +#include "spaces/ublas_space.h" +#include "linear_solvers/skyline_lu_custom_scalar_solver.h" +#include "solving_strategies/schemes/scheme.h" +#include "solving_strategies/schemes/residual_based_bossak_displacement_scheme.hpp" +#include "solving_strategies/schemes/residual_based_adjoint_bossak_scheme.h" +#include "solving_strategies/strategies/solving_strategy.h" +#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" +#include "solving_strategies/strategies/residualbased_linear_strategy.h" +#include "solving_strategies/convergencecriterias/residual_criteria.h" +#include "utilities/indirect_scalar.h" +#include "response_functions/adjoint_response_function.h" +#include "utilities/sensitivity_builder.h" +#include "utilities/adjoint_extensions.h" + + +namespace Kratos +{ +namespace Testing +{ +namespace +{ +const double AlphaBossak = -0.3; +namespace Base +{ +typedef UblasSpace SparseSpaceType; +typedef UblasSpace LocalSpaceType; +typedef LinearSolver LinearSolverType; +typedef Scheme SchemeType; +typedef ConvergenceCriteria ConvergenceCriteriaType; +typedef SolvingStrategy SolvingStrategyType; + +struct PrimalResults +{ + KRATOS_CLASS_POINTER_DEFINITION(PrimalResults); + virtual ~PrimalResults() {}; + virtual void StoreCurrentSolutionStep(const ModelPart& rModelPart) = 0; + virtual void LoadCurrentSolutionStep(ModelPart& rModelPart) const = 0; +}; + +class PrimalStrategy : public SolvingStrategy +{ +public: + KRATOS_CLASS_POINTER_DEFINITION(PrimalStrategy); + + PrimalStrategy(ModelPart& rModelPart, PrimalResults::Pointer pPrimalResults) + : SolvingStrategy(rModelPart), + mpPrimalResults(pPrimalResults) + { + auto p_scheme = + Kratos::make_shared>( + AlphaBossak); + auto p_linear_solver = + Kratos::make_shared>(); + auto p_conv_criteria = + Kratos::make_shared>( + 1e-10, 1e-13); + mpSolver = Kratos::make_shared>( + rModelPart, p_scheme, p_linear_solver, p_conv_criteria, 10, true, false, true); + } + + void Initialize() override + { + mpSolver->Initialize(); + } + + double Solve() override + { + auto result = mpSolver->Solve(); + mpPrimalResults->StoreCurrentSolutionStep(this->GetModelPart()); + return result; + } + +private: + PrimalResults::Pointer mpPrimalResults; + SolvingStrategyType::Pointer mpSolver; +}; + +class AdjointStrategy : public SolvingStrategy +{ +public: + KRATOS_CLASS_POINTER_DEFINITION(AdjointStrategy); + + AdjointStrategy(ModelPart& rModelPart, + Kratos::shared_ptr pPrimalResults, + AdjointResponseFunction::Pointer pResponseFunction) + : SolvingStrategy(rModelPart), + mpPrimalResults(pPrimalResults) + { + auto p_linear_solver = + Kratos::make_shared>(); + auto scheme_settings = Parameters{R"({ "alpha_bossak": )" + std::to_string(AlphaBossak) + " }"}; + auto p_adjoint_scheme = + Kratos::make_shared>( + scheme_settings, pResponseFunction); + mpSolver = + Kratos::make_shared>( + rModelPart, p_adjoint_scheme, p_linear_solver); + } + + void Initialize() override + { + mpSolver->Initialize(); + } + + double Solve() override + { + mpPrimalResults->LoadCurrentSolutionStep(this->GetModelPart()); + return mpSolver->Solve(); + } + +private: + PrimalResults::Pointer mpPrimalResults; + SolvingStrategyType::Pointer mpSolver; +}; +} + +namespace NonLinearSpringMassDamper +{ +/** + * @class PrimalElement + * @brief A system of two mass-spring-dampers for testing a second-order ode. + * @details Taken from L.F. Fernandez, D.A. Tortorelli, Semi-analytical + * sensitivity analysis for nonlinear transient problems. + * + * | _____ _____ + * |---[ Damper ]--|mass1|---[ Damper ]--|mass2| + * |-----/\/\/\----|_____|-----/\/\/\----|_____| + * | + * + * Spring force: fe = x + stiffness * x^3 + * Damper force: fc = damping * x' + * + * Momentum equations: + * mass1 * acc1 + 2 * damping * vel1 - damping * vel2 + 2 * disp1 - disp2 + stiffness * disp1^3 - stiffness * (disp2 - disp1)^3 = 0, + * mass2 * acc2 - damping * vel1 + damping * vel2 - disp1 + disp2 + stiffness * (disp2 - disp1)^3 = 0. + */ +class PrimalElement : public Element +{ +public: + KRATOS_CLASS_POINTER_DEFINITION(PrimalElement); + + static Pointer Create(Node<3>::Pointer pNode1, Node<3>::Pointer pNode2) + { + auto nodes = PointerVector>{}; + nodes.push_back(pNode1); + nodes.push_back(pNode2); + return Kratos::make_shared(nodes); + } + + PrimalElement(const NodesArrayType& ThisNodes) + : Element(0, ThisNodes) + { + } + + void EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& rCurrentProcessInfo) override + { + rResult.resize(2); + rResult[0] = this->GetGeometry()[0].GetDof(DISPLACEMENT_X).EquationId(); + rResult[1] = this->GetGeometry()[1].GetDof(DISPLACEMENT_X).EquationId(); + } + + void GetDofList(DofsVectorType& rElementalDofList, ProcessInfo& rCurrentProcessInfo) override + { + rElementalDofList.resize(2); + rElementalDofList[0] = this->GetGeometry()[0].pGetDof(DISPLACEMENT_X); + rElementalDofList[1] = this->GetGeometry()[1].pGetDof(DISPLACEMENT_X); + } + + void GetValuesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(DISPLACEMENT_X, Step); + } + + void GetFirstDerivativesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(VELOCITY_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(VELOCITY_X, Step); + } + + void GetSecondDerivativesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(ACCELERATION_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(ACCELERATION_X, Step); + } + + void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, + VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo) override + { + this->CalculateLeftHandSide(rLeftHandSideMatrix, rCurrentProcessInfo); + this->CalculateRightHandSide(rRightHandSideVector, rCurrentProcessInfo); + } + + void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo) override + { + rLeftHandSideMatrix.resize(2, 2, false); + const double& x1 = this->GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT_X); + const double& x2 = this->GetGeometry()[1].FastGetSolutionStepValue(DISPLACEMENT_X); + rLeftHandSideMatrix(0, 0) = 2. + 3. * stiffness * x1 * x1 + 3. * stiffness * (x2 - x1) * (x2 - x1); + rLeftHandSideMatrix(0, 1) = -1. - 3. * stiffness * (x2 - x1) * (x2 - x1); + rLeftHandSideMatrix(1, 0) = -1. - 3. * stiffness * (x2 - x1) * (x2 - x1); + rLeftHandSideMatrix(1, 1) = 1. + 3. * stiffness * (x2 - x1) * (x2 - x1); + } + + void CalculateRightHandSide(VectorType& rRightHandSideVector, + ProcessInfo& rCurrentProcessInfo) override + { + rRightHandSideVector.resize(2, false); + const double& x1 = this->GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT_X); + const double& x2 = this->GetGeometry()[1].FastGetSolutionStepValue(DISPLACEMENT_X); + const double x21 = x2 - x1; + rRightHandSideVector(0) = -(2. * x1 - x2 + stiffness * x1 * x1 * x1 - stiffness * x21 * x21 * x21); + rRightHandSideVector(1) = -(-x1 + x2 + stiffness * x21 * x21 * x21); + } + + void CalculateMassMatrix(MatrixType& rMassMatrix, ProcessInfo& rCurrentProcessInfo) override + { + rMassMatrix.resize(2, 2, false); + rMassMatrix(0, 0) = mass1; + rMassMatrix(0, 1) = 0.; + rMassMatrix(1, 1) = mass2; + rMassMatrix(1, 0) = 0.; + } + + void CalculateDampingMatrix(MatrixType& rDampingMatrix, ProcessInfo& rCurrentProcessInfo) override + { + rDampingMatrix.resize(2, 2, false); + rDampingMatrix(0, 0) = 2. * damping; + rDampingMatrix(0, 1) = -damping; + rDampingMatrix(1, 1) = damping; + rDampingMatrix(1, 0) = -damping; + } + +private: + const double mass1 = 1.; + const double mass2 = 1.; + const double stiffness = 1.; + const double damping = 0.1; +}; + +class AdjointElement : public Element +{ + class ThisExtensions : public AdjointExtensions + { + Element* mpElement; + + public: + ThisExtensions(Element* pElement) : mpElement{pElement} + { + } + + void GetFirstDerivativesVector(std::size_t NodeId, + std::vector>& rVector, + std::size_t Step) override + { + auto& r_node = mpElement->GetGeometry()[NodeId]; + if (rVector.size() != 1) + { + rVector.resize(1); + } + rVector[0] = MakeIndirectScalar(r_node, ADJOINT_VECTOR_2_X, Step); + } + + void GetSecondDerivativesVector(std::size_t NodeId, + std::vector>& rVector, + std::size_t Step) override + { + auto& r_node = mpElement->GetGeometry()[NodeId]; + if (rVector.size() != 1) + { + rVector.resize(1); + } + rVector[0] = MakeIndirectScalar(r_node, ADJOINT_VECTOR_3_X, Step); + } + + void GetAuxiliaryVector(std::size_t NodeId, + std::vector>& rVector, + std::size_t Step) override + { + auto& r_node = mpElement->GetGeometry()[NodeId]; + if (rVector.size() != 1) + { + rVector.resize(1); + } + rVector[0] = MakeIndirectScalar(r_node, AUX_ADJOINT_VECTOR_1_X, Step); + } + + void GetFirstDerivativesVariables(std::vector& rVariables) const override + { + if (rVariables.size() != 1) + { + rVariables.resize(1); + } + rVariables[0] = &ADJOINT_VECTOR_2; + } + + void GetSecondDerivativesVariables(std::vector& rVariables) const override + { + if (rVariables.size() != 1) + { + rVariables.resize(1); + } + rVariables[0] = &ADJOINT_VECTOR_3; + } + + void GetAuxiliaryVariables(std::vector& rVariables) const override + { + if (rVariables.size() != 1) + { + rVariables.resize(1); + } + rVariables[0] = &AUX_ADJOINT_VECTOR_1; + } + }; + +public: + KRATOS_CLASS_POINTER_DEFINITION(AdjointElement); + + static Pointer Create(Node<3>::Pointer pNode1, Node<3>::Pointer pNode2) + { + auto nodes = PointerVector>{}; + nodes.push_back(pNode1); + nodes.push_back(pNode2); + return Kratos::make_shared(nodes); + } + + AdjointElement(const NodesArrayType& ThisNodes) + : Element(0, ThisNodes), mPrimalElement(ThisNodes) + { + SetValue(ADJOINT_EXTENSIONS, Kratos::make_shared(this)); + } + + void EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& rCurrentProcessInfo) override + { + rResult.resize(2); + rResult[0] = this->GetGeometry()[0].GetDof(ADJOINT_VECTOR_1_X).EquationId(); + rResult[1] = this->GetGeometry()[1].GetDof(ADJOINT_VECTOR_1_X).EquationId(); + } + + void GetDofList(DofsVectorType& rElementalDofList, ProcessInfo& rCurrentProcessInfo) override + { + rElementalDofList.resize(2); + rElementalDofList[0] = this->GetGeometry()[0].pGetDof(ADJOINT_VECTOR_1_X); + rElementalDofList[1] = this->GetGeometry()[1].pGetDof(ADJOINT_VECTOR_1_X); + } + + void GetValuesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(ADJOINT_VECTOR_1_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(ADJOINT_VECTOR_1_X, Step); + } + + void GetFirstDerivativesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(ADJOINT_VECTOR_2_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(ADJOINT_VECTOR_2_X, Step); + } + + void GetSecondDerivativesVector(Vector& values, int Step = 0) override + { + values.resize(2); + values[0] = this->GetGeometry()[0].FastGetSolutionStepValue(ADJOINT_VECTOR_3_X, Step); + values[1] = this->GetGeometry()[1].FastGetSolutionStepValue(ADJOINT_VECTOR_3_X, Step); + } + + void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo) override + { + mPrimalElement.CalculateLeftHandSide(rLeftHandSideMatrix, rCurrentProcessInfo); + noalias(rLeftHandSideMatrix) = -rLeftHandSideMatrix; + } + + void CalculateFirstDerivativesLHS(MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo) override + { + KRATOS_TRY; + mPrimalElement.CalculateDampingMatrix(rLeftHandSideMatrix, rCurrentProcessInfo); + noalias(rLeftHandSideMatrix) = -rLeftHandSideMatrix; + KRATOS_CATCH(""); + } + + void CalculateSecondDerivativesLHS(MatrixType& rLeftHandSideMatrix, + ProcessInfo& rCurrentProcessInfo) override + { + KRATOS_TRY; + mPrimalElement.CalculateMassMatrix(rLeftHandSideMatrix, rCurrentProcessInfo); + noalias(rLeftHandSideMatrix) = -rLeftHandSideMatrix; + KRATOS_CATCH(""); + } + + void CalculateSensitivityMatrix(const Variable& rDesignVariable, + Matrix& rOutput, + const ProcessInfo& rCurrentProcessInfo) override + { + KRATOS_TRY; + if (rDesignVariable == SCALAR_SENSITIVITY) + { + rOutput.resize(1, 2, false); + const double& x1 = this->GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT_X); + const double& x2 = this->GetGeometry()[1].FastGetSolutionStepValue(DISPLACEMENT_X); + const double x21 = x2 - x1; + rOutput(0, 0) = -(x1 * x1 * x1 - x21 * x21 * x21); + rOutput(0, 1) = -(x21 * x21 * x21); + } + else + { + KRATOS_ERROR << "Invalid variable: " << rDesignVariable << std::endl; + } + KRATOS_CATCH(""); + } + + ///@} + +private: + PrimalElement mPrimalElement; +}; + +class ResponseFunction : public AdjointResponseFunction +{ + public: + KRATOS_CLASS_POINTER_DEFINITION(ResponseFunction); + + ResponseFunction(ModelPart& rModelPart) : mrModelPart(rModelPart) + { + } + + void CalculateGradient(const Element& rAdjointElement, + const Matrix& rResidualGradient, + Vector& rResponseGradient, + const ProcessInfo& rProcessInfo) override + { + rResponseGradient.resize(2, false); + rResponseGradient(0) = 2. * rAdjointElement.GetGeometry()[0].FastGetSolutionStepValue(DISPLACEMENT_X); + rResponseGradient(1) = 2. * rAdjointElement.GetGeometry()[1].FastGetSolutionStepValue(DISPLACEMENT_X); + } + + void CalculateFirstDerivativesGradient(const Element& rAdjointElement, + const Matrix& rResidualGradient, + Vector& rResponseGradient, + const ProcessInfo& rProcessInfo) override + { + rResponseGradient.resize(2, false); + rResponseGradient(0) = 2. * rAdjointElement.GetGeometry()[0].FastGetSolutionStepValue(VELOCITY_X); + rResponseGradient(1) = 2. * rAdjointElement.GetGeometry()[1].FastGetSolutionStepValue(VELOCITY_X); + } + + void CalculateSecondDerivativesGradient(const Element& rAdjointElement, + const Matrix& rResidualGradient, + Vector& rResponseGradient, + const ProcessInfo& rProcessInfo) override + { + rResponseGradient.resize(2, false); + rResponseGradient(0) = 0.; + rResponseGradient(1) = 0.; + } + + void CalculatePartialSensitivity(Element& rAdjointElement, + const Variable& rVariable, + const Matrix& rSensitivityMatrix, + Vector& rSensitivityGradient, + const ProcessInfo& rProcessInfo) override + { + rSensitivityGradient.resize(1, false); + rSensitivityGradient(0) = 0.; + } + + void CalculatePartialSensitivity(Element& rAdjointElement, + const Variable>& rVariable, + const Matrix& rSensitivityMatrix, + Vector& rSensitivityGradient, + const ProcessInfo& rProcessInfo) override + { + rSensitivityGradient.resize(1, false); + rSensitivityGradient(0) = 0.; + } + + double CalculateValue(ModelPart& rModelPart) override + { + const double& x1 = + mrModelPart.GetNode(1).FastGetSolutionStepValue(DISPLACEMENT_X); + const double& x2 = + mrModelPart.GetNode(2).FastGetSolutionStepValue(DISPLACEMENT_X); + const double& v1 = mrModelPart.GetNode(1).FastGetSolutionStepValue(VELOCITY_X); + const double& v2 = mrModelPart.GetNode(2).FastGetSolutionStepValue(VELOCITY_X); + return x1 * x1 + x2 * x2 + v1 * v1 + v2 * v2; + } + + private: + ModelPart& mrModelPart; +}; + +struct PrimalResults : Base::PrimalResults +{ + std::vector time; + std::vector x1; + std::vector x2; + std::vector v1; + std::vector v2; + std::vector a1; + std::vector a2; + + void StoreCurrentSolutionStep(const ModelPart& rModelPart) override + { + this->time.push_back(rModelPart.GetProcessInfo()[TIME]); + auto& node1 = rModelPart.GetNode(1); + auto& node2 = rModelPart.GetNode(2); + this->x1.push_back(node1.FastGetSolutionStepValue(DISPLACEMENT_X)); + this->v1.push_back(node1.FastGetSolutionStepValue(VELOCITY_X)); + const double acc1 = + (1. - AlphaBossak) * node1.FastGetSolutionStepValue(ACCELERATION_X) + + AlphaBossak * node1.FastGetSolutionStepValue(ACCELERATION_X, 1); + this->a1.push_back(acc1); + this->x2.push_back(node2.FastGetSolutionStepValue(DISPLACEMENT_X)); + this->v2.push_back(node2.FastGetSolutionStepValue(VELOCITY_X)); + const double acc2 = + (1. - AlphaBossak) * node2.FastGetSolutionStepValue(ACCELERATION_X) + + AlphaBossak * node2.FastGetSolutionStepValue(ACCELERATION_X, 1); + this->a2.push_back(acc2); + } + + void LoadCurrentSolutionStep(ModelPart& rModelPart) const override + { + const double current_time = rModelPart.GetProcessInfo()[TIME]; + if (current_time < 1e-8 || current_time > this->time.back() + 1e-8) + { + std::stringstream ss; + ss << "Adjoint time = " << current_time + << " outside of primal solution time range!\n"; + throw std::runtime_error{ss.str()}; + } + auto it = std::find_if( + this->time.begin(), this->time.end(), + [current_time](const double& t) -> bool { return current_time <= t; }); + std::size_t pos = it - this->time.begin(); + if (pos == this->time.size()) + { + --pos; + } + else if (pos > 0) + { + const auto t0 = this->time.at(pos - 1); + const auto t1 = this->time.at(pos); + if (std::abs(current_time - t0) < 1e-8) + { + pos = pos - 1; + } + else if (!(std::abs(current_time - t1) < 1e-8)) + { + std::stringstream ss; + ss << "Adjoint time = " << current_time + << " does not match primal solution time!\n"; + throw std::runtime_error{ss.str()}; + } + } + auto& node1 = rModelPart.GetNode(1); + auto& node2 = rModelPart.GetNode(2); + node1.FastGetSolutionStepValue(DISPLACEMENT_X) = this->x1.at(pos); + node1.FastGetSolutionStepValue(VELOCITY_X) = this->v1.at(pos); + node1.FastGetSolutionStepValue(ACCELERATION_X) = this->a1.at(pos); + node2.FastGetSolutionStepValue(DISPLACEMENT_X) = this->x2.at(pos); + node2.FastGetSolutionStepValue(VELOCITY_X) = this->v2.at(pos); + node2.FastGetSolutionStepValue(ACCELERATION_X) = this->a2.at(pos); + } +}; + +void InitializePrimalModelPart(ModelPart& rModelPart) +{ + rModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + rModelPart.AddNodalSolutionStepVariable(REACTION); + rModelPart.AddNodalSolutionStepVariable(VELOCITY); + rModelPart.AddNodalSolutionStepVariable(ACCELERATION); + rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); + rModelPart.CreateNewNode(2, 0.0, 0.0, 0.0); + rModelPart.SetBufferSize(2); + for (auto& r_node : rModelPart.Nodes()) + { + r_node.AddDof(DISPLACEMENT_X, REACTION_X); + } + auto p_element = + PrimalElement::Create(rModelPart.pGetNode(1), rModelPart.pGetNode(2)); + rModelPart.AddElement(p_element); + auto& node1 = rModelPart.GetNode(1); + auto& node2 = rModelPart.GetNode(2); + node2.FastGetSolutionStepValue(DISPLACEMENT_X) = 1.0; + node1.FastGetSolutionStepValue(ACCELERATION_X) = 2.0; + node2.FastGetSolutionStepValue(ACCELERATION_X) =-2.0; +} + +void InitializeAdjointModelPart(ModelPart& rModelPart) +{ + rModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + rModelPart.AddNodalSolutionStepVariable(REACTION); + rModelPart.AddNodalSolutionStepVariable(VELOCITY); + rModelPart.AddNodalSolutionStepVariable(ACCELERATION); + rModelPart.AddNodalSolutionStepVariable(ADJOINT_VECTOR_1); + rModelPart.AddNodalSolutionStepVariable(ADJOINT_VECTOR_2); + rModelPart.AddNodalSolutionStepVariable(ADJOINT_VECTOR_3); + rModelPart.AddNodalSolutionStepVariable(AUX_ADJOINT_VECTOR_1); + rModelPart.AddNodalSolutionStepVariable(SCALAR_SENSITIVITY); + rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); + rModelPart.CreateNewNode(2, 0.0, 0.0, 0.0); + rModelPart.SetBufferSize(2); + for (auto& r_node : rModelPart.Nodes()) + { + r_node.AddDof(ADJOINT_VECTOR_1_X); + } + auto p_adjoint_element = + AdjointElement::Create(rModelPart.pGetNode(1), rModelPart.pGetNode(2)); + rModelPart.AddElement(p_adjoint_element); +} + +} + +} // unnamed namespace + +KRATOS_TEST_CASE_IN_SUITE(ResidualBasedAdjointBossak_TwoMassSpringDamperSystem, KratosCoreFastSuite) +{ + namespace Nlsmd = NonLinearSpringMassDamper; + // Solve the primal problem. + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("test"); + + Nlsmd::InitializePrimalModelPart(model_part); + auto p_results_data = Kratos::make_shared(); + Base::PrimalStrategy solver(model_part, p_results_data); + solver.Initialize(); + const double end_time = 0.1; + const double start_time = 0.; + const std::size_t N = 5; + const double delta_time = (end_time - start_time) / N; + model_part.CloneTimeStep(start_time - delta_time); + model_part.CloneTimeStep(start_time); + for (double current_time = start_time; current_time < end_time;) + { + current_time += delta_time; + model_part.CloneTimeStep(current_time); + solver.Solve(); + } + + // Solve the adjoint problem. + ModelPart& adjoint_model_part = current_model.CreateModelPart("test_adjoint"); + + Nlsmd::InitializeAdjointModelPart(adjoint_model_part); + auto p_response_function = + Kratos::make_shared(adjoint_model_part); + Base::AdjointStrategy adjoint_solver(adjoint_model_part, p_results_data, p_response_function); + adjoint_solver.Initialize(); + SensitivityBuilder sensitivity_builder( + Parameters{R"({ "element_data_sensitivity_variables": ["SCALAR_SENSITIVITY"] })"}, + adjoint_model_part, p_response_function); + sensitivity_builder.Initialize(); + adjoint_model_part.CloneTimeStep(end_time + 2. * delta_time); + adjoint_model_part.CloneTimeStep(end_time + delta_time); + for (double current_time = end_time + delta_time; current_time >= start_time + 1.5 * delta_time;) + { + current_time -= delta_time; + adjoint_model_part.CloneTimeStep(current_time); + adjoint_solver.Solve(); + sensitivity_builder.UpdateSensitivities(); + } + + // Check. + const double adjoint_sensitivity = adjoint_model_part.Elements().front().GetValue(SCALAR_SENSITIVITY); + const double fd_sensitivity = (1.0251139877e-01 - 1.0251114465e-01) / 1.e-4; + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(1).FastGetSolutionStepValue(ADJOINT_VECTOR_1_X), 2.1808885528e-02, 1e-6); + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(2).FastGetSolutionStepValue(ADJOINT_VECTOR_1_X), -1.3753669361e-02, 1e-6); + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(1).FastGetSolutionStepValue(ADJOINT_VECTOR_2_X), -1.1404210281, 1e-6); + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(2).FastGetSolutionStepValue(ADJOINT_VECTOR_2_X), 7.5552893007e-01, 1e-6); + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(1).FastGetSolutionStepValue(ADJOINT_VECTOR_3_X), 1.8155023724e-02, 1e-6); + KRATOS_CHECK_NEAR(adjoint_model_part.GetNode(2).FastGetSolutionStepValue(ADJOINT_VECTOR_3_X), -1.0319132594e-02, 1e-6); + KRATOS_CHECK_NEAR(adjoint_sensitivity, fd_sensitivity, 1e-7); +} +} +} diff --git a/kratos/tests/cpp_tests/strategies/schemes/test_schemes.cpp b/kratos/tests/cpp_tests/strategies/schemes/test_schemes.cpp new file mode 100644 index 000000000000..927e9e260400 --- /dev/null +++ b/kratos/tests/cpp_tests/strategies/schemes/test_schemes.cpp @@ -0,0 +1,296 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes +#include + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" + + +// Utility includes +#include "includes/define.h" +#include "includes/model_part.h" +#include "spaces/ublas_space.h" +#include "solving_strategies/schemes/residual_based_newmark_displacement_scheme.hpp" +#include "solving_strategies/schemes/residual_based_bossak_displacement_scheme.hpp" +#include "solving_strategies/schemes/residual_based_bdf_displacement_scheme.h" + +namespace Kratos +{ + namespace Testing + { + /// Tests + + typedef UblasSpace SparseSpaceType; + typedef UblasSpace LocalSpaceType; + + typedef Scheme< SparseSpaceType, LocalSpaceType > SchemeType; + typedef PointerVectorSet, SetIdentityFunction>, std::less>::result_type>, std::equal_to>::result_type>, Dof* > DofsArrayType; + + static inline DofsArrayType BasicTestSchemeDisplacement( + ModelPart& ModelPart, + SchemeType::Pointer pScheme, + std::vector< Dof::Pointer >& DoF, + const double DeltaTime + ) + { + ModelPart.SetBufferSize(3); + + ModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + ModelPart.AddNodalSolutionStepVariable(VELOCITY); + ModelPart.AddNodalSolutionStepVariable(ACCELERATION); + + auto pnode = ModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); + + pnode->AddDof(DISPLACEMENT_X); + pnode->AddDof(DISPLACEMENT_Y); + pnode->AddDof(DISPLACEMENT_Z); + + ModelPart.GetProcessInfo()[DELTA_TIME] = DeltaTime; + + DoF.reserve(3); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_X)); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_Y)); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_Z)); + + // Set initial solution + const array_1d zero_vector = ZeroVector(3); + pnode->FastGetSolutionStepValue(DISPLACEMENT) = zero_vector; + pnode->FastGetSolutionStepValue(DISPLACEMENT, 1) = zero_vector; + pnode->FastGetSolutionStepValue(DISPLACEMENT, 2) = zero_vector; + pnode->FastGetSolutionStepValue(VELOCITY) = zero_vector; + pnode->FastGetSolutionStepValue(VELOCITY, 1) = zero_vector; + pnode->FastGetSolutionStepValue(VELOCITY, 2) = zero_vector; + pnode->FastGetSolutionStepValue(ACCELERATION) = zero_vector; + pnode->FastGetSolutionStepValue(ACCELERATION, 1) = zero_vector; + pnode->FastGetSolutionStepValue(ACCELERATION, 2) = zero_vector; + + DofsArrayType Doftemp; + Doftemp.reserve(DoF.size()); + for (auto it= DoF.begin(); it!= DoF.end(); it++) + { + Doftemp.push_back( it->get() ); + } + Doftemp.Sort(); + + CompressedMatrix A(boost::numeric::ublas::zero_matrix(3, 3)); + Vector Dx = ZeroVector(3); + Vector b = ZeroVector(3); + + pScheme->Initialize(ModelPart); + + return Doftemp; + } + + /** + * Checks if the Newmark scheme performs correctly the integration + */ + + KRATOS_TEST_CASE_IN_SUITE(DisplacementNewmarkSchemeTest, KratosCoreFastSuite) + { + Model current_model; + + constexpr double tolerance = 1e-6; + + ModelPart& model_part = current_model.CreateModelPart("Main"); + + typedef ResidualBasedNewmarkDisplacementScheme< SparseSpaceType, LocalSpaceType > ResidualBasedNewmarkDisplacementSchemeType; + SchemeType::Pointer pscheme = SchemeType::Pointer( new ResidualBasedNewmarkDisplacementSchemeType() ); + + const double delta_time = 1.0e-4; + + std::vector< Dof::Pointer > DoF; + DofsArrayType Doftemp = BasicTestSchemeDisplacement(model_part, pscheme, DoF, delta_time); + + CompressedMatrix A = boost::numeric::ublas::zero_matrix(3, 3); + Vector Dx = ZeroVector(3); + Vector b = ZeroVector(3); + + double time = 0; + + Node<3>::Pointer pnode = model_part.pGetNode(1); + + pnode->FastGetSolutionStepValue(DISPLACEMENT_X) = std::cos(time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 1) = std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 2) = std::cos(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X) = -std::sin(time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 1) = -std::sin(time - delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 2) = -std::sin(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X) = -std::cos(time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 1) = -std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 2) = -std::cos(time - 2.0 * delta_time); + + pscheme->Initialize(model_part); + + const unsigned int number_iterations = 10; + for (unsigned int iter = 0; iter < number_iterations; ++iter) + { + time += delta_time; + + model_part.CloneTimeStep(time); + + Dx[0] = std::cos(time) - std::cos(time - delta_time); + + pscheme->InitializeSolutionStep(model_part, A, Dx, b); + pscheme->Update(model_part, Doftemp, A, Dx, b); + + const double x = pnode->FastGetSolutionStepValue(DISPLACEMENT_X); + const double v = pnode->FastGetSolutionStepValue(VELOCITY_X); + const double a = pnode->FastGetSolutionStepValue(ACCELERATION_X); + +// // Debug +// std::cout << time << "\t" << x << "\t" << v << "\t" << a << std::endl; + + KRATOS_CHECK_LESS_EQUAL(std::abs(x - std::cos(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(v + std::sin(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(a + std::cos(time)), tolerance); + } + } + + /** + * Checks if the Bossak scheme performs correctly the integration + */ + + KRATOS_TEST_CASE_IN_SUITE(DisplacementBossakSchemeTest, KratosCoreFastSuite) + { + Model current_model; + + constexpr double tolerance = 1e-6; + + ModelPart& model_part = current_model.CreateModelPart("Main"); + + typedef ResidualBasedBossakDisplacementScheme< SparseSpaceType, LocalSpaceType > ResidualBasedBossakDisplacementSchemeType; + SchemeType::Pointer pscheme = SchemeType::Pointer( new ResidualBasedBossakDisplacementSchemeType() ); + + const double delta_time = 1.0e-4; + + std::vector< Dof::Pointer > DoF; + DofsArrayType Doftemp = BasicTestSchemeDisplacement(model_part, pscheme, DoF, delta_time); + + CompressedMatrix A = boost::numeric::ublas::zero_matrix(3, 3); + Vector Dx = ZeroVector(3); + Vector b = ZeroVector(3); + + double time = 0; + + Node<3>::Pointer pnode = model_part.pGetNode(1); + + pnode->FastGetSolutionStepValue(DISPLACEMENT_X) = std::cos(time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 1) = std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 2) = std::cos(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X) = -std::sin(time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 1) = -std::sin(time - delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 2) = -std::sin(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X) = -std::cos(time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 1) = -std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 2) = -std::cos(time - 2.0 * delta_time); + + pscheme->Initialize(model_part); + + const unsigned int number_iterations = 10; + for (unsigned int iter = 0; iter < number_iterations; ++iter) + { + time += delta_time; + + model_part.CloneTimeStep(time); + + Dx[0] = std::cos(time) - std::cos(time - delta_time); + + pscheme->InitializeSolutionStep(model_part, A, Dx, b); + pscheme->Update(model_part, Doftemp, A, Dx, b); + + const double x = pnode->FastGetSolutionStepValue(DISPLACEMENT_X); + const double v = pnode->FastGetSolutionStepValue(VELOCITY_X); + const double a = pnode->FastGetSolutionStepValue(ACCELERATION_X); + +// // Debug +// std::cout << time << "\t" << x << "\t" << v << "\t" << a << std::endl; + + KRATOS_CHECK_LESS_EQUAL(std::abs(x - std::cos(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(v + std::sin(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(a + std::cos(time)), tolerance); + } + } + + /** + * Checks if the BDF2 scheme performs correctly the integration + */ + + KRATOS_TEST_CASE_IN_SUITE(DisplacementBDF2SchemeTest, KratosCoreFastSuite) + { + Model current_model; + + constexpr double tolerance = 1e-6; + + ModelPart& model_part = current_model.CreateModelPart("Main"); + + typedef ResidualBasedBDFDisplacementScheme< SparseSpaceType, LocalSpaceType > ResidualBasedBDFDisplacementSchemeType; + SchemeType::Pointer pscheme = SchemeType::Pointer( new ResidualBasedBDFDisplacementSchemeType(2) ); + + const double delta_time = 1.0e-4; + + std::vector< Dof::Pointer > DoF; + DofsArrayType Doftemp = BasicTestSchemeDisplacement(model_part, pscheme, DoF, delta_time); + + CompressedMatrix A = boost::numeric::ublas::zero_matrix(3, 3); + Vector Dx = ZeroVector(3); + Vector b = ZeroVector(3); + + double time = 0; + + Node<3>::Pointer pnode = model_part.pGetNode(1); + + pnode->FastGetSolutionStepValue(DISPLACEMENT_X) = std::cos(time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 1) = std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(DISPLACEMENT_X, 2) = std::cos(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X) = -std::sin(time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 1) = -std::sin(time - delta_time); + pnode->FastGetSolutionStepValue(VELOCITY_X, 2) = -std::sin(time - 2.0 * delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X) = -std::cos(time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 1) = -std::cos(time - delta_time); + pnode->FastGetSolutionStepValue(ACCELERATION_X, 2) = -std::cos(time - 2.0 * delta_time); + + pscheme->Initialize(model_part); + + const unsigned int number_iterations = 10; + for (unsigned int iter = 0; iter < number_iterations; ++iter) + { + time += delta_time; + + model_part.CloneTimeStep(time); + + Dx[0] = std::cos(time) - std::cos(time - delta_time); + + pscheme->InitializeSolutionStep(model_part, A, Dx, b); + pscheme->Update(model_part, Doftemp, A, Dx, b); + + const double x = pnode->FastGetSolutionStepValue(DISPLACEMENT_X); + const double v = pnode->FastGetSolutionStepValue(VELOCITY_X); + const double a = pnode->FastGetSolutionStepValue(ACCELERATION_X); + +// // Debug +// std::cout << time << "\t" << x << "\t" << v << "\t" << a << std::endl; + + KRATOS_CHECK_LESS_EQUAL(std::abs(x - std::cos(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(v + std::sin(time)), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(a + std::cos(time)), tolerance); + } + } + + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/strategies/strategies/test_strategies.cpp b/kratos/tests/cpp_tests/strategies/strategies/test_strategies.cpp new file mode 100755 index 000000000000..5d1cf5880bee --- /dev/null +++ b/kratos/tests/cpp_tests/strategies/strategies/test_strategies.cpp @@ -0,0 +1,223 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +/* External includes */ + +/* Project includes */ +#include "testing/testing.h" + +/* Utility includes */ +#include "includes/define.h" +#include "containers/model.h" +#include "includes/model_part.h" +#include "spaces/ublas_space.h" + +/* Element include */ +#include "tests/cpp_tests/auxiliar_files/test_element.h" + +// Linear solvers +#include "linear_solvers/reorderer.h" +#include "linear_solvers/direct_solver.h" +#include "linear_solvers/linear_solver.h" +#include "linear_solvers/skyline_lu_factorization_solver.h" + +// The most basic scheme (static) +#include "solving_strategies/schemes/residualbased_incrementalupdate_static_scheme.h" + +// The most extended criteria (residual criteria) +#include "solving_strategies/convergencecriterias/residual_criteria.h" + +// The most builder and solver (the block builder and solver) +#include "solving_strategies/convergencecriterias/residual_criteria.h" + +// The strategies to test +#include "solving_strategies/strategies/residualbased_linear_strategy.h" +#include "solving_strategies/strategies/residualbased_newton_raphson_strategy.h" + +namespace Kratos +{ + namespace Testing + { + /// Tests + // NOTE: The strategies test many things simulataneously + // TODO: Create test for the other components + typedef Node<3> NodeType; + typedef Geometry GeometryType; + typedef UblasSpace SparseSpaceType; + typedef UblasSpace LocalSpaceType; + + // The direct solver + typedef Reorderer ReordererType; + typedef DirectSolver DirectSolverType; + typedef LinearSolver LinearSolverType; + typedef SkylineLUFactorizationSolver SkylineLUFactorizationSolverType; + + // The convergence criteria type + typedef ConvergenceCriteria< SparseSpaceType, LocalSpaceType > ConvergenceCriteriaType; + typedef ResidualCriteria< SparseSpaceType, LocalSpaceType > ResidualCriteriaType; + + // The builder ans solver type + typedef BuilderAndSolver< SparseSpaceType, LocalSpaceType, LinearSolverType > BuilderAndSolverType; + typedef ResidualBasedBlockBuilderAndSolver< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedBlockBuilderAndSolverType; + + // The time scheme + typedef Scheme< SparseSpaceType, LocalSpaceType > SchemeType; + typedef ResidualBasedIncrementalUpdateStaticScheme< SparseSpaceType, LocalSpaceType> ResidualBasedIncrementalUpdateStaticSchemeType; + + // The strategies + typedef SolvingStrategy SolvingStrategyType; + typedef ResidualBasedLinearStrategy< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedLinearStrategyType; + typedef ResidualBasedNewtonRaphsonStrategy< SparseSpaceType, LocalSpaceType, LinearSolverType > ResidualBasedNewtonRaphsonStrategyType; + + // Dof arrays + typedef PointerVectorSet, SetIdentityFunction>, std::less>::result_type>, std::equal_to>::result_type>, Dof* > DofsArrayType; + + typedef TestElement::ResidualType ResidualType; + + static inline DofsArrayType BasicTestStrategyDisplacement( + ModelPart& ModelPart, + const ResidualType ThisResidualType + ) + { + ModelPart.SetBufferSize(3); + + ModelPart.AddNodalSolutionStepVariable(DISPLACEMENT); + ModelPart.AddNodalSolutionStepVariable(REACTION); + ModelPart.AddNodalSolutionStepVariable(VELOCITY); + ModelPart.AddNodalSolutionStepVariable(ACCELERATION); + + NodeType::Pointer pnode = ModelPart.CreateNewNode(1, 0.0, 0.0, 0.0); + std::vector geom(1); + geom[0] = pnode; + GeometryType::Pointer pgeom = Kratos::make_shared(PointerVector{geom}); + Element::Pointer pelem = Kratos::make_shared(1, pgeom, ThisResidualType); + ModelPart.AddElement(pelem); + + pnode->AddDof(DISPLACEMENT_X, REACTION_X); + pnode->AddDof(DISPLACEMENT_Y, REACTION_Y); + pnode->AddDof(DISPLACEMENT_Z, REACTION_Z); + + std::vector< Dof::Pointer > DoF; + DoF.reserve(3); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_X)); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_Y)); + DoF.push_back(pnode->pGetDof(DISPLACEMENT_Z)); + + // Set initial solution + (pnode->FastGetSolutionStepValue(DISPLACEMENT)).clear(); + (pnode->FastGetSolutionStepValue(DISPLACEMENT, 1)).clear(); + (pnode->FastGetSolutionStepValue(DISPLACEMENT, 2)).clear(); + + DofsArrayType Doftemp; + Doftemp.reserve(DoF.size()); + for (auto it= DoF.begin(); it!= DoF.end(); it++) + Doftemp.push_back( it->get() ); + + Doftemp.Sort(); + + return Doftemp; + } + + /** + * Checks if the Linear strategy performs correctly the resolution of the system + */ + + KRATOS_TEST_CASE_IN_SUITE(DisplacementLinearStrategy, KratosCoreFastSuite) + { + Model current_model; + + constexpr double tolerance = 1e-6; + + ModelPart& model_part = current_model.CreateModelPart("Main"); + + SchemeType::Pointer pscheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer psolver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + BuilderAndSolverType::Pointer pbuildandsolve = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverType(psolver) ); + + SolvingStrategyType::Pointer pstrategy = SolvingStrategyType::Pointer( new ResidualBasedLinearStrategyType(model_part, pscheme, psolver, pbuildandsolve, true)); + + DofsArrayType Doftemp = BasicTestStrategyDisplacement(model_part, ResidualType::LINEAR); + + NodeType::Pointer pnode = model_part.pGetNode(1); + + double time = 0.0; + const double delta_time = 1.0e-4; + const unsigned int number_iterations = 1; + for (unsigned int iter = 0; iter < number_iterations; ++iter) { + time += delta_time; + + model_part.CloneTimeStep(time); + + pstrategy->SetEchoLevel(0); + pstrategy->Solve(); + + for (auto it= Doftemp.begin(); it!= Doftemp.end(); it++) { + KRATOS_CHECK_LESS_EQUAL(std::abs(it->GetSolutionStepValue() - 1.0), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(it->GetSolutionStepReactionValue()), tolerance); + } + } + } + + /** + * Checks if the Newton Rapshon strategy performs correctly the resolution of the system + */ + + KRATOS_TEST_CASE_IN_SUITE(DisplacementNRStrategy, KratosCoreFastSuite) + { + Model current_model; + + constexpr double tolerance = 1e-6; + + ModelPart& model_part = current_model.CreateModelPart("Main"); + + SchemeType::Pointer pscheme = SchemeType::Pointer( new ResidualBasedIncrementalUpdateStaticSchemeType() ); + LinearSolverType::Pointer psolver = LinearSolverType::Pointer( new SkylineLUFactorizationSolverType() ); + ConvergenceCriteriaType::Pointer pcriteria = ConvergenceCriteriaType::Pointer( new ResidualCriteriaType(1.0e-4, 1.0e-9) ); + BuilderAndSolverType::Pointer pbuildandsolve = BuilderAndSolverType::Pointer( new ResidualBasedBlockBuilderAndSolverType(psolver) ); + + SolvingStrategyType::Pointer pstrategy = SolvingStrategyType::Pointer( new ResidualBasedNewtonRaphsonStrategyType(model_part, pscheme, psolver, pcriteria, pbuildandsolve, 10, true)); + + DofsArrayType Doftemp = BasicTestStrategyDisplacement(model_part, ResidualType::NON_LINEAR); + + NodeType::Pointer pnode = model_part.pGetNode(1); + + double time = 0.0; + const double delta_time = 1.0e-4; + const unsigned int number_iterations = 1; + for (unsigned int iter = 0; iter < number_iterations; ++iter) { + time += delta_time; + + model_part.CloneTimeStep(time); + + array_1d init_vector; + init_vector[0] = 0.5; + init_vector[1] = 0.5; + init_vector[2] = 0.5; + pnode->FastGetSolutionStepValue(DISPLACEMENT) = init_vector; + + pcriteria->SetEchoLevel(0); + pstrategy->SetEchoLevel(0); + pstrategy->Solve(); + + for (auto it= Doftemp.begin(); it!= Doftemp.end(); it++) { + KRATOS_CHECK_LESS_EQUAL(std::abs(it->GetSolutionStepValue() - 1.0), tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(it->GetSolutionStepReactionValue()), tolerance); + } + } + } + + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/testing/test_testing.cpp b/kratos/tests/cpp_tests/testing/test_testing.cpp new file mode 100644 index 000000000000..fe6656b6237f --- /dev/null +++ b/kratos/tests/cpp_tests/testing/test_testing.cpp @@ -0,0 +1,35 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Pooyan Dadvand +// +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(TestSuite, KratosCoreFastSuite) { + Tester::CreateTestSuite("MyTestTestSuite"); + KRATOS_TESTING_ADD_TEST_TO_TEST_SUITE("TestTestSuite", "MyTestTestSuite"); + + std::stringstream info; + info << Tester::GetTestSuite("MyTestTestSuite"); + KRATOS_CHECK_NOT_EQUAL( + info.str().find("MyTestTestSuite"), std::string::npos); +} +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_assign_unique_model_part_collection_tag_utility.cpp b/kratos/tests/cpp_tests/utilities/test_assign_unique_model_part_collection_tag_utility.cpp new file mode 100644 index 000000000000..b10ea8b1a8ed --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_assign_unique_model_part_collection_tag_utility.cpp @@ -0,0 +1,339 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "geometries/triangle_2d_3.h" +#include "testing/testing.h" +#include "includes/kratos_flags.h" + +/* Utilities */ +#include "utilities/assign_unique_model_part_collection_tag_utility.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + typedef std::size_t IndexSize; + typedef std::unordered_map IndexIndexMapType; + typedef std::unordered_map> IndexStringMapType; + + /** + * Checks the correct work of the sub modelparts list utility + */ + + KRATOS_TEST_CASE_IN_SUITE(AssignUniqueModelPartCollectionTagUtility, KratosCoreFastSuite) + { + + // Creating the reference model part and the relative submodelparts non alphabetically ordered + Model current_model; + ModelPart& first_model_part = current_model.CreateModelPart("Main"); + ModelPart& first_sub_modelpart_1 = first_model_part.CreateSubModelPart("BSubModelPart1"); + ModelPart& first_sub_modelpart_2 = first_model_part.CreateSubModelPart("ASubModelPart2"); + ModelPart& first_sub_modelpart_3 = first_model_part.CreateSubModelPart("ZSubModelPart3"); + ModelPart& first_sub_modelpart_4 = first_model_part.CreateSubModelPart("YSubModelPart4"); + + // Creating the Properties + Properties::Pointer p_elem_prop = first_model_part.pGetProperties(0); + + // First we create the nodes + NodeType::Pointer p_node_1 = first_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = first_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = first_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = first_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = first_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = first_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Adding nodes to random submodelparts + first_sub_modelpart_1.AddNode(p_node_1); + first_sub_modelpart_2.AddNode(p_node_4); + first_sub_modelpart_3.AddNode(p_node_5); + first_sub_modelpart_4.AddNode(p_node_6); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = first_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = first_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = first_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = first_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); + + // Adding nodes to random submodelparts + first_sub_modelpart_1.AddElement(p_elem_0); + first_sub_modelpart_2.AddElement(p_elem_3); + +// // Debug +// KRATOS_WATCH(first_model_part) + + AssignUniqueModelPartCollectionTagUtility collections_utility(first_model_part); + + IndexIndexMapType nodes_tags, conds_tags, elems_tags; + IndexStringMapType collections; + collections_utility.ComputeTags(nodes_tags, conds_tags, elems_tags, collections); + + // Creating the second model part + ModelPart& second_model_part = current_model.CreateModelPart("SecondMain"); + second_model_part.CreateSubModelPart("BSubModelPart1"); + second_model_part.CreateSubModelPart("ASubModelPart2"); + second_model_part.CreateSubModelPart("ZSubModelPart3"); + second_model_part.CreateSubModelPart("YSubModelPart4"); + + // We add the nodes and elements from the first model part + second_model_part.AddNodes(first_model_part.Nodes().begin(), first_model_part.Nodes().end()); + second_model_part.AddElements(first_model_part.Elements().begin(), first_model_part.Elements().end()); + + for (auto & nodes_tag : nodes_tags) { + const IndexSize id = nodes_tag.first; + NodeType::Pointer p_node = second_model_part.pGetNode(id); + const IndexSize key = nodes_tag.second; + if (key != 0) {// NOTE: key == 0 is the MainModelPart + if (collections.find(key) != collections.end()) { + for (auto sub_model_part_name : collections[key]) { + ModelPart& r_sub_model_part = second_model_part.GetSubModelPart(sub_model_part_name); + r_sub_model_part.AddNode(p_node); + } + } + } + } + for (auto & elems_tag : elems_tags) { + const IndexSize id = elems_tag.first; + ElementType::Pointer p_elem = second_model_part.pGetElement(id); + const IndexSize key = elems_tag.second; + if (key != 0) {// NOTE: key == 0 is the MainModelPart + if (collections.find(key) != collections.end()) { + for (auto sub_model_part_name : collections[key]) { + ModelPart& r_sub_model_part = second_model_part.GetSubModelPart(sub_model_part_name); + r_sub_model_part.AddElement(p_elem); + } + } + } + } + + + std::vector sub_model_parts_names = first_model_part.GetSubModelPartNames(); + for (auto& sub_model_part_name : sub_model_parts_names) { + ModelPart& r_first_sub_model_part = first_model_part.GetSubModelPart(sub_model_part_name); + ModelPart& r_second_sub_model_part = second_model_part.GetSubModelPart(sub_model_part_name); + KRATOS_CHECK_EQUAL(r_first_sub_model_part.NumberOfNodes(), r_second_sub_model_part.NumberOfNodes()); + KRATOS_CHECK_EQUAL(r_first_sub_model_part.NumberOfElements(), r_second_sub_model_part.NumberOfElements()); + + for (IndexType i = 0; i < r_first_sub_model_part.NumberOfNodes(); i++) { + auto it_first_node = r_first_sub_model_part.Nodes().begin() + i; + auto it_found_second_node = r_second_sub_model_part.Nodes().find(it_first_node->Id()); + KRATOS_CHECK_NOT_EQUAL(it_found_second_node, r_second_sub_model_part.NodesEnd()); + } + for (IndexType i = 0; i < r_first_sub_model_part.NumberOfElements(); i++) { + auto it_first_elem = r_first_sub_model_part.Elements().begin() + i; + auto it_found_second_elem = r_second_sub_model_part.Elements().find(it_first_elem->Id()); + KRATOS_CHECK_NOT_EQUAL(it_found_second_elem, r_second_sub_model_part.ElementsEnd()); + } + } + } + + + /** + * Checks the correct work of the model parts collections utility (with different sublevels of modelparts) + */ + KRATOS_TEST_CASE_IN_SUITE(AssignUniqueModelPartCollectionTagUtilityWithSubLevels, KratosCoreFastSuite) + { + // Creating the reference model part and the relative submodelparts + Model current_model; + ModelPart& first_model_part = current_model.CreateModelPart("Main"); + ModelPart& first_sub_modelpart_1 = first_model_part.CreateSubModelPart("BSubModelPart1"); + ModelPart& first_sub_modelpart_1a = first_sub_modelpart_1.CreateSubModelPart("SubModelPart1a"); + ModelPart& first_sub_modelpart_1b = first_sub_modelpart_1.CreateSubModelPart("SubModelPart1b"); + ModelPart& first_sub_modelpart_2 = first_model_part.CreateSubModelPart("ASubModelPart2"); + ModelPart& first_sub_modelpart_3 = first_model_part.CreateSubModelPart("ZSubModelPart3"); + ModelPart& first_sub_modelpart_4 = first_model_part.CreateSubModelPart("YSubModelPart4"); + + // Creating the Properties + Properties::Pointer p_elem_prop = first_model_part.pGetProperties(0); + + // First we create the nodes + NodeType::Pointer p_node_1 = first_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = first_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = first_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = first_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = first_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = first_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Adding nodes to random submodelparts + first_sub_modelpart_1.AddNode(p_node_1); + first_sub_modelpart_1a.AddNode(p_node_2); + first_sub_modelpart_1b.AddNode(p_node_3); + first_sub_modelpart_2.AddNode(p_node_4); + first_sub_modelpart_3.AddNode(p_node_5); + first_sub_modelpart_4.AddNode(p_node_6); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = first_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = first_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = first_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = first_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); + + // Adding nodes to random submodelparts + first_sub_modelpart_1.AddElement(p_elem_0); + first_sub_modelpart_1a.AddElement(p_elem_1); + first_sub_modelpart_1b.AddElement(p_elem_2); + first_sub_modelpart_2.AddElement(p_elem_3); + + AssignUniqueModelPartCollectionTagUtility collections_utility(first_model_part); + + IndexIndexMapType nodes_tags, conds_tags, elems_tags; + IndexStringMapType collections; + collections_utility.ComputeTags(nodes_tags, conds_tags, elems_tags, collections); + + // Creating the second model part + ModelPart& second_model_part = current_model.CreateModelPart("SecondMain"); + ModelPart* p_second_sub_modelpart_1 = &second_model_part.CreateSubModelPart("BSubModelPart1"); + p_second_sub_modelpart_1->CreateSubModelPart("SubModelPart1a"); + p_second_sub_modelpart_1->CreateSubModelPart("SubModelPart1b"); + second_model_part.CreateSubModelPart("ASubModelPart2"); + second_model_part.CreateSubModelPart("ZSubModelPart3"); + second_model_part.CreateSubModelPart("YSubModelPart4"); + + // We add the nodes and elements from the first model part + second_model_part.AddNodes(first_model_part.Nodes().begin(), first_model_part.Nodes().end()); + second_model_part.AddElements(first_model_part.Elements().begin(), first_model_part.Elements().end()); + + for (auto & nodes_tag : nodes_tags) { + const IndexSize id = nodes_tag.first; + NodeType::Pointer p_node = second_model_part.pGetNode(id); + const IndexSize key = nodes_tag.second; + if (key != 0) {// NOTE: key == 0 is the MainModelPart + if (collections.find(key) != collections.end()) { + for (auto sub_model_part_name : collections[key]) { + ModelPart& r_sub_model_part = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(second_model_part, sub_model_part_name); + r_sub_model_part.AddNode(p_node); + } + } + } + } + for (auto & elems_tag : elems_tags) { + const IndexSize id = elems_tag.first; + ElementType::Pointer p_elem = second_model_part.pGetElement(id); + const IndexSize key = elems_tag.second; + if (key != 0) {// NOTE: key == 0 is the MainModelPart + if (collections.find(key) != collections.end()) { + for (auto sub_model_part_name : collections[key]) { + ModelPart& r_sub_model_part = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(second_model_part, sub_model_part_name); + r_sub_model_part.AddElement(p_elem); + } + } + } + } + + std::vector sub_model_parts_names = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPartNames(first_model_part); + for (auto& sub_model_part_name : sub_model_parts_names) { + if (sub_model_part_name != first_model_part.Name()) + { + ModelPart& r_first_sub_model_part = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(first_model_part, sub_model_part_name); + ModelPart& r_second_sub_model_part = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(second_model_part, sub_model_part_name); + KRATOS_CHECK_EQUAL(r_first_sub_model_part.NumberOfNodes(), r_second_sub_model_part.NumberOfNodes()); + KRATOS_CHECK_EQUAL(r_first_sub_model_part.NumberOfElements(), r_second_sub_model_part.NumberOfElements()); + + for (IndexType i = 0; i < r_first_sub_model_part.NumberOfNodes(); i++) { + auto it_first_node = r_first_sub_model_part.Nodes().begin() + i; + auto it_found_second_node = r_second_sub_model_part.Nodes().find(it_first_node->Id()); + KRATOS_CHECK_NOT_EQUAL(it_found_second_node, r_second_sub_model_part.NodesEnd()); + } + for (IndexType i = 0; i < r_first_sub_model_part.NumberOfElements(); i++) { + auto it_first_elem = r_first_sub_model_part.Elements().begin() + i; + auto it_found_second_elem = r_second_sub_model_part.Elements().find(it_first_elem->Id()); + KRATOS_CHECK_NOT_EQUAL(it_found_second_elem, r_second_sub_model_part.ElementsEnd()); + } + } + } + } + + + /** + * Checks the correct work of the model parts collections utility static methods + */ + KRATOS_TEST_CASE_IN_SUITE(GetRecursiveSubModelPart, KratosCoreFastSuite) + { + // Creating the reference model part and the relative submodelparts + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Main"); + ModelPart& sub_modelpart_1 = model_part.CreateSubModelPart("BSubModelPart1"); + sub_modelpart_1.CreateSubModelPart("SubModelPart1a"); + sub_modelpart_1.CreateSubModelPart("SubModelPart1b"); + model_part.CreateSubModelPart("ASubModelPart2"); + model_part.CreateSubModelPart("ZSubModelPart3"); + model_part.CreateSubModelPart("YSubModelPart4"); + + // auto names = AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPartNames(model_part); + // for(auto name : names) + // KRATOS_WATCH(name); + + KRATOS_CHECK_EQUAL("Main", + AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(model_part, "Main").Name()); + KRATOS_CHECK_EQUAL("BSubModelPart1", + AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(model_part, "BSubModelPart1").Name()); + KRATOS_CHECK_EQUAL("BSubModelPart1", + AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(model_part, "Main.BSubModelPart1").Name()); + KRATOS_CHECK_EQUAL("SubModelPart1b", + AssignUniqueModelPartCollectionTagUtility::GetRecursiveSubModelPart(model_part, "BSubModelPart1.SubModelPart1b").Name()); + } + + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_binbased_fast_point_locator.cpp b/kratos/tests/cpp_tests/utilities/test_binbased_fast_point_locator.cpp new file mode 100644 index 000000000000..4483e75b88f4 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_binbased_fast_point_locator.cpp @@ -0,0 +1,356 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes + +// External includes + +// Project includes +#include "containers/model.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/triangle_3d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "testing/testing.h" +#include "includes/model_part.h" + +/* Utilities */ +#include "utilities/binbased_fast_point_locator.h" +#include "utilities/binbased_fast_point_locator_conditions.h" + +namespace Kratos +{ + namespace Testing + { + typedef Node<3> NodeType; + + /** + * Checks the correct work of the binbased fast point locator + * Test triangle + */ + KRATOS_TEST_CASE_IN_SUITE(BinBasedFastPointLocator1, KratosCoreFastSuite) + { + Model current_model; + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (3); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (3); + element_nodes_1[0] = p_node_1; + element_nodes_1[1] = p_node_3; + element_nodes_1[2] = p_node_4; + Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (3); + element_nodes_2[0] = p_node_2; + element_nodes_2[1] = p_node_5; + element_nodes_2[2] = p_node_3; + Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (3); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_6; + element_nodes_3[2] = p_node_3; + Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); + + // We create the locator + auto point_locator = BinBasedFastPointLocator<2>(this_model_part); + point_locator.UpdateSearchDatabase(); + + array_1d coordinates(3, 0.0); + coordinates[0] = 0.5; + coordinates[1] = 0.5; + Vector shape_functions; + Element::Pointer p_element; + bool is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_element, 1000, 5.0e-2); + + Vector ref_shape_functions(3); + ref_shape_functions[0] = 0.5; + ref_shape_functions[1] = 0.0; + ref_shape_functions[2] = 0.5; + + const double tolerance = 1.0e-16; + KRATOS_CHECK(is_found); + KRATOS_CHECK_EQUAL(p_element->Id(), p_elem_0->Id()); + KRATOS_CHECK_LESS_EQUAL(norm_2(shape_functions - ref_shape_functions), tolerance); + + coordinates[0] = -0.5; + coordinates[1] = -0.5; + is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_element, 1000, 5.0e-2); + KRATOS_CHECK_IS_FALSE(is_found); + } + + /** + * Checks the correct work of the binbased fast point locator + * Test tetrahedra + */ + KRATOS_TEST_CASE_IN_SUITE(BinBasedFastPointLocator2, KratosCoreFastSuite) + { + Model current_model; + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_12; + element_nodes_0[1] = p_node_10; + element_nodes_0[2] = p_node_8; + element_nodes_0[3] = p_node_9; + Tetrahedra3D4 tetrahedra_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_4; + element_nodes_1[1] = p_node_6; + element_nodes_1[2] = p_node_9; + element_nodes_1[3] = p_node_7; + Tetrahedra3D4 tetrahedra_1( PointerVector{element_nodes_1} ); + + std::vector element_nodes_2 (4); + element_nodes_2[0] = p_node_11; + element_nodes_2[1] = p_node_7; + element_nodes_2[2] = p_node_9; + element_nodes_2[3] = p_node_8; + Tetrahedra3D4 tetrahedra_2( PointerVector{element_nodes_2} ); + + std::vector element_nodes_3 (4); + element_nodes_3[0] = p_node_5; + element_nodes_3[1] = p_node_3; + element_nodes_3[2] = p_node_8; + element_nodes_3[3] = p_node_6; + Tetrahedra3D4 tetrahedra_3( PointerVector{element_nodes_3} ); + + std::vector element_nodes_4 (4); + element_nodes_4[0] = p_node_4; + element_nodes_4[1] = p_node_6; + element_nodes_4[2] = p_node_7; + element_nodes_4[3] = p_node_3; + Tetrahedra3D4 tetrahedra_4( PointerVector{element_nodes_4} ); + + std::vector element_nodes_5 (4); + element_nodes_5[0] = p_node_2; + element_nodes_5[1] = p_node_3; + element_nodes_5[2] = p_node_5; + element_nodes_5[3] = p_node_6; + Tetrahedra3D4 tetrahedra_5( PointerVector{element_nodes_5} ); + + std::vector element_nodes_6 (4); + element_nodes_6[0] = p_node_10; + element_nodes_6[1] = p_node_9; + element_nodes_6[2] = p_node_6; + element_nodes_6[3] = p_node_8; + Tetrahedra3D4 tetrahedra_6( PointerVector{element_nodes_6} ); + + std::vector element_nodes_7 (4); + element_nodes_7[0] = p_node_7; + element_nodes_7[1] = p_node_8; + element_nodes_7[2] = p_node_3; + element_nodes_7[3] = p_node_6; + Tetrahedra3D4 tetrahedra_7( PointerVector{element_nodes_7} ); + + std::vector element_nodes_8 (4); + element_nodes_8[0] = p_node_7; + element_nodes_8[1] = p_node_8; + element_nodes_8[2] = p_node_6; + element_nodes_8[3] = p_node_9; + Tetrahedra3D4 tetrahedra_8( PointerVector{element_nodes_8} ); + + std::vector element_nodes_9 (4); + element_nodes_9[0] = p_node_4; + element_nodes_9[1] = p_node_1; + element_nodes_9[2] = p_node_6; + element_nodes_9[3] = p_node_3; + Tetrahedra3D4 tetrahedra_9( PointerVector{element_nodes_9} ); + + std::vector element_nodes_10 (4); + element_nodes_10[0] = p_node_9; + element_nodes_10[1] = p_node_12; + element_nodes_10[2] = p_node_11; + element_nodes_10[3] = p_node_8; + Tetrahedra3D4 tetrahedra_10( PointerVector{element_nodes_10} ); + + std::vector element_nodes_11 (4); + element_nodes_11[0] = p_node_3; + element_nodes_11[1] = p_node_2; + element_nodes_11[2] = p_node_1; + element_nodes_11[3] = p_node_6; + Tetrahedra3D4 tetrahedra_11( PointerVector{element_nodes_11} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D4N", 1, tetrahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D4N", 2, tetrahedra_1, p_elem_prop); + Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element3D4N", 3, tetrahedra_2, p_elem_prop); + Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element3D4N", 4, tetrahedra_3, p_elem_prop); + Element::Pointer p_elem_4 = this_model_part.CreateNewElement("Element3D4N", 5, tetrahedra_4, p_elem_prop); + Element::Pointer p_elem_5 = this_model_part.CreateNewElement("Element3D4N", 6, tetrahedra_5, p_elem_prop); + Element::Pointer p_elem_6 = this_model_part.CreateNewElement("Element3D4N", 7, tetrahedra_6, p_elem_prop); + Element::Pointer p_elem_7 = this_model_part.CreateNewElement("Element3D4N", 8, tetrahedra_7, p_elem_prop); + Element::Pointer p_elem_8 = this_model_part.CreateNewElement("Element3D4N", 9, tetrahedra_8, p_elem_prop); + Element::Pointer p_elem_9 = this_model_part.CreateNewElement("Element3D4N", 10, tetrahedra_9, p_elem_prop); + Element::Pointer p_elem_10 = this_model_part.CreateNewElement("Element3D4N", 11, tetrahedra_10, p_elem_prop); + Element::Pointer p_elem_11 = this_model_part.CreateNewElement("Element3D4N", 12, tetrahedra_11, p_elem_prop); + + // We create the locator + auto point_locator = BinBasedFastPointLocator<3>(this_model_part); + point_locator.UpdateSearchDatabase(); + + array_1d coordinates(3, 0.0); + coordinates[0] = 0.5; + coordinates[1] = 0.5; + coordinates[2] = 0.5; + Vector shape_functions; + Element::Pointer p_element; + bool is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_element, 1000, 5.0e-2); + + Vector ref_shape_functions(4); + ref_shape_functions[0] = 0.0; + ref_shape_functions[1] = 0.5; + ref_shape_functions[2] = 0.0; + ref_shape_functions[3] = 0.5; + + const double tolerance = 1.0e-16; + KRATOS_CHECK(is_found); + KRATOS_CHECK_EQUAL(p_element->Id(), p_elem_3->Id()); + KRATOS_CHECK_LESS_EQUAL(norm_2(shape_functions - ref_shape_functions), tolerance); + + coordinates[0] = -0.5; + coordinates[1] = -0.5; + coordinates[2] = -0.5; + is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_element, 1000, 5.0e-2); + KRATOS_CHECK_IS_FALSE(is_found); + } + + /** + * Checks the correct work of the binbased fast point locator + * Test triangle for conditions + */ + + KRATOS_TEST_CASE_IN_SUITE(BinBasedFastPointLocator3, KratosCoreFastSuite) + { + Model current_model; + ModelPart& this_model_part = current_model.CreateModelPart("test_model_part",2); + + Properties::Pointer p_cond_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Now we create the "conditions" + std::vector condition_nodes_0 (3); + condition_nodes_0[0] = p_node_1; + condition_nodes_0[1] = p_node_2; + condition_nodes_0[2] = p_node_3; + Triangle3D3 triangle_0( PointerVector{condition_nodes_0} ); + + std::vector condition_nodes_1 (3); + condition_nodes_1[0] = p_node_1; + condition_nodes_1[1] = p_node_3; + condition_nodes_1[2] = p_node_4; + Triangle3D3 triangle_1( PointerVector{condition_nodes_1} ); + + std::vector condition_nodes_2 (3); + condition_nodes_2[0] = p_node_2; + condition_nodes_2[1] = p_node_5; + condition_nodes_2[2] = p_node_3; + Triangle3D3 triangle_2( PointerVector{condition_nodes_2} ); + + std::vector condition_nodes_3 (3); + condition_nodes_3[0] = p_node_5; + condition_nodes_3[1] = p_node_6; + condition_nodes_3[2] = p_node_3; + Triangle3D3 triangle_3( PointerVector{condition_nodes_3} ); + + Condition::Pointer p_cond_0 = this_model_part.CreateNewCondition("SurfaceCondition3D3N", 1, triangle_0, p_cond_prop); + Condition::Pointer p_cond_1 = this_model_part.CreateNewCondition("SurfaceCondition3D3N", 2, triangle_1, p_cond_prop); + Condition::Pointer p_cond_2 = this_model_part.CreateNewCondition("SurfaceCondition3D3N", 3, triangle_2, p_cond_prop); + Condition::Pointer p_cond_3 = this_model_part.CreateNewCondition("SurfaceCondition3D3N", 4, triangle_3, p_cond_prop); + + // We create the locator + auto point_locator = BinBasedFastPointLocatorConditions<3>(this_model_part); + point_locator.UpdateSearchDatabase(); + + array_1d coordinates(3, 0.0); + coordinates[0] = 0.5; + coordinates[1] = 0.5; + Vector shape_functions; + Condition::Pointer p_condition; + bool is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_condition, 1000, 5.0e-2); + + Vector ref_shape_functions(3); + ref_shape_functions[0] = 0.5; + ref_shape_functions[1] = 0.0; + ref_shape_functions[2] = 0.5; + + const double tolerance = 1.0e-16; + KRATOS_CHECK(is_found); + KRATOS_CHECK_EQUAL(p_condition->Id(), p_cond_0->Id()); + KRATOS_CHECK_LESS_EQUAL(norm_2(shape_functions - ref_shape_functions), tolerance); + + coordinates[0] = -0.5; + coordinates[1] = -0.5; + is_found = point_locator.FindPointOnMeshSimplified(coordinates, shape_functions, p_condition, 1000, 5.0e-2); + KRATOS_CHECK_IS_FALSE(is_found); + } + } // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_brent_iteration.cpp b/kratos/tests/cpp_tests/utilities/test_brent_iteration.cpp new file mode 100644 index 000000000000..95ca8945a28a --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_brent_iteration.cpp @@ -0,0 +1,54 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Jordi Cotela +// +// + +// Project includes +#include "testing/testing.h" +#include "utilities/brent_iteration.h" + +namespace Kratos { + namespace Testing { + + namespace Internals { + double Brent_Test_Function1(double x) + { + return (x-2.0)*(x+1.0); // Roots at 2.0 and -1.0 + } + } + + KRATOS_TEST_CASE_IN_SUITE(BrentIteration, KratosCoreFastSuite) + { + double iterTol = 1e-5; + double maxIter = 10; + double checkTol = 1e-3; + + // Standard operation + KRATOS_CHECK_NEAR(BrentIteration::FindRoot(Internals::Brent_Test_Function1,1.0,3.0,iterTol,maxIter),2.0,checkTol); + + // Passing solution as input + KRATOS_CHECK_NEAR(BrentIteration::FindRoot(Internals::Brent_Test_Function1,2.0,3.0,iterTol,maxIter),2.0,checkTol); + KRATOS_CHECK_NEAR(BrentIteration::FindRoot(Internals::Brent_Test_Function1,1.0,2.0,iterTol,maxIter),2.0,checkTol); + + // Wrong input: initial guesses on the same side of root + try { + BrentIteration::FindRoot(Internals::Brent_Test_Function1,2.5,3.0,iterTol,maxIter); + KRATOS_THROW_ERROR(Exception,"Test Failed: BrentIteration did not throw expected error",""); + } + catch (Exception& e) { + KRATOS_CHECK_STRING_CONTAIN_SUB_STRING(std::string(e.what()), "Error in BrentIteration::FindRoot: The images of both initial guesses have the same sign."); + } + + } + } +} + + diff --git a/kratos/tests/cpp_tests/utilities/test_brute_force_point_locator.cpp b/kratos/tests/cpp_tests/utilities/test_brute_force_point_locator.cpp new file mode 100644 index 000000000000..dea2f9605586 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_brute_force_point_locator.cpp @@ -0,0 +1,212 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// +// + +// Project includes +#include "containers/model.h" +#include "testing/testing.h" +#include "utilities/brute_force_point_locator.h" + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorTriangleElement, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Triangle"); + model_part.GetProcessInfo().SetValue(DOMAIN_SIZE, 2); + + model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + const int elem_id_to_be_found = 43; + model_part.CreateNewElement("Element2D3N", elem_id_to_be_found, {1, 2, 3}, p_properties); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(0.1, 0.25, 0.0); + + Vector shape_function_values; + + const int found_id = point_locator.FindElement(the_point, shape_function_values); + + KRATOS_CHECK_EQUAL(found_id, elem_id_to_be_found); + KRATOS_CHECK_EQUAL(shape_function_values.size(), 3); + + KRATOS_CHECK_NEAR(shape_function_values[0], 0.65, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[1], 0.1, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[2], 0.25, 1e-06); +} + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorQuadrilateralElement, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Quadrilateral"); + model_part.GetProcessInfo().SetValue(DOMAIN_SIZE, 2); + + model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + model_part.CreateNewNode(2, 1.2, 0.1, 0.0); + model_part.CreateNewNode(3, 1.3, 1.02, 0.0); + model_part.CreateNewNode(4, 0.1, 1.0, 0.0); + + Properties::Pointer p_properties(new Properties(0)); + const int elem_id_to_be_found = 181; + model_part.CreateNewElement("Element2D4N", elem_id_to_be_found, {1, 2, 3, 4}, p_properties); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(0.13, 0.52, 0.0); + + Vector shape_function_values; + + const int found_id = point_locator.FindElement(the_point, shape_function_values); + + KRATOS_CHECK_EQUAL(found_id, elem_id_to_be_found); + KRATOS_CHECK_EQUAL(shape_function_values.size(), 4); + + KRATOS_CHECK_NEAR(shape_function_values[0], 0.452231, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[1], 0.0316039, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[2], 0.0337157, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[3], 0.48245, 1e-06); +} + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorTetrahedraElement, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Tetrahedral"); + model_part.GetProcessInfo().SetValue(DOMAIN_SIZE, 3); + + model_part.CreateNewNode(1, 0.0, 0.04, 0.0); + model_part.CreateNewNode(2, 1.01, 0.1, 0.2); + model_part.CreateNewNode(3, 1.3, 1.02, 0.0); + model_part.CreateNewNode(4, 0.1, 0.03, 1.09); + + Properties::Pointer p_properties(new Properties(0)); + const int elem_id_to_be_found = 23; + model_part.CreateNewElement("Element3D4N", elem_id_to_be_found, {1, 2, 3, 4}, p_properties); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(0.25, 0.12, 0.32); + + Vector shape_function_values; + + const int found_id = point_locator.FindElement(the_point, shape_function_values); + + KRATOS_CHECK_EQUAL(found_id, elem_id_to_be_found); + KRATOS_CHECK_EQUAL(shape_function_values.size(), 4); + + KRATOS_CHECK_NEAR(shape_function_values[0], 0.530166, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[1], 0.121616, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[2], 0.0769547, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[3], 0.271263, 1e-06); +} + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorHexahedraElement, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Hexahedral"); + model_part.GetProcessInfo().SetValue(DOMAIN_SIZE, 3); + + model_part.CreateNewNode(1, 0.0, 0.04, 0.0); + model_part.CreateNewNode(2, 1.01, 0.1, 0.2); + model_part.CreateNewNode(3, 1.3, 1.02, 0.0); + model_part.CreateNewNode(4, 0.1, 1.05, 0.09); + model_part.CreateNewNode(5, 0.02, 0.03, 1.09); + model_part.CreateNewNode(6, 1.08, 0.03, 1.09); + model_part.CreateNewNode(7, 1.1, 1.03, 1.22); + model_part.CreateNewNode(8, 0.1, 0.97, 1.09); + + Properties::Pointer p_properties(new Properties(0)); + const int elem_id_to_be_found = 69; + model_part.CreateNewElement("Element3D8N", elem_id_to_be_found, {1,2,3,4,5,6,7,8}, p_properties); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(0.28, 0.32, 0.72); + + Vector shape_function_values; + + const int found_id = point_locator.FindElement(the_point, shape_function_values); + + KRATOS_CHECK_EQUAL(found_id, elem_id_to_be_found); + KRATOS_CHECK_EQUAL(shape_function_values.size(), 8); + + KRATOS_CHECK_NEAR(shape_function_values[0], 0.197609, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[1], 0.0590793, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[2], 0.0242583, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[3], 0.0811397, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[4], 0.348142, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[5], 0.104084, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[6], 0.0427376, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[7], 0.142949, 1e-06); +} + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorNode, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("ForTest"); + + // Fill the model part geometry data + const int node_id_to_be_found = 517; + const double coord_x = 11.258; + const double coord_y = -789.2368; + const double coord_z = 0.863; + model_part.CreateNewNode(12, 0.0, 0.1002, 0.0); + model_part.CreateNewNode(24, 1.0, 0.0, 47.421); + model_part.CreateNewNode(node_id_to_be_found, coord_x, coord_y, coord_z); + model_part.CreateNewNode(5123, coord_x, coord_y, coord_z+0.001); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(coord_x, coord_y, coord_z); + + const int found_id = point_locator.FindNode(the_point); + + KRATOS_CHECK_EQUAL(found_id, node_id_to_be_found); +} + +KRATOS_TEST_CASE_IN_SUITE(BruteForcePointLocatorQuadrilateralCondition, KratosCoreFastSuite) +{ + Model current_model; + ModelPart& model_part = current_model.CreateModelPart("Quadrilateral"); + model_part.GetProcessInfo().SetValue(DOMAIN_SIZE, 3); + + model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + model_part.CreateNewNode(2, 1.2, 0.1, 0.0); + model_part.CreateNewNode(3, 1.3, 1.02, 0.0); + model_part.CreateNewNode(4, 0.1, 1.0, 0.0); + + Properties::Pointer p_properties(new Properties(0)); + const int cond_id_to_be_found = 86; + model_part.CreateNewCondition("SurfaceCondition3D4N", cond_id_to_be_found, {1, 2, 3, 4}, p_properties); + + BruteForcePointLocator point_locator(model_part); + + Point the_point(0.13, 0.52, 0.0); + + Vector shape_function_values; + + const int found_id = point_locator.FindCondition(the_point, shape_function_values); + + KRATOS_CHECK_EQUAL(found_id, cond_id_to_be_found); + KRATOS_CHECK_EQUAL(shape_function_values.size(), 4); + + KRATOS_CHECK_NEAR(shape_function_values[0], 0.452231, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[1], 0.0316039, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[2], 0.0337157, 1e-06); + KRATOS_CHECK_NEAR(shape_function_values[3], 0.48245, 1e-06); +} + +} // namespace Testing +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_discont_utils.cpp b/kratos/tests/cpp_tests/utilities/test_discont_utils.cpp new file mode 100644 index 000000000000..b9c3de25a360 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_discont_utils.cpp @@ -0,0 +1,330 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +#include "includes/gid_io.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "utilities/discont_utils.h" + +namespace Kratos +{ + namespace Testing + { + + KRATOS_TEST_CASE_IN_SUITE(TriangleHorizontalDiscontUtils, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Compute the triangle intersection + BoundedMatrix point_coordinates; + BoundedMatrix continuous_N_gradients; + array_1d nodal_distances; + array_1d partition_volumes; + BoundedMatrix gauss_pt_continuous_N_values; + array_1d partition_signs; + std::vector enriched_N_gradients_values(3); + BoundedMatrix enriched_N_values; + array_1d edge_areas; + + + auto rGeom = base_model_part.Elements()[1].GetGeometry(); + for (unsigned int inode=0; inode point_coordinates; + BoundedMatrix continuous_N_gradients; + array_1d nodal_distances; + array_1d partition_volumes; + BoundedMatrix gauss_pt_continuous_N_values; + array_1d partition_signs; + std::vector enriched_N_gradients_values(3); + BoundedMatrix enriched_N_values; + array_1d edge_areas; + + + auto rGeom = base_model_part.Elements()[1].GetGeometry(); + for (unsigned int inode=0; inode point_coordinates; + BoundedMatrix continuous_N_gradients; + array_1d nodal_distances; + array_1d partition_volumes; + BoundedMatrix gauss_pt_continuous_N_values; + array_1d partition_signs; + std::vector enriched_N_gradients_values(3); + BoundedMatrix enriched_N_values; + array_1d edge_areas; + + + auto rGeom = base_model_part.Elements()[1].GetGeometry(); + for (unsigned int inode=0; inode >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.size(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the tetrahedra splitting utility + DivideTetrahedra3D4 tetrahedra_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + tetrahedra_splitter.GenerateDivision(); + + // Call the intersection generation method + tetrahedra_splitter.GenerateIntersectionsSkin(); + + // Call the positive exterior faces generation method + std::vector < unsigned int > pos_ext_faces_parent_ids; + std::vector < DivideTetrahedra3D4::IndexedPointGeometryPointerType > pos_ext_faces; + tetrahedra_splitter.GenerateExteriorFaces( + pos_ext_faces, + pos_ext_faces_parent_ids, + tetrahedra_splitter.mPositiveSubdivisions); + + // Call the negative exterior faces generation method + std::vector < unsigned int > neg_ext_faces_parent_ids; + std::vector < DivideTetrahedra3D4::IndexedPointGeometryPointerType > neg_ext_faces; + tetrahedra_splitter.GenerateExteriorFaces( + neg_ext_faces, + neg_ext_faces_parent_ids, + tetrahedra_splitter.mNegativeSubdivisions); + + const double tolerance = 1e-10; + + // Check general splitting values + KRATOS_CHECK(tetrahedra_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mDivisionsNumber, 4); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdgesNumber, 3); + + // Check split edges + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[0], 0); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[1], 1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[2], 2); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[3], 3); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[4], -1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[5], -1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[6], 6); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[7], -1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[8], 8); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[9], 9); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[10],-1); + + // Check subdivisions + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].Z(), 0.5, tolerance); + + // Check interfaces + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mPositiveInterfacesParentIds[0], 0); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mNegativeInterfacesParentIds[0], 2); + + // Check exterior faces + KRATOS_CHECK_EQUAL(pos_ext_faces.size(), 3); + KRATOS_CHECK_EQUAL(neg_ext_faces.size(), 7); + + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[0], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[1], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[2], 0); + + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[0], 1); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[1], 2); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[2], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[3], 2); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[4], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[5], 1); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[6], 0); + + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[2].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[6])[2].Z(), 0.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(DivideGeometryTetrahedra3D4Oblique, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + base_model_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry < Node < 3 > >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.size(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the tetrahedra splitting utility + DivideTetrahedra3D4 tetrahedra_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + tetrahedra_splitter.GenerateDivision(); + + // Call the intersection generation method + tetrahedra_splitter.GenerateIntersectionsSkin(); + + // Call the positive exterior faces generation method + std::vector < unsigned int > pos_ext_faces_parent_ids; + std::vector < DivideTetrahedra3D4::IndexedPointGeometryPointerType > pos_ext_faces; + tetrahedra_splitter.GenerateExteriorFaces( + pos_ext_faces, + pos_ext_faces_parent_ids, + tetrahedra_splitter.mPositiveSubdivisions); + + // Call the negative exterior faces generation method + std::vector < unsigned int > neg_ext_faces_parent_ids; + std::vector < DivideTetrahedra3D4::IndexedPointGeometryPointerType > neg_ext_faces; + tetrahedra_splitter.GenerateExteriorFaces( + neg_ext_faces, + neg_ext_faces_parent_ids, + tetrahedra_splitter.mNegativeSubdivisions); + + const double tolerance = 1e-10; + + // Check general splitting values + KRATOS_CHECK(tetrahedra_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mDivisionsNumber, 6); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdgesNumber, 4); + + // Check split edges + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[0], 0); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[1], 1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[2], 2); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[3], 3); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[4], 4); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[5], -1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[6], 6); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[7], 7); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[8], -1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[9], 9); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdges[10],-1); + + // Check subdivisions + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[0])[3].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[1])[3].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveSubdivisions[2])[3].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[0])[3].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[1])[3].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[2].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeSubdivisions[2])[3].Z(), 0.5, tolerance); + + // Check interfaces + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[0])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mPositiveInterfaces[1])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[0])[2].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*tetrahedra_splitter.mNegativeInterfaces[1])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mPositiveInterfacesParentIds[0], 0); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mPositiveInterfacesParentIds[1], 1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mNegativeInterfacesParentIds[0], 1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mNegativeInterfacesParentIds[1], 2); + + // Check exterior faces + KRATOS_CHECK_EQUAL(pos_ext_faces.size(), 6); + KRATOS_CHECK_EQUAL(neg_ext_faces.size(), 6); + + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[0], 1); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[1], 2); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[2], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[3], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[4], 2); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[5], 2); + + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[0], 2); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[1], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[2], 1); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[3], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[4], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[5], 2); + + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[2])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[1].Z(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[3])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[4])[2].Z(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[2].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[5])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Z(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[3])[2].Z(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[4])[2].Z(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[0].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[1].Z(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[5])[2].Z(), 0.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(DivideGeometryTetrahedra3D4NoDivision, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Tetrahedra"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + base_model_part.CreateNewNode(4, 0.0, 0.0, 1.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element3D4N", 1, {1, 2, 3, 4}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[4].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry < Node < 3 > >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.size(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the tetrahedra splitting utility + DivideTetrahedra3D4 tetrahedra_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + tetrahedra_splitter.GenerateDivision(); + + // Check general splitting values + KRATOS_CHECK_IS_FALSE(tetrahedra_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mDivisionsNumber, 1); + KRATOS_CHECK_EQUAL(tetrahedra_splitter.mSplitEdgesNumber, 0); + + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_divide_triangle_2d_3.cpp b/kratos/tests/cpp_tests/utilities/test_divide_triangle_2d_3.cpp new file mode 100644 index 000000000000..364dd56e5569 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_divide_triangle_2d_3.cpp @@ -0,0 +1,360 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +#include "includes/gid_io.h" +#include "utilities/divide_triangle_2d_3.h" + +namespace Kratos +{ + namespace Testing + { + + KRATOS_TEST_CASE_IN_SUITE(DivideGeometryTriangle2D3Horizontal, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry < Node < 3 > >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.size(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the triangle splitting utility + DivideTriangle2D3 triangle_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + triangle_splitter.GenerateDivision(); + + // Call the intersection generation method + triangle_splitter.GenerateIntersectionsSkin(); + + // Call the positive exterior faces generation method + std::vector < unsigned int > pos_ext_faces_parent_ids; + std::vector < DivideTriangle2D3::IndexedPointGeometryPointerType > pos_ext_faces; + triangle_splitter.GenerateExteriorFaces( + pos_ext_faces, + pos_ext_faces_parent_ids, + triangle_splitter.mPositiveSubdivisions); + + // Call the negative exterior faces generation method + std::vector < unsigned int > neg_ext_faces_parent_ids; + std::vector < DivideTriangle2D3::IndexedPointGeometryPointerType > neg_ext_faces; + triangle_splitter.GenerateExteriorFaces( + neg_ext_faces, + neg_ext_faces_parent_ids, + triangle_splitter.mNegativeSubdivisions); + + const double tolerance = 1e-10; + + // Check general splitting values + KRATOS_CHECK(triangle_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(triangle_splitter.mDivisionsNumber, 3); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdgesNumber, 2); + + // Check split edges + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[0], 0); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[1], 1); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[2], 2); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[3], -1); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[4], 4); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[5], 5); + + // Check subdivisions + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[1].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[2].Y(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[2].Y(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[2].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[2].Y(), 0.0, tolerance); + + // Check interfaces + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_EQUAL(triangle_splitter.mPositiveInterfacesParentIds[0], 0); + KRATOS_CHECK_EQUAL(triangle_splitter.mNegativeInterfacesParentIds[0], 0); + + // Check exterior faces + KRATOS_CHECK_EQUAL(pos_ext_faces.size(), 2); + KRATOS_CHECK_EQUAL(neg_ext_faces.size(), 3); + + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[0], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[1], 0); + + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[0], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[1], 1); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[2], 1); + + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Y(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Y(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Y(), 0.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(DivideGeometryTriangle2D3Vertical, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = -1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = -1.0; + + // Set the elemental distances vector + Geometry < Node < 3 > >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.size(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the triangle splitting utility + DivideTriangle2D3 triangle_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + triangle_splitter.GenerateDivision(); + + // Call the intersection generation method + triangle_splitter.GenerateIntersectionsSkin(); + + // Call the positive exterior faces generation method + std::vector < unsigned int > pos_ext_faces_parent_ids; + std::vector < DivideTriangle2D3::IndexedPointGeometryPointerType > pos_ext_faces; + triangle_splitter.GenerateExteriorFaces( + pos_ext_faces, + pos_ext_faces_parent_ids, + triangle_splitter.mPositiveSubdivisions); + + // Call the negative exterior faces generation method + std::vector < unsigned int > neg_ext_faces_parent_ids; + std::vector < DivideTriangle2D3::IndexedPointGeometryPointerType > neg_ext_faces; + triangle_splitter.GenerateExteriorFaces( + neg_ext_faces, + neg_ext_faces_parent_ids, + triangle_splitter.mNegativeSubdivisions); + + const double tolerance = 1e-10; + + // Check general splitting values + KRATOS_CHECK(triangle_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(triangle_splitter.mDivisionsNumber, 3); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdgesNumber, 2); + + // Check split edges + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[0], 0); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[1], 1); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[2], 2); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[3], 3); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[4], 4); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdges[5], -1); + + // Check subdivisions + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[2].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveSubdivisions[0])[2].Y(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[2].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[0])[2].Y(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[1].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[2].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeSubdivisions[1])[2].Y(), 0.0, tolerance); + + // Check interfaces + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mPositiveInterfaces[0])[1].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*triangle_splitter.mNegativeInterfaces[0])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_EQUAL(triangle_splitter.mPositiveInterfacesParentIds[0], 0); + KRATOS_CHECK_EQUAL(triangle_splitter.mNegativeInterfacesParentIds[0], 0); + + // Check exterior faces + KRATOS_CHECK_EQUAL(pos_ext_faces.size(), 2); + KRATOS_CHECK_EQUAL(neg_ext_faces.size(), 3); + + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[0], 0); + KRATOS_CHECK_EQUAL(pos_ext_faces_parent_ids[1], 0); + + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[0], 0); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[1], 1); + KRATOS_CHECK_EQUAL(neg_ext_faces_parent_ids[2], 1); + + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[0])[1].Y(), 0.5, tolerance); + + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].X(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*pos_ext_faces[1])[1].Y(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[0].Y(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[0])[1].Y(), 1.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[0].Y(), 1.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[1])[1].Y(), 0.0, tolerance); + + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].X(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[0].Y(), 0.0, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].X(), 0.5, tolerance); + KRATOS_CHECK_NEAR((*neg_ext_faces[2])[1].Y(), 0.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(DivideGeometryTriangle2D3NoDivision, KratosCoreFastSuite) + { + Model current_model; + + // Generate a model part with the previous + ModelPart& base_model_part = current_model.CreateModelPart("Triangle"); + base_model_part.AddNodalSolutionStepVariable(DISTANCE); + + // Fill the model part geometry data + base_model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + base_model_part.CreateNewNode(2, 1.0, 0.0, 0.0); + base_model_part.CreateNewNode(3, 0.0, 1.0, 0.0); + Properties::Pointer p_properties(new Properties(0)); + base_model_part.CreateNewElement("Element2D3N", 1, {1, 2, 3}, p_properties); + + // Set the DISTANCE field + base_model_part.Nodes()[1].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[2].FastGetSolutionStepValue(DISTANCE) = 1.0; + base_model_part.Nodes()[3].FastGetSolutionStepValue(DISTANCE) = 1.0; + + // Set the elemental distances vector + Geometry < Node < 3 > >& r_geometry = base_model_part.Elements()[1].GetGeometry(); + + array_1d distances_vector; + for (unsigned int i = 0; i < r_geometry.PointsNumber(); ++i) { + distances_vector(i) = r_geometry[i].FastGetSolutionStepValue(DISTANCE); + } + + base_model_part.Elements()[1].SetValue(ELEMENTAL_DISTANCES, distances_vector); + + Vector& r_elemental_distances = base_model_part.Elements()[1].GetValue(ELEMENTAL_DISTANCES); + + // Build the triangle splitting utility + DivideTriangle2D3 triangle_splitter(r_geometry, r_elemental_distances); + + // Call the divide geometry method + triangle_splitter.GenerateDivision(); + + // Check general splitting values + KRATOS_CHECK_IS_FALSE(triangle_splitter.mIsSplit); + KRATOS_CHECK_EQUAL(triangle_splitter.mDivisionsNumber, 1); + KRATOS_CHECK_EQUAL(triangle_splitter.mSplitEdgesNumber, 0); + + } + } +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_embedded_skin_utility.cpp b/kratos/tests/cpp_tests/utilities/test_embedded_skin_utility.cpp new file mode 100644 index 000000000000..33ebfafb498f --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_embedded_skin_utility.cpp @@ -0,0 +1,106 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// + +// Project includes +#include "testing/testing.h" +#include "containers/model.h" +#include "includes/checks.h" +// #include "includes/gid_io.h" +#include "geometries/quadrilateral_2d_4.h" +#include "processes/calculate_distance_to_skin_process.h" +#include "processes/structured_mesh_generator_process.h" +#include "utilities/embedded_skin_utility.h" + +namespace Kratos +{ +namespace Testing +{ + + KRATOS_TEST_CASE_IN_SUITE(EmbeddedSkinUtility2D, KratosCoreFastSuite) + { + Model current_model; + + // Generate a volume mesh (done with the StructuredMeshGeneratorProcess) + Node<3>::Pointer p_point_1 = Kratos::make_shared>(1, 0.00, 0.00, 0.00); + Node<3>::Pointer p_point_2 = Kratos::make_shared>(2, 0.00, 10.00, 0.00); + Node<3>::Pointer p_point_3 = Kratos::make_shared>(3, 10.00, 10.00, 0.00); + Node<3>::Pointer p_point_4 = Kratos::make_shared>(4, 10.00, 0.00, 0.00); + + Quadrilateral2D4> geometry(p_point_1, p_point_2, p_point_3, p_point_4); + + Parameters mesher_parameters(R"( + { + "number_of_divisions": 12, + "element_name": "Element2D3N" + })"); + + ModelPart &surface_part = current_model.CreateModelPart("Volume"); + surface_part.AddNodalSolutionStepVariable(DISTANCE); + StructuredMeshGeneratorProcess(geometry, surface_part, mesher_parameters).Execute(); + + // Generate the skin + ModelPart &skin_part = current_model.CreateModelPart("Skin"); + skin_part.AddNodalSolutionStepVariable(VELOCITY); + skin_part.CreateNewNode(901, 2.4, 2.4, 0.0); + skin_part.CreateNewNode(902, 7.6, 2.4, 0.0); + skin_part.CreateNewNode(903, 7.6, 7.6, 0.0); + skin_part.CreateNewNode(904, 2.4, 7.6, 0.0); + skin_part.CreateNewNode(905, 3.9, 3.9, 0.0); + skin_part.CreateNewNode(906, 6.1, 3.9, 0.0); + skin_part.CreateNewNode(907, 6.1, 6.1, 0.0); + skin_part.CreateNewNode(908, 3.9, 6.1, 0.0); + Properties::Pointer p_properties(new Properties(0)); + skin_part.CreateNewElement("Element2D2N", 901, {{901,902}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 902, {{902,903}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 903, {{903,904}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 904, {{904,901}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 905, {{905,906}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 906, {{906,907}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 907, {{907,908}}, p_properties); + skin_part.CreateNewElement("Element2D2N", 908, {{908,905}}, p_properties); + + // Compute distance + CalculateDistanceToSkinProcess<2>(surface_part, skin_part).Execute(); + + // Generate the skin + ModelPart &generated_skin_part = current_model.CreateModelPart("GeneratedSkinPart"); + EmbeddedSkinUtility<2> embedded_skin_utility(surface_part, generated_skin_part, "continuous"); + embedded_skin_utility.GenerateSkin(); + + KRATOS_CHECK_EQUAL(generated_skin_part.NumberOfNodes(), 152); + KRATOS_CHECK_EQUAL(generated_skin_part.NumberOfConditions(), 76); + + // GidIO<> gid_io_fluid("/home/rzorrilla/Desktop/surface_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_fluid.InitializeMesh(0.00); + // gid_io_fluid.WriteMesh(surface_part.GetMesh()); + // gid_io_fluid.FinalizeMesh(); + // gid_io_fluid.InitializeResults(0, surface_part.GetMesh()); + // gid_io_fluid.WriteNodalResults(DISTANCE, surface_part.Nodes(), 0, 0); + // gid_io_fluid.FinalizeResults(); + + // GidIO<> gid_io_skin("/home/rzorrilla/Desktop/skin_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_skin.InitializeMesh(0.00); + // gid_io_skin.WriteMesh(skin_part.GetMesh()); + // gid_io_skin.FinalizeMesh(); + // gid_io_skin.InitializeResults(0, skin_part.GetMesh()); + // gid_io_skin.FinalizeResults(); + + // GidIO<> gid_io_generated_skin("/home/rzorrilla/Desktop/generated_skin_mesh", GiD_PostAscii, SingleFile, WriteDeformed, WriteConditions); + // gid_io_generated_skin.InitializeMesh(0.00); + // gid_io_generated_skin.WriteMesh(generated_skin_part.GetMesh()); + // gid_io_generated_skin.FinalizeMesh(); + // gid_io_generated_skin.InitializeResults(0, generated_skin_part.GetMesh()); + // gid_io_generated_skin.FinalizeResults(); + } + +} +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_geometrical_projection_utilities.cpp b/kratos/tests/cpp_tests/utilities/test_geometrical_projection_utilities.cpp new file mode 100644 index 000000000000..739ea24c2b33 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_geometrical_projection_utilities.cpp @@ -0,0 +1,107 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// Vicente Mataix Ferrandiz +// +// + +// Project includes +#include "testing/testing.h" +#include "utilities/geometrical_projection_utilities.h" + +#include "geometries/triangle_3d_3.h" + +namespace Kratos +{ +namespace Testing +{ + +using NodeType = typename GeometricalProjectionUtilities::NodeType; +using GeometryType = typename GeometricalProjectionUtilities::GeometryType; + +GeometryType::Pointer CreateTriangle2D3NForTest() +{ + GeometryType::PointsArrayType points; + points.push_back(Kratos::make_shared(1,0.04, 0.02, 0.0)); + points.push_back(Kratos::make_shared(2,1.1, 0.03, 0.0)); + points.push_back(Kratos::make_shared(3,1.08, 1.0, 0.0)); + + return GeometryType::Pointer(new Triangle3D3(points)); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalProjectionUtilitiesFastProjectDirection, KratosCoreFastSuite) +{ + GeometryType::Pointer p_geom = CreateTriangle2D3NForTest(); + + double expected_proj_dist = 1.258; + + const double x_coord = 0.325; + const double y_coord = 0.147; + + const Point point_to_proj(x_coord, y_coord, expected_proj_dist); + + array_1d dir_vector; + array_1d normal_vector; + + dir_vector[0] = 0.0; + dir_vector[1] = 0.0; + dir_vector[2] = -1.0; + + normal_vector[0] = 0.0; + normal_vector[1] = 0.0; + normal_vector[2] = 1.0; + + Point projected_point; + + double proj_distance = GeometricalProjectionUtilities::FastProjectDirection( + *p_geom, + point_to_proj, + projected_point, + normal_vector, + dir_vector); + + KRATOS_CHECK_DOUBLE_EQUAL(expected_proj_dist, proj_distance); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.X(), x_coord); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.Y(), y_coord); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.Z(), 0.0); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalProjectionUtilitiesFastProject, KratosCoreFastSuite) +{ + const double expected_proj_dist = 1.258; + + const double x_coord = 0.325; + const double y_coord = 0.147; + + const Point point_in_plane(-1.274, 10.478, 0.0); + const Point point_to_proj(x_coord, y_coord, expected_proj_dist); + + array_1d normal_vector; + + normal_vector[0] = 0.0; + normal_vector[1] = 0.0; + normal_vector[2] = 1.0; + + double proj_distance; + + Point projected_point = GeometricalProjectionUtilities::FastProject( + point_in_plane, + point_to_proj, + normal_vector, + proj_distance); + + KRATOS_CHECK_DOUBLE_EQUAL(expected_proj_dist, proj_distance); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.X(), x_coord); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.Y(), y_coord); + KRATOS_CHECK_DOUBLE_EQUAL(projected_point.Z(), 0.0); +} + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_geometrical_sensitivity_utility.cpp b/kratos/tests/cpp_tests/utilities/test_geometrical_sensitivity_utility.cpp new file mode 100644 index 000000000000..f04d96ba2223 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_geometrical_sensitivity_utility.cpp @@ -0,0 +1,196 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: +// + +// External includes + +// Project includes +#include "testing/testing.h" +#include "geometries/point.h" +#include "geometries/geometry.h" +#include "geometries/quadrilateral_2d_4.h" +#include "geometries/hexahedra_3d_8.h" +#include "geometries/triangle_2d_3.h" +#include "geometries/tetrahedra_3d_4.h" +#include "utilities/geometrical_sensitivity_utility.h" + +namespace Kratos +{ +namespace Testing +{ + +Geometry::Pointer CreateQuadrilateral2D4N() +{ + Geometry::PointsArrayType points; + points.push_back(Kratos::make_shared(0.0, 0.0, 0.0)); + points.push_back(Kratos::make_shared(1.2, 0.1, 0.0)); + points.push_back(Kratos::make_shared(1.3, 1.02, 0.0)); + points.push_back(Kratos::make_shared(0.1, 1.0, 0.0)); + + return Geometry::Pointer(new Quadrilateral2D4(points)); +} + +Geometry::Pointer CreateHexahedra3D8N() +{ + Geometry::PointsArrayType points; + points.push_back(Kratos::make_shared(0.0, 0.0, 0.0)); + points.push_back(Kratos::make_shared(1.02, 0.0, 0.0)); + points.push_back(Kratos::make_shared(1.1, 1.03, 0.07)); + points.push_back(Kratos::make_shared(0.01, 1.0, 0.0)); + points.push_back(Kratos::make_shared(0.0, 0.0, 1.05)); + points.push_back(Kratos::make_shared(1.08, 0.01, 1.0)); + points.push_back(Kratos::make_shared(1.03, 1.09, 1.0)); + points.push_back(Kratos::make_shared(0.0, 1.05, 1.04)); + + return Geometry::Pointer(new Hexahedra3D8(points)); +} + +Geometry::Pointer CreateTriangle2D3N() +{ + Geometry::PointsArrayType points; + points.push_back(Kratos::make_shared(0.04, 0.02, 0.0)); + points.push_back(Kratos::make_shared(1.1, 0.03, 0.0)); + points.push_back(Kratos::make_shared(1.08, 1.0, 0.0)); + + return Geometry::Pointer(new Triangle2D3(points)); +} + +Geometry::Pointer CreateTetrahedra3D4N() +{ + Geometry::PointsArrayType points; + points.push_back(Kratos::make_shared(0.0, 0.04, 0.0)); + points.push_back(Kratos::make_shared(1.01, 0.0, 0.2)); + points.push_back(Kratos::make_shared(1.05, 1.0, 0.0)); + points.push_back(Kratos::make_shared(0.0, 0.03, 1.09)); + + return Geometry::Pointer(new Tetrahedra3D4(points)); +} + +void CheckDeterminantOfJacobianSensitivityByFiniteDifference(double DetJ_Deriv, + unsigned IntegrationPoint, + ShapeParameter Deriv, + Geometry& rGeom, + GeometryData::IntegrationMethod ThisMethod, + double StepSize = 1e-7, + double Tolerance = 1e-7) +{ + double detJ = rGeom.DeterminantOfJacobian(IntegrationPoint, ThisMethod); + rGeom[Deriv.NodeIndex].Coordinates()[Deriv.Direction] += StepSize; + double detJ_perturbed = rGeom.DeterminantOfJacobian(IntegrationPoint, ThisMethod); + rGeom[Deriv.NodeIndex].Coordinates()[Deriv.Direction] -= StepSize; + double finite_difference_detJ_deriv = (detJ_perturbed - detJ) / StepSize; + KRATOS_CHECK_NEAR(DetJ_Deriv, finite_difference_detJ_deriv, Tolerance); +} + +void CheckShapeFunctionsGradientSensitivityByFiniteDifference(Matrix& DN_DX_Deriv, + unsigned IntegrationPoint, + ShapeParameter Deriv, + Geometry& rGeom, + GeometryData::IntegrationMethod ThisMethod, + double StepSize = 1e-7, + double Tolerance = 1e-7) +{ + Geometry::ShapeFunctionsGradientsType DN_DX; + rGeom.ShapeFunctionsIntegrationPointsGradients(DN_DX, ThisMethod); + const Matrix& rDN_DX = DN_DX[IntegrationPoint]; + + rGeom[Deriv.NodeIndex].Coordinates()[Deriv.Direction] += StepSize; + + Geometry::ShapeFunctionsGradientsType DN_DX_perturbed; + rGeom.ShapeFunctionsIntegrationPointsGradients(DN_DX_perturbed, ThisMethod); + const Matrix& rDN_DX_perturbed = DN_DX_perturbed[IntegrationPoint]; + + rGeom[Deriv.NodeIndex].Coordinates()[Deriv.Direction] -= StepSize; + + // Perform some checks to avoid false positives. + KRATOS_CHECK(DN_DX_Deriv.size1() != 0); + KRATOS_CHECK(DN_DX_Deriv.size2() != 0); + for (unsigned i = 0; i < DN_DX_Deriv.size1(); ++i) + for (unsigned j = 0; j < DN_DX_Deriv.size2(); ++j) + { + const double finite_difference_ij = (rDN_DX_perturbed(i,j) - rDN_DX(i,j)) / StepSize; + KRATOS_CHECK_NEAR(DN_DX_Deriv(i, j), finite_difference_ij, Tolerance); + } +} + +void TestThisGeometry(Geometry& rGeom, + GeometryData::IntegrationMethod ThisMethod, + double StepSize = 1e-7, + double Tolerance = 1e-7) +{ + + Geometry::JacobiansType J; + rGeom.Jacobian(J, ThisMethod); + + Geometry::ShapeFunctionsGradientsType DN_De; + DN_De = rGeom.ShapeFunctionsLocalGradients(ThisMethod); + + GeometricalSensitivityUtility::ShapeFunctionsGradientType DN_DX_deriv; + + for (unsigned g = 0; g < rGeom.IntegrationPointsNumber(ThisMethod); ++g) + { + const Matrix& rJ = J[g]; + const Matrix& rDN_De = DN_De[g]; + GeometricalSensitivityUtility geom_sensitivity(rJ, rDN_De); + + auto s = ShapeParameter::Sequence(rGeom.PointsNumber(), + rGeom.WorkingSpaceDimension()); + while (s) + { + double detJ_deriv; + const auto& deriv = s.CurrentValue(); + geom_sensitivity.CalculateSensitivity(deriv, detJ_deriv, DN_DX_deriv); + CheckDeterminantOfJacobianSensitivityByFiniteDifference( + detJ_deriv, g, deriv, rGeom, ThisMethod, StepSize, Tolerance); + CheckShapeFunctionsGradientSensitivityByFiniteDifference( + DN_DX_deriv, g, deriv, rGeom, ThisMethod, StepSize, Tolerance); + ++s; + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalSensitivityUtility_Quadrilateral2D4N_GAUSS_2, KratosSensitivityTestSuite) +{ + Geometry::Pointer p_geom = CreateQuadrilateral2D4N(); + Geometry& r_geom = *p_geom; + TestThisGeometry(r_geom, GeometryData::GI_GAUSS_2); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalSensitivityUtility_Quadrilateral2D4N_GAUSS_1, KratosSensitivityTestSuite) +{ + Geometry::Pointer p_geom = CreateQuadrilateral2D4N(); + Geometry& r_geom = *p_geom; + TestThisGeometry(r_geom, GeometryData::GI_GAUSS_1); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalSensitivityUtility_Hexahedra3D8N_GAUSS_2, KratosSensitivityTestSuite) +{ + Geometry::Pointer p_geom = CreateHexahedra3D8N(); + Geometry& r_geom = *p_geom; + TestThisGeometry(r_geom, GeometryData::GI_GAUSS_2); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalSensitivityUtility_Triangle2D3N_GAUSS_1, KratosSensitivityTestSuite) +{ + Geometry::Pointer p_geom = CreateTriangle2D3N(); + Geometry& r_geom = *p_geom; + TestThisGeometry(r_geom, GeometryData::GI_GAUSS_1, 1e-8); +} + +KRATOS_TEST_CASE_IN_SUITE(GeometricalSensitivityUtility_Tetrahedra3D4N_GAUSS_1, KratosSensitivityTestSuite) +{ + Geometry::Pointer p_geom = CreateTetrahedra3D4N(); + Geometry& r_geom = *p_geom; + TestThisGeometry(r_geom, GeometryData::GI_GAUSS_1, 1e-8); +} + +} // namespace Testing +} // namespace Kratos. \ No newline at end of file diff --git a/kratos/tests/cpp_tests/utilities/test_geometry_utils.cpp b/kratos/tests/cpp_tests/utilities/test_geometry_utils.cpp new file mode 100644 index 000000000000..d92d1e286ec2 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_geometry_utils.cpp @@ -0,0 +1,55 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "testing/testing.h" +#include "includes/checks.h" +#include "includes/gid_io.h" +#include "utilities/geometry_utilities.h" + +namespace Kratos { +namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(GeometryUtilsPointDistanceToTriangleOutOfPlane, KratosCoreFastSuite) + { + // Triangle plane points + Point triangle_point_1(-1.0,-1.0, 0.0); + Point triangle_point_2( 1.0,-1.0, 0.0); + Point triangle_point_3(-1.0, 1.0, 0.0); + + // Point out of plane to compute the distance to + Point distance_point(0.357143, -0.214286, 0.0714286); + + + const double dist = GeometryUtils::PointDistanceToTriangle3D(triangle_point_1, triangle_point_2, triangle_point_3, distance_point); + + KRATOS_CHECK_NEAR(dist, 0.123718, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(GeometryUtilsPointDistanceToTriangleInPlane, KratosCoreFastSuite) + { + // Triangle plane points + Point triangle_point_1( 1.0,-1.0, 0.0); + Point triangle_point_2( 1.0, 1.0, 0.0); + Point triangle_point_3(-1.0, 1.0, 0.0); + + // Point over the plane to compute the distance to + Point distance_point(0.357143, -0.214286, 0.0714286); + + const double dist = GeometryUtils::PointDistanceToTriangle3D(triangle_point_1, triangle_point_2, triangle_point_3, distance_point); + + KRATOS_CHECK_NEAR(dist, distance_point.Z(), 1e-6); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_intersection_utilities.cpp b/kratos/tests/cpp_tests/utilities/test_intersection_utilities.cpp new file mode 100644 index 000000000000..bfbc7de4e95d --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_intersection_utilities.cpp @@ -0,0 +1,424 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "geometries/point.h" +#include "geometries/line_2d_2.h" +#include "geometries/triangle_3d_3.h" +#include "includes/checks.h" +#include "testing/testing.h" +#include "utilities/intersection_utilities.h" + +namespace Kratos { +namespace Testing { + + Line2D2 GenerateSlopedLine2D2(){ + Point::Pointer p_point_1 = Kratos::make_shared(1.0, 0.0, 0.0); + Point::Pointer p_point_2 = Kratos::make_shared(0.0, 1.0, 0.0); + Line2D2 line_geom(p_point_1, p_point_2); + return line_geom; + } + + Line2D2 GenerateVerticalLine2D2(){ + Point::Pointer p_point_1 = Kratos::make_shared(0.0, 0.0, 0.0); + Point::Pointer p_point_2 = Kratos::make_shared(0.0, 1.0, 0.0); + Line2D2 line_geom(p_point_1, p_point_2); + return line_geom; + } + + Triangle3D3 GenerateStraightTriangle3D3(){ + Point::Pointer p_point_1 = Kratos::make_shared(0.0, 0.0, 0.0); + Point::Pointer p_point_2 = Kratos::make_shared(0.0, 1.0, 0.0); + Point::Pointer p_point_3 = Kratos::make_shared(0.0, 0.0, 1.0); + Triangle3D3 triang_geom(p_point_1, p_point_2, p_point_3); + return triang_geom; + } + + Triangle3D3 GenerateSkewedTriangle3D3(){ + Point::Pointer p_point_1 = Kratos::make_shared(1.0, 0.0, 0.0); + Point::Pointer p_point_2 = Kratos::make_shared(0.0, 0.0, 1.0); + Point::Pointer p_point_3 = Kratos::make_shared(0.0, 1.0, 0.5); + Triangle3D3 triang_geom(p_point_1, p_point_2, p_point_3); + return triang_geom; + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineIntersectionCentered, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateVerticalLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(-1.0,0.5,0.0); + const Point line_pt_2( 1.0,0.5,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt_coords(0), 0.0, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(1), 0.5, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(2), 0.0, 1e-10); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateSlopedLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(-0.5,0.0,0.0); + const Point line_pt_2( 1.0,1.0,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt_coords(0), 0.4, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(1), 0.6, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(2), 0.0, 1e-10); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineParallel, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateVerticalLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(1.0,2.0,0.0); + const Point line_pt_2(1.0,3.0,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 0); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineCollinear, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateVerticalLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(0.0,0.25,0.0); + const Point line_pt_2(0.0,0.75,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 2); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineNonParallelNoIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateSlopedLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(0.0,0.0,0.0); + const Point line_pt_2(0.25,0.25,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 0); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineLineThroughPoint, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto line_geom = GenerateVerticalLine2D2(); + + // Set the points that define the intersection line + const Point line_pt_1(-1.0,0.0,0.0); + const Point line_pt_2(0.0,0.0,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineLineIntersection>( + line_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 3); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[2], 0.0, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineCenteredIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto triang_geom = GenerateStraightTriangle3D3(); + + // Set the points that define the intersection line + const Point line_pt_1(1.0,0.25,0.25); + const Point line_pt_2(-1.0,0.25,0.25); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt_coords(0), 0.0, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(1), 0.25, 1e-10); + KRATOS_CHECK_NEAR(int_pt_coords(2), 0.25, 1e-10); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineSkewedIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto triang_geom = GenerateSkewedTriangle3D3(); + + // Set the points that define the intersection line + const Point line_pt_1(2.0,0.0,0.0); + const Point line_pt_2(-1.0,0.25,0.25); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point coordinates + const array_1d int_pt_coords = int_pt.Coordinates(); + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt_coords(0), 0.857143, 1e-6); + KRATOS_CHECK_NEAR(int_pt_coords(1), 0.0952381, 1e-6); + KRATOS_CHECK_NEAR(int_pt_coords(2), 0.0952381, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineNoIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto triang_geom = GenerateStraightTriangle3D3(); + + // Set the points that define the intersection line + const Point line_pt_1(1.0,0.25,0.25); + const Point line_pt_2(0.1,0.25,0.25); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Check that there is no intersection + KRATOS_CHECK_EQUAL(int_id, 0); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineThroughPoint, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto triang_geom = GenerateStraightTriangle3D3(); + + // Set the points that define the intersection line + const Point line_pt_1(1.0,0.0,0.0); + const Point line_pt_2(-1.0,0.0,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Compute and check the obtained intersection point passes through the node + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(int_pt.Coordinates()[2], 0.0, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineCoplanar, KratosCoreFastSuite) + { + // Set the triangle to be intersected + auto triang_geom = GenerateStraightTriangle3D3(); + + // Set the points that define the intersection line + const Point line_pt_1(0.0,0.0,0.0); + const Point line_pt_2(0.0,1.0,0.0); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // Check that there is no intersection + KRATOS_CHECK_EQUAL(int_id, 2); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesTriangleLineBoundaryIntersection, KratosCoreFastSuite) + { + // Set the triangle to be intersected + Point::Pointer p_point_1 = Kratos::make_shared(0.302838, 0.210816, 0.5); + Point::Pointer p_point_2 = Kratos::make_shared(0.325, 0.196891, 0.5); + Point::Pointer p_point_3 = Kratos::make_shared(0.31342, 0.204924, 0.475141); + Triangle3D3 triang_geom(p_point_1, p_point_2, p_point_3); + + // Set the points that define the intersection line + const Point line_pt_1(0.3,0.2,0.5); + const Point line_pt_2(0.4,0.2,0.5); + + // Initialize the intersection point + Point int_pt(0.0,0.0,0.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeTriangleLineIntersection>( + triang_geom, + line_pt_1.Coordinates(), + line_pt_2.Coordinates(), + int_pt.Coordinates()); + + // The triangle and edge are set such that the intersection occurs close to the triangle boundary + KRATOS_CHECK_EQUAL(int_id, 1); + KRATOS_CHECK_NEAR(int_pt[0], 0.320052, 1e-6); + KRATOS_CHECK_NEAR(int_pt[1], 0.2, 1e-6); + KRATOS_CHECK_NEAR(int_pt[2], 0.5, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineBoxIntersectionNoHitpoint, KratosCoreFastSuite) + { + // Set the origin and endpoint of the segment + const Point line_origin(0.5,0.5,2.0); + const Point line_endpoint(0.6,0.8,2.5); + + // Set the box minimum and maximum point + const Point box_min_point(0.0,0.0,0.0); + const Point box_max_point(1.0,1.0,1.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineBoxIntersection( + box_min_point.Coordinates(), + box_max_point.Coordinates(), + line_origin.Coordinates(), + line_endpoint.Coordinates()); + + KRATOS_CHECK_EQUAL(int_id, 0); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineBoxIntersectionSingle, KratosCoreFastSuite) + { + // Set the origin and endpoint of the segment + const Point line_origin(0.5,0.5,0.5); + const Point line_endpoint(-0.5,0.3,0.3); + + // Set the box minimum and maximum point + const Point box_min_point(0.0,0.0,0.0); + const Point box_max_point(1.0,1.0,1.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineBoxIntersection( + box_min_point.Coordinates(), + box_max_point.Coordinates(), + line_origin.Coordinates(), + line_endpoint.Coordinates()); + + KRATOS_CHECK_EQUAL(int_id, 1); + } + + KRATOS_TEST_CASE_IN_SUITE(IntersectionUtilitiesLineBoxIntersectionDouble, KratosCoreFastSuite) + { + // Set the origin and endpoint of the segment + const Point line_origin(-0.5,0.5,0.5); + const Point line_endpoint(1.5,0.5,0.5); + + // Set the box minimum and maximum point + const Point box_min_point(0.0,0.0,0.0); + const Point box_max_point(1.0,1.0,1.0); + + // Call the intersection utility + const int int_id = IntersectionUtilities::ComputeLineBoxIntersection( + box_min_point.Coordinates(), + box_max_point.Coordinates(), + line_origin.Coordinates(), + line_endpoint.Coordinates()); + + KRATOS_CHECK_EQUAL(int_id, 1); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_math_utils.cpp b/kratos/tests/cpp_tests/utilities/test_math_utils.cpp new file mode 100644 index 000000000000..2c67987bc090 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_math_utils.cpp @@ -0,0 +1,850 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes + + +// Project includes +#include "testing/testing.h" +#include "includes/global_variables.h" + +// Utility includes +#include "utilities/math_utils.h" + +namespace Kratos +{ + namespace Testing + { + /// Tests + + /** Checks if the area of the triangle is calculated correctly using Heron equation. + * Checks if the area of the triangle is calculated correctly using Heron equation. + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsHeron, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + const double area = MathUtils::Heron(std::sqrt(2.0), 1.0, 1.0); + + KRATOS_CHECK_NEAR(area, 0.5, tolerance); + } + + /** Checks if it gives you the absolute value of a given value + * Checks if It gives you the absolute value of a given value + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsAbs, KratosCoreFastSuite) + { + const double absolute = MathUtils::Abs(-1.0); + + KRATOS_CHECK_EQUAL(absolute, 1.0); + } + + /** Checks if it gives you the minimum value of a given value + * Checks if It gives you the minimum value of a given value + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsMin, KratosCoreFastSuite) + { + const double min = MathUtils::Min(0.0,1.0); + + KRATOS_CHECK_EQUAL(min, 0.0); + } + + /** Checks if it gives you the maximum value of a given value + * Checks if It gives you the maximum value of a given value + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsMax, KratosCoreFastSuite) + { + const double max = MathUtils::Max(0.0,1.0); + + KRATOS_CHECK_EQUAL(max, 1.0); + } + + /** Checks if it calculates the determinant of a 1x1, 2x2, 3x3 and 4x4 matrix + * Checks if it calculates the determinant of a 1x1, 2x2, 3x3 and 4x4 matrix + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsDetMat, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + BoundedMatrix mat11 = ZeroMatrix(1, 1); + mat11(0,0) = 1.0; + + double det = MathUtils::DetMat(mat11); + + KRATOS_CHECK_NEAR(det, 1.0, tolerance); + + BoundedMatrix mat22 = ZeroMatrix(2, 2); + mat22(0,0) = 1.0; + mat22(1,1) = 1.0; + + det = MathUtils::DetMat(mat22); + + KRATOS_CHECK_NEAR(det, 1.0, tolerance); + + BoundedMatrix mat33 = ZeroMatrix(3, 3); + mat33(0,0) = 1.0; + mat33(1,1) = 1.0; + mat33(2,2) = 1.0; + + det = MathUtils::DetMat(mat33); + + KRATOS_CHECK_NEAR(det, 1.0, tolerance); + + BoundedMatrix mat44 = ZeroMatrix(4, 4); + mat44(0,0) = 1.0; + mat44(1,1) = 1.0; + mat44(2,2) = 1.0; + mat44(3,3) = 1.0; + + det = MathUtils::DetMat(mat44); + + KRATOS_CHECK_NEAR(det, 1.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsCofactor, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + BoundedMatrix mat11 = ZeroMatrix(1, 1); + mat11(0,0) = 2.0; + + double cofactor = MathUtils::Cofactor(mat11, 0, 0); + + KRATOS_CHECK_EQUAL(cofactor, 1.0); + + BoundedMatrix mat22 = ZeroMatrix(2, 2); + mat22(0,0) = -2.0; mat22(0,1) = 2.0; + mat22(1,0) = -1.0; mat22(1,1) = 1.0; + + cofactor = MathUtils::Cofactor(mat22, 1, 1); + KRATOS_CHECK_EQUAL(cofactor, -2.0); + + cofactor = MathUtils::Cofactor(mat22, 0, 1); + KRATOS_CHECK_EQUAL(cofactor, 1.0); + + BoundedMatrix mat33 = ZeroMatrix(3, 3); + mat33(0,0) = -2.0; mat33(0,1) = 2.0; mat33(0,2) = -3.0; + mat33(1,0) = -1.0; mat33(1,1) = 1.0; mat33(1,2) = 3.0; + mat33(2,0) = 2.0; mat33(2,1) = 0.0; mat33(2,2) = -1.0; + + cofactor = MathUtils::Cofactor(mat33, 2, 1); + KRATOS_CHECK_NEAR(cofactor, 9.0, tolerance); + } + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsCofactorMatrix, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + BoundedMatrix mat33 = ZeroMatrix(3, 3); + mat33(0,0) = 2.0; mat33(0,1) = 0.0; mat33(0,2) = 2.0; + mat33(1,0) = 2.0; mat33(1,1) = 0.0; mat33(1,2) =-2.0; + mat33(2,0) = 0.0; mat33(2,1) = 1.0; mat33(2,2) = 1.0; + + BoundedMatrix ref33 = ZeroMatrix(3, 3); + ref33(0,0) = 2.0; ref33(0,1) =-2.0; ref33(0,2) = 2.0; + ref33(1,0) = 2.0; ref33(1,1) = 2.0; ref33(1,2) =-2.0; + ref33(2,0) = 0.0; ref33(2,1) = 8.0; ref33(2,2) = 0.0; + + MathUtils::MatrixType cof_mat = MathUtils::CofactorMatrix(mat33); + for (unsigned i = 0; i < ref33.size1(); ++i) + for (unsigned j = 0; j < ref33.size2(); ++j) + KRATOS_CHECK_NEAR(cof_mat(i,j), ref33(i,j), tolerance); + } + + /** Checks if it calculates the generalized determinant of a non-square matrix + * Checks if it calculates the generalized determinant of a non-square matrix + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsGenDetMat, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + Matrix mat23 = ZeroMatrix(2, 3); + mat23(0,0) = 1.0; + mat23(1,1) = 1.0; + + double det = MathUtils::GeneralizedDet(mat23); + + KRATOS_CHECK_NEAR(det, 1.0, tolerance); + + Matrix mat55 = ZeroMatrix(5, 5); + mat55(0,0) = 1.0; + mat55(1,1) = 1.0; + mat55(2,2) = 1.0; + mat55(3,3) = 1.0; + mat55(2,3) = - 1.0; + mat55(3,2) = 1.0; + mat55(4,4) = 2.0; + + det = MathUtils::Det(mat55); + + KRATOS_CHECK_NEAR(det, 4.0, tolerance); + } + + /** Checks if it calculates the inverse of a 1x1, 2x2, 3x3 and 4x4 matrix + * Checks if it calculates the inverse of a 1x1, 2x2, 3x3 and 4x4 matrix + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsInvMat, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + BoundedMatrix mat11; + mat11(0,0) = 0.896308; + + double det; + const BoundedMatrix inv11 = MathUtils::InvertMatrix<1>(mat11, det); + const BoundedMatrix I11 = prod(inv11, mat11); + + KRATOS_CHECK_NEAR(I11(0,0), 1.0, tolerance); + + BoundedMatrix mat22; + mat22(0,0) = 0.670005; + mat22(0,1) = 0.853367; + mat22(1,0) = 1.47006; + mat22(1,1) = 1.00029; + + const BoundedMatrix inv22 = MathUtils::InvertMatrix<2>(mat22, det); + const BoundedMatrix I22 = prod(inv22, mat22); + + for (unsigned int i = 0; i < 2; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + if (i == j) + { + KRATOS_CHECK_NEAR(I22(i,j), 1.0, tolerance); + } + else + { + KRATOS_CHECK_NEAR(I22(i,j), 0.0, tolerance); + } + } + } + + BoundedMatrix mat33; + mat33(0,0) = 0.678589; + mat33(0,1) = 0.386213; + mat33(0,2) = 0.371126; + mat33(1,0) = 1.01524; + mat33(1,1) = 0.403437; + mat33(1,2) = 1.03755; + mat33(2,0) = 0.450516; + mat33(2,1) = 1.08225; + mat33(2,2) = 0.972831; + + const BoundedMatrix inv33 = MathUtils::InvertMatrix<3>(mat33, det); + const BoundedMatrix I33 = prod(inv33, mat33); + + for (unsigned int i = 0; i < 3; i++) + { + for (unsigned int j = 0; j < 3; j++) + { + if (i == j) + { + KRATOS_CHECK_NEAR(I33(i,j), 1.0, tolerance); + } + else + { + KRATOS_CHECK_NEAR(I33(i,j), 0.0, tolerance); + } + } + } + + BoundedMatrix mat44; + mat44(0,0) = 0.00959158; + mat44(0,1) = 0.466699; + mat44(0,2) = 0.167357; + mat44(0,3) = 0.255465; + mat44(1,0) = 1.6356; + mat44(1,1) = 0.387988; + mat44(1,2) = 1.17823; + mat44(1,3) = 1.38661; + mat44(2,0) = 2.57105; + mat44(2,1) = 1.63057; + mat44(2,2) = 2.5713; + mat44(2,3) = 1.73297; + mat44(3,0) = 3.40005; + mat44(3,1) = 1.94218; + mat44(3,2) = 2.58081; + mat44(3,3) = 3.3083; + + const BoundedMatrix inv44 = MathUtils::InvertMatrix<4>(mat44, det); + const BoundedMatrix I44 = prod(inv44, mat44); + + for (unsigned int i = 0; i < 4; i++) + { + for (unsigned int j = 0; j < 4; j++) + { + if (i == j) + { + KRATOS_CHECK_NEAR(I44(i,j), 1.0, tolerance); + } + else + { + KRATOS_CHECK_NEAR(I44(i,j), 0.0, tolerance); + } + } + } + } + + /** Checks if it calculates the inverse of a 1x1, 2x2, 3x3 and 4x4 matrix + * Checks if it calculates the inverse of a 1x1, 2x2, 3x3 and 4x4 matrix + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsInvertMatrix, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + double det; + Matrix inv(1,1); + Matrix I(1,1); + + unsigned int i_dim = 1; + + Matrix mat = ZeroMatrix(i_dim, i_dim); + + mat(0,0) = 0.346432; + + MathUtils::InvertMatrix(mat,inv, det); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) { + for (unsigned int j = 0; j < i_dim; j++) { + if (i == j) { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } else { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + + i_dim = 2; + mat.resize(i_dim, i_dim, false); + inv.resize(i_dim, i_dim, false); + I.resize(i_dim, i_dim, false); + + mat(0,0) = 0.833328; + mat(0,1) = 0.491166; + mat(1,0) = 0.81167; + mat(1,1) = 1.17205; + + MathUtils::InvertMatrix(mat,inv, det); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) { + for (unsigned int j = 0; j < i_dim; j++) { + if (i == j) { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } else { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + + i_dim = 3; + mat.resize(i_dim, i_dim, false); + inv.resize(i_dim, i_dim, false); + I.resize(i_dim, i_dim, false); + + mat(0,0) = 0.371083; + mat(0,1) = 0.392607; + mat(0,2) = 0.306494; + mat(1,0) = 0.591012; + mat(1,1) = 1.00733; + mat(1,2) = 1.07727; + mat(2,0) = 0.0976054; + mat(2,1) = 2.54893; + mat(2,2) = 1.23981; + + MathUtils::InvertMatrix(mat,inv, det); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) { + for (unsigned int j = 0; j < i_dim; j++) { + if (i == j) { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } else { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + + i_dim = 4; + mat.resize(i_dim, i_dim, false); + inv.resize(i_dim, i_dim, false); + I.resize(i_dim, i_dim, false); + + mat(0,0) = 0.0; + mat(0,1) = 0.979749; + mat(0,2) = 0.494393; + mat(0,3) = 0.23073; + mat(1,0) = 1.79224; + mat(1,1) = 0.198842; + mat(1,2) = 0.074485; + mat(1,3) = 1.45717; + mat(2,0) = 1.6039; + mat(2,1) = 0.673926; + mat(2,2) = 2.63817; + mat(2,3) = 1.0287; + mat(3,0) = 0.366503; + mat(3,1) = 3.02634; + mat(3,2) = 1.24104; + mat(3,3) = 3.62022; + + MathUtils::InvertMatrix(mat,inv, det); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) { + for (unsigned int j = 0; j < i_dim; j++) { + if (i == j) { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } else { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + + i_dim = 5; + mat.resize(i_dim, i_dim, false); + inv.resize(i_dim, i_dim, false); + I.resize(i_dim, i_dim, false); + + mat = ZeroMatrix(5, 5); + mat(0,0) = 1.0; + mat(1,1) = 1.0; + mat(2,2) = 1.0; + mat(3,3) = 1.0; + mat(2,3) = - 1.0; + mat(3,2) = 1.0; + mat(4,4) = 2.0; + + MathUtils::InvertMatrix(mat,inv, det); + + KRATOS_CHECK_NEAR(det, 4.0, tolerance); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) { + for (unsigned int j = 0; j < i_dim; j++) { + if (i == j) { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } else { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + } + + /** Checks if it can solve a dense system of equations + * Checks if it can solve a dense system of equations + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsSolve, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + const std::size_t i_dim = 4; + double det; + Matrix A(i_dim, i_dim); + Matrix inv(i_dim, i_dim); + Vector b(i_dim); + + A(0,0) = 0.0; + A(0,1) = 0.979749; + A(0,2) = 0.494393; + A(0,3) = 0.23073; + A(1,0) = 1.79224; + A(1,1) = 0.198842; + A(1,2) = 0.074485; + A(1,3) = 1.45717; + A(2,0) = 1.6039; + A(2,1) = 0.673926; + A(2,2) = 2.63817; + A(2,3) = 1.0287; + A(3,0) = 0.366503; + A(3,1) = 3.02634; + A(3,2) = 1.24104; + A(3,3) = 3.62022; + + b[0] = 0.0; + b[1] = 1.0; + b[2] = 2.0; + b[3] = 3.0; + + MathUtils::InvertMatrix(A,inv, det); + + const Vector ref_x = prod(inv, b); + Vector x; + + MathUtils::Solve(A,x,b); + + for (std::size_t i = 0; i < i_dim; i++) { + KRATOS_CHECK_NEAR(ref_x[i], x[i], tolerance); + } + } + + /** Checks if it calculates correctly the inverse of a non square matrix + * Checks if it calculates correctly the inverse of a non square matrix + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsGeneralizedInvertMatrix, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + // We check the Left inverse + + const unsigned int i_dim = 2; + const unsigned int j_dim = 3; + + Matrix mat = ZeroMatrix(i_dim, j_dim); + + mat(0,0) = 0.770724; + mat(1,0) = 0.573294; + mat(0,1) = 1.27699; + mat(1,1) = 1.57776; + mat(0,2) = 1.30216; + mat(1,2) = 2.66483; + + double det; + Matrix inv; + + MathUtils::GeneralizedInvertMatrix(mat,inv, det); + + Matrix I = prod(mat, inv); + + for (unsigned int i = 0; i < i_dim; i++) + { + for (unsigned int j = 0; j < i_dim; j++) + { + if (i == j) + { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } + else + { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + + // We check the Right inverse + mat.resize(j_dim, i_dim, false); + mat = ZeroMatrix(j_dim, i_dim); + + mat(0,0) = 0.786075; + mat(1,0) = 0.91272; + mat(2,0) = 0.745604; + mat(0,1) = 0.992728; + mat(1,1) = 1.82324; + mat(2,1) = 0.19581; + + MathUtils::GeneralizedInvertMatrix(mat,inv, det); + + I = prod(inv, mat); + + for (unsigned int i = 0; i < i_dim; i++) + { + for (unsigned int j = 0; j < i_dim; j++) + { + if (i == j) + { + KRATOS_CHECK_NEAR(I(i,j), 1.0, tolerance); + } + else + { + KRATOS_CHECK_NEAR(I(i,j), 0.0, tolerance); + } + } + } + } + + /** Checks if it calculates the sign function + * Checks if it calculates the sign function + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsSign, KratosCoreFastSuite) + { + int sign = MathUtils::Sign(-1.0); + + KRATOS_CHECK_EQUAL(sign, -1); + + sign = MathUtils::Sign(1.0); + + KRATOS_CHECK_EQUAL(sign, 1); + } + + /** Checks if it calculates the eigen decomposition of a 3x3 system + * Checks if it calculates the eigen decomposition of a 3x3 system + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsEigen, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + BoundedMatrix mat33; + BoundedMatrix eigenmat33; + BoundedMatrix vectormat33; + + mat33(0,0) = 0.678589; + mat33(0,1) = 0.386213; + mat33(0,2) = 0.371126; + mat33(1,0) = mat33(0,1); + mat33(1,1) = 0.403437; + mat33(1,2) = 1.03755; + mat33(2,0) = mat33(0,2); + mat33(2,1) = mat33(1,2); + mat33(2,2) = 0.972831; + + bool converged = MathUtils::EigenSystem<3>(mat33, vectormat33, eigenmat33); + + BoundedMatrix othermat33 = prod(trans(vectormat33), eigenmat33); + BoundedMatrix auxmat33 = prod(othermat33, vectormat33); + + for (unsigned int i = 0; i < 3; i++) + { + for (unsigned int j = i; j < 3; j++) + { + KRATOS_CHECK_NEAR(auxmat33(i,j), mat33(i,j), tolerance); + } + } + + KRATOS_CHECK_EQUAL(converged, true); + } + + /** Checks if it calculates the dot product + * Checks if it calculates the dot product + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsDot, KratosCoreFastSuite) + { + Vector a = ZeroVector(3); + a[1] = 1.0; + Vector b = ZeroVector(3); + b[0] = 1.0; + + const double c = MathUtils::Dot3(a, b); + const double d = MathUtils::Dot(a, b); + + KRATOS_CHECK_EQUAL(c, 0.0); + KRATOS_CHECK_EQUAL(d, 0.0); + } + + /** Checks if it calculates the norm of a vector + * Checks if it calculates the norm of a vector + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsNorm, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + a[0] = 1.0; + + const double b = MathUtils::Norm3(a); + const double c = MathUtils::Norm(a); + + KRATOS_CHECK_EQUAL(b, 1.0); + KRATOS_CHECK_EQUAL(c, 1.0); + } + + /** Checks if it calculates the norm of a vector without underflow + * Checks if it calculates the norm of a vector without underflow + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsStableNormUnderflow, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + a[0] = 1e-162; + + const double b = MathUtils::StableNorm(a); + + KRATOS_CHECK_EQUAL(b, 1e-162); + } + + /** Checks if it calculates the norm of a vector without overflow + * Checks if it calculates the norm of a vector without overflow + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsStableNormOverflow, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + a[0] = 1e155; + + const double b = MathUtils::StableNorm(a); + + KRATOS_CHECK_EQUAL(b, 1e155); + } + + /** Checks if it calculates the cross product (I) + * Checks if it calculates the cross product (I) + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsVectorAngleTest1, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + array_1d b = ZeroVector(3); + a[0] = 1.0; + b[1] = 1.0; + + const double angle = MathUtils::VectorsAngle(b, a); + + KRATOS_CHECK_EQUAL(angle, Globals::Pi/2.0); + } + + /** Checks if it calculates the cross product (II) + * Checks if it calculates the cross product (II) + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsVectorAngleTest2, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + array_1d b = ZeroVector(3); + a[0] = 1.0; + b[0] = -1.0; + + const double angle = MathUtils::VectorsAngle(b, a); + + KRATOS_CHECK_EQUAL(angle, Globals::Pi); + } + + /** Checks if it calculates the cross product (III) + * Checks if it calculates the cross product (III) + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsVectorAngleTest3, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + array_1d b = ZeroVector(3); + a[0] = 1.0; + a[2] = 1.0; + a /= norm_2(a); + b[1] = -1.0; + b[2] = 1.0; + b /= norm_2(b); + + const double angle = MathUtils::VectorsAngle(b, a); + + KRATOS_CHECK_EQUAL(angle, Globals::Pi/3.0); + } + + /** Checks if it calculates the angle between two vectors + * Checks if it calculates the angle between two vectors + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsCross, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + a[1] = 2.0; + array_1d b = ZeroVector(3); + b[0] = 1.0; + + array_1d c, d; + + MathUtils::CrossProduct(c, b, a); + MathUtils::UnitCrossProduct(d, b, a); + + KRATOS_CHECK_EQUAL(c[2], 2.0); + KRATOS_CHECK_EQUAL(d[2], 1.0); + } + + /** Checks if it calculates the orthonormal base + * Checks if it calculates the orthonormal base + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsOrthonormalBasis, KratosCoreFastSuite) + { + array_1d a = ZeroVector(3); + a[1] = 1.0; + + array_1d b, c; + + MathUtils::OrthonormalBasisHughesMoeller(a, b, c); + + KRATOS_CHECK_EQUAL(b[0], 1.0); + KRATOS_CHECK_EQUAL(c[2], -1.0); + + MathUtils::OrthonormalBasisFrisvad(a, b, c); + + KRATOS_CHECK_EQUAL(b[0], 1.0); + KRATOS_CHECK_EQUAL(c[2], -1.0); + + MathUtils::OrthonormalBasisNaive(a, b, c); + + + KRATOS_CHECK_EQUAL(b[0], 1.0); + KRATOS_CHECK_EQUAL(c[2], -1.0); + } + + /** Checks if it calculates the tensor product + * Checks if it calculates the tensor product + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsTensor, KratosCoreFastSuite) + { + Vector a = ZeroVector(3); + a[1] = 2.0; + Vector b = ZeroVector(3); + b[0] = 1.0; + + const Matrix c = MathUtils::TensorProduct3(a, b); + + KRATOS_CHECK_EQUAL(c(0,0), 0.0); + KRATOS_CHECK_EQUAL(c(1,0), 2.0); + KRATOS_CHECK_EQUAL(c(0,1), 0.0); + KRATOS_CHECK_EQUAL(c(1,1), 0.0); + } + + /** Checks if it calculates the matrix operations + * Checks if it calculates the matrix operations + */ + + KRATOS_TEST_CASE_IN_SUITE(MathUtilsMatrixOperations, KratosCoreFastSuite) + { + Matrix a = IdentityMatrix(3); + Matrix b = IdentityMatrix(3); + + MathUtils::AddMatrix(a, b, 0 ,0); + + KRATOS_CHECK_EQUAL(a(0,0), 2.0); + KRATOS_CHECK_EQUAL(a(1,0), 0.0); + KRATOS_CHECK_EQUAL(a(0,1), 0.0); + KRATOS_CHECK_EQUAL(a(1,1), 2.0); + + MathUtils::SubtractMatrix(a, b, 0 ,0); + + KRATOS_CHECK_EQUAL(a(0,0), 1.0); + KRATOS_CHECK_EQUAL(a(1,0), 0.0); + KRATOS_CHECK_EQUAL(a(0,1), 0.0); + KRATOS_CHECK_EQUAL(a(1,1), 1.0); + + MathUtils::WriteMatrix(a, b, 0 ,0); + + KRATOS_CHECK_EQUAL(a(0,0), 1.0); + KRATOS_CHECK_EQUAL(a(1,0), 0.0); + KRATOS_CHECK_EQUAL(a(0,1), 0.0); + KRATOS_CHECK_EQUAL(a(1,1), 1.0); + } + + } // namespace Testing +} // namespace Kratos. + diff --git a/kratos/tests/cpp_tests/utilities/test_plane_approximation_utility.cpp b/kratos/tests/cpp_tests/utilities/test_plane_approximation_utility.cpp new file mode 100644 index 000000000000..c9f48b628cf8 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_plane_approximation_utility.cpp @@ -0,0 +1,140 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Ruben Zorrilla +// +// + +// Project includes +#include "geometries/point.h" +#include "includes/checks.h" +#include "testing/testing.h" +#include "utilities/plane_approximation_utility.h" + +namespace Kratos { +namespace Testing { + + KRATOS_TEST_CASE_IN_SUITE(PlaneApproximationUtilityTriangle, KratosCoreFastSuite) + { + // Set of points to be approximated by the plane + Point point_1(0.0, 0.0, 0.0); + Point point_2(1.0, 0.0, 0.0); + Point point_3(0.5, 1.0, 0.0); + + // Fill the array of coordinates + std::vector< array_1d > points_coordinates; + points_coordinates.push_back(point_1.Coordinates()); + points_coordinates.push_back(point_2.Coordinates()); + points_coordinates.push_back(point_3.Coordinates()); + + // Compute the plane approximation + array_1d base_point_coords, normal; + PlaneApproximationUtility<2>::ComputePlaneApproximation(points_coordinates, base_point_coords, normal); + + // Compute and check the obtained plane distance values + const double d_1 = inner_prod(normal , point_1.Coordinates() - base_point_coords); + const double d_2 = inner_prod(normal , point_2.Coordinates() - base_point_coords); + const double d_3 = inner_prod(normal , point_3.Coordinates() - base_point_coords); + + KRATOS_CHECK_NEAR(d_1, -0.5, 1e-6); + KRATOS_CHECK_NEAR(d_2, 0.5, 1e-6); + KRATOS_CHECK_NEAR(d_3, 0.0, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(PlaneApproximationUtilityDiamond, KratosCoreFastSuite) + { + // Set of points to be approximated by the plane + Point point_1(0.0, 0.0, 0.0); + Point point_2(1.0, 0.0, 0.0); + Point point_3(0.5, 1.0, 0.0); + Point point_4(1.5, 1.0, 0.0); + + // Fill the array of coordinates + std::vector< array_1d > points_coordinates; + points_coordinates.push_back(point_1.Coordinates()); + points_coordinates.push_back(point_2.Coordinates()); + points_coordinates.push_back(point_3.Coordinates()); + points_coordinates.push_back(point_4.Coordinates()); + + // Compute the plane approximation + array_1d base_point_coords, normal; + PlaneApproximationUtility<2>::ComputePlaneApproximation(points_coordinates, base_point_coords, normal); + + // Compute and check the obtained plane distance values + const double d_1 = inner_prod(normal , point_1.Coordinates() - base_point_coords); + const double d_2 = inner_prod(normal , point_2.Coordinates() - base_point_coords); + const double d_3 = inner_prod(normal , point_3.Coordinates() - base_point_coords); + const double d_4 = inner_prod(normal , point_4.Coordinates() - base_point_coords); + + KRATOS_CHECK_NEAR(d_1, 0.0674564, 1e-6); + KRATOS_CHECK_NEAR(d_2, -0.547956, 1e-6); + KRATOS_CHECK_NEAR(d_3, 0.547956, 1e-6); + KRATOS_CHECK_NEAR(d_4, -0.0674564, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(PlaneApproximationUtilityCircleTriangleIntersection, KratosCoreFastSuite) + { + // Set of points to be approximated by the plane + Point point_1(0.9, 0.0, 0.0); + Point point_2(0.0, 0.9, 0.0); + Point point_3(0.8937, 0.1063, 0.0); + Point point_4(0.1063, 0.8937, 0.0); + + // Fill the array of coordinates + std::vector< array_1d > points_coordinates; + points_coordinates.push_back(point_1.Coordinates()); + points_coordinates.push_back(point_2.Coordinates()); + points_coordinates.push_back(point_3.Coordinates()); + points_coordinates.push_back(point_4.Coordinates()); + + // Compute the plane approximation + array_1d base_point_coords, normal; + PlaneApproximationUtility<2>::ComputePlaneApproximation(points_coordinates, base_point_coords, normal); + + // Compute and check the obtained plane distance values + const double d_1 = inner_prod(normal , point_1.Coordinates() - base_point_coords); + const double d_2 = inner_prod(normal , point_2.Coordinates() - base_point_coords); + const double d_3 = inner_prod(normal , point_3.Coordinates() - base_point_coords); + const double d_4 = inner_prod(normal , point_4.Coordinates() - base_point_coords); + + KRATOS_CHECK_NEAR(d_1, -0.0353553, 1e-6); + KRATOS_CHECK_NEAR(d_2, -0.0353553, 1e-6); + KRATOS_CHECK_NEAR(d_3, 0.0353553, 1e-6); + KRATOS_CHECK_NEAR(d_4, 0.0353553, 1e-6); + } + + KRATOS_TEST_CASE_IN_SUITE(PlaneApproximationUtilityAlignedIntersection, KratosCoreFastSuite) + { + // Set of points to be approximated by the plane + // Note that they are selected such that, a 2D case is solved in 3D + Point point_1(0.0, 0.0, 0.0); + Point point_2(1.0, 0.0, 0.0); + Point point_3(0.0, 1.0, 0.0); + + // Fill the array of coordinates + std::vector< array_1d > points_coordinates; + points_coordinates.push_back(point_1.Coordinates()); + points_coordinates.push_back(point_2.Coordinates()); + points_coordinates.push_back(point_3.Coordinates()); + + // Compute the plane approximation + array_1d base_point_coords, normal; + PlaneApproximationUtility<3>::ComputePlaneApproximation(points_coordinates, base_point_coords, normal); + + // Compute and check the obtained plane values + KRATOS_CHECK_NEAR(base_point_coords[0], 1.0/3.0, 1e-6); + KRATOS_CHECK_NEAR(base_point_coords[1], 1.0/3.0, 1e-6); + KRATOS_CHECK_NEAR(base_point_coords[2], 0.0, 1e-6); + KRATOS_CHECK_NEAR(normal[0], 0.0, 1e-6); + KRATOS_CHECK_NEAR(normal[1], 0.0, 1e-6); + KRATOS_CHECK_NEAR(normal[2], 1.0, 1e-6); + } + +} // namespace Testing. +} // namespace Kratos. diff --git a/kratos/tests/cpp_tests/utilities/test_stl_io.cpp b/kratos/tests/cpp_tests/utilities/test_stl_io.cpp new file mode 100644 index 000000000000..a5de88550b01 --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_stl_io.cpp @@ -0,0 +1,47 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Philipp Bucher +// +// + + +// Project includes +#include "testing/testing.h" +#include "utilities/stl_io.h" + + +namespace Kratos { +namespace Testing { + +KRATOS_TEST_CASE_IN_SUITE(StdVectorOutputStream, KratosCoreFastSuite) +{ + using Kratos::operator<<; // needed bcs it is inside the namespace "Testing" + + std::vector int_vector {1,5,-63,581,6}; + std::vector double_vector {4.335, 8.639, -888.47, 9874.0}; + std::vector string_vector {"val_1", "custom", "again_test"}; + + std::stringstream ss_int; + ss_int << int_vector; + KRATOS_CHECK_EQUAL(ss_int.str(), "[1, 5, -63, 581, 6]"); + + std::stringstream ss_double; + ss_double << double_vector; + KRATOS_CHECK_EQUAL(ss_double.str(), "[4.335, 8.639, -888.47, 9874]"); + + std::stringstream ss_string; + ss_string << string_vector; + KRATOS_CHECK_EQUAL(ss_string.str(), "[val_1, custom, again_test]"); +} + +} // namespace Testing +} // namespace Kratos. + + diff --git a/kratos/tests/cpp_tests/utilities/test_svd_utils.cpp b/kratos/tests/cpp_tests/utilities/test_svd_utils.cpp new file mode 100644 index 000000000000..9569e5e3d0cf --- /dev/null +++ b/kratos/tests/cpp_tests/utilities/test_svd_utils.cpp @@ -0,0 +1,126 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Vicente Mataix Ferrandiz +// + +// System includes +#include + +// External includes + +// Project includes +#include "testing/testing.h" +#include "utilities/svd_utils.h" + +// TODO: Move thid to the proper folder + +namespace Kratos +{ + namespace Testing + { + /// Tests + + /** Checks if it calculates the SVD of a matrix 2x2 + * Checks if it calculates the SVD of a matrix 2x2 + */ + KRATOS_TEST_CASE_IN_SUITE(SVDUtilsjacobiSVD2x2Test, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-6; + + Matrix a_matrix, u_matrix, s_matrix, v_matrix; + + a_matrix.resize(2, 2,false); + a_matrix(0,0) = 0.57690; + a_matrix(0,1) = 0.28760; + a_matrix(1,0) = 0.72886; + a_matrix(1,1) = 0.40541; + + SVDUtils::JacobiSingularValueDecomposition(a_matrix, u_matrix, s_matrix, v_matrix); + + // Check decomposition is correct + const Matrix auxmat22 = prod(u_matrix, Matrix(prod(s_matrix,v_matrix))); + + for (std::size_t i = 0; i < 2; ++i) { + for (std::size_t j = i; j < 2; ++j) { + KRATOS_CHECK_NEAR(auxmat22(i,j), a_matrix(i,j), tolerance); + } + } + + // Check SV are correct (value and order) + KRATOS_CHECK_NEAR(s_matrix(0,0), 1.053846, tolerance); + KRATOS_CHECK_NEAR(s_matrix(1,1), 0.023021, tolerance); + } + + /** Checks if it calculates the SVD of a matrix 3x3 + * Checks if it calculates the SVD of a matrix 3x3 + */ + KRATOS_TEST_CASE_IN_SUITE(SVDUtilsJacobiSVD3x3Test, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-4; + + Matrix a_matrix, u_matrix, s_matrix, v_matrix; + + a_matrix.resize(3, 3, false); + a_matrix(0,0) = 0.57690; + a_matrix(0,1) = 0.28760; + a_matrix(0,2) = 0.63942; + a_matrix(1,0) = 0.72886; + a_matrix(1,1) = 0.40541; + a_matrix(1,2) = 0.13415; + a_matrix(2,0) = 0.81972; + a_matrix(2,1) = 0.54501; + a_matrix(2,2) = 0.28974; + + SVDUtils::JacobiSingularValueDecomposition(a_matrix, u_matrix, s_matrix, v_matrix); + + // Check decomposition is correct + Matrix auxmat33 = prod(u_matrix, Matrix(prod(s_matrix,v_matrix))); + + for (std::size_t i = 0; i < 3; ++i) { + for (std::size_t j = i; j < 3; ++j) { + KRATOS_CHECK_NEAR(auxmat33(i,j), a_matrix(i,j), tolerance); + } + } + + // Check SV are correct (value and order) + KRATOS_CHECK_NEAR(s_matrix(0,0), 1.554701, tolerance); + KRATOS_CHECK_NEAR(s_matrix(1,1), 0.412674, tolerance); + KRATOS_CHECK_NEAR(s_matrix(2,2), 0.059198, tolerance); + } + + /** Checks if it calculates the condition number of a matrix + * Checks if it calculates the condition number of a matrix + */ + KRATOS_TEST_CASE_IN_SUITE(SVDUtilsConditionNumberTest, KratosCoreFastSuite) + { + constexpr double tolerance = 1e-4; + + Matrix a_matrix, u_matrix, s_matrix, v_matrix; + + a_matrix.resize(3, 3, false); + a_matrix(0,0) = 0.57690; + a_matrix(0,1) = 0.28760; + a_matrix(0,2) = 0.63942; + a_matrix(1,0) = 0.72886; + a_matrix(1,1) = 0.40541; + a_matrix(1,2) = 0.13415; + a_matrix(2,0) = 0.81972; + a_matrix(2,1) = 0.54501; + a_matrix(2,2) = 0.28974; + + const double condition_number = SVDUtils::SVDConditionNumber(a_matrix); // NOTE: Considering the default tolerance + + // Check condition number is correct + KRATOS_CHECK_NEAR(condition_number, 26.2607, tolerance); + } + + } // namespace Testing +} // namespace Kratos. + From 77c9b00b0fd4c20befe846bd595e85a535e5e214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 11 Dec 2018 15:42:18 +0100 Subject: [PATCH 19/31] Revert conflict --- .../test_compute_nodal_gradient_process.cpp | 255 +++++++++++++++--- 1 file changed, 213 insertions(+), 42 deletions(-) diff --git a/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp index c997f530d98d..37606adba997 100644 --- a/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp @@ -17,7 +17,9 @@ // Project includes #include "containers/model.h" #include "geometries/triangle_2d_3.h" +#include "geometries/quadrilateral_2d_4.h" #include "geometries/tetrahedra_3d_4.h" +#include "geometries/hexahedra_3d_8.h" #include "testing/testing.h" #include "includes/kratos_flags.h" #include "includes/gid_io.h" @@ -45,7 +47,7 @@ namespace Kratos gid_io.WriteNodalResults(DISTANCE_GRADIENT, ThisModelPart.Nodes(), label, 0); } - /** + /** * Checks the correct work of the nodal gradient compute * Test triangle */ @@ -53,79 +55,83 @@ namespace Kratos KRATOS_TEST_CASE_IN_SUITE(NodalGradient1, KratosCoreFastSuite) { Model current_model; - + ModelPart& this_model_part = current_model.CreateModelPart("Main"); this_model_part.SetBufferSize(2); - + this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); - + auto& process_info = this_model_part.GetProcessInfo(); process_info[STEP] = 1; process_info[NL_ITERATION_NUMBER] = 1; - - // First we create the nodes + + // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); - + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + // Now we create the "conditions" std::vector element_nodes_0 (3); element_nodes_0[0] = p_node_1; element_nodes_0[1] = p_node_2; element_nodes_0[2] = p_node_3; Triangle2D3 triangle_0( PointerVector{element_nodes_0} ); - + std::vector element_nodes_1 (3); element_nodes_1[0] = p_node_1; element_nodes_1[1] = p_node_3; element_nodes_1[2] = p_node_4; Triangle2D3 triangle_1( PointerVector{element_nodes_1} ); - + std::vector element_nodes_2 (3); element_nodes_2[0] = p_node_2; element_nodes_2[1] = p_node_5; element_nodes_2[2] = p_node_3; Triangle2D3 triangle_2( PointerVector{element_nodes_2} ); - + std::vector element_nodes_3 (3); element_nodes_3[0] = p_node_5; element_nodes_3[1] = p_node_6; element_nodes_3[2] = p_node_3; Triangle2D3 triangle_3( PointerVector{element_nodes_3} ); - + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D3N", 1, triangle_0, p_elem_prop); Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D3N", 2, triangle_1, p_elem_prop); Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element2D3N", 3, triangle_2, p_elem_prop); Element::Pointer p_elem_3 = this_model_part.CreateNewElement("Element2D3N", 4, triangle_3, p_elem_prop); - + // Set DISTANCE for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_AREA, 0.0); } - - typedef ComputeNodalGradientProcess<2, Variable, Historical> GradientType; + + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); - -// // DEBUG + +// // DEBUG // GiDIODebugGradient(this_model_part); - + const double tolerance = 1.0e-8; KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_6->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); } - - /** + + /** * Checks the correct work of the nodal gradient compute * Test tetrahedra */ @@ -136,31 +142,35 @@ namespace Kratos ModelPart& this_model_part = current_model.CreateModelPart("Main"); this_model_part.SetBufferSize(2); - + this_model_part.AddNodalSolutionStepVariable(DISTANCE); this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); - + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); - + auto& process_info = this_model_part.GetProcessInfo(); process_info[STEP] = 1; process_info[NL_ITERATION_NUMBER] = 1; - - // First we create the nodes + + // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); - + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); - + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + // Now we create the "conditions" std::vector element_nodes_0 (4); element_nodes_0[0] = p_node_12; @@ -168,84 +178,84 @@ namespace Kratos element_nodes_0[2] = p_node_8; element_nodes_0[3] = p_node_9; Tetrahedra3D4 tetrahedra_0( PointerVector{element_nodes_0} ); - + std::vector element_nodes_1 (4); element_nodes_1[0] = p_node_4; element_nodes_1[1] = p_node_6; element_nodes_1[2] = p_node_9; element_nodes_1[3] = p_node_7; Tetrahedra3D4 tetrahedra_1( PointerVector{element_nodes_1} ); - + std::vector element_nodes_2 (4); element_nodes_2[0] = p_node_11; element_nodes_2[1] = p_node_7; element_nodes_2[2] = p_node_9; element_nodes_2[3] = p_node_8; Tetrahedra3D4 tetrahedra_2( PointerVector{element_nodes_2} ); - + std::vector element_nodes_3 (4); element_nodes_3[0] = p_node_5; element_nodes_3[1] = p_node_3; element_nodes_3[2] = p_node_8; element_nodes_3[3] = p_node_6; Tetrahedra3D4 tetrahedra_3( PointerVector{element_nodes_3} ); - + std::vector element_nodes_4 (4); element_nodes_4[0] = p_node_4; element_nodes_4[1] = p_node_6; element_nodes_4[2] = p_node_7; element_nodes_4[3] = p_node_3; Tetrahedra3D4 tetrahedra_4( PointerVector{element_nodes_4} ); - + std::vector element_nodes_5 (4); element_nodes_5[0] = p_node_2; element_nodes_5[1] = p_node_3; element_nodes_5[2] = p_node_5; element_nodes_5[3] = p_node_6; Tetrahedra3D4 tetrahedra_5( PointerVector{element_nodes_5} ); - + std::vector element_nodes_6 (4); element_nodes_6[0] = p_node_10; element_nodes_6[1] = p_node_9; element_nodes_6[2] = p_node_6; element_nodes_6[3] = p_node_8; Tetrahedra3D4 tetrahedra_6( PointerVector{element_nodes_6} ); - + std::vector element_nodes_7 (4); element_nodes_7[0] = p_node_7; element_nodes_7[1] = p_node_8; element_nodes_7[2] = p_node_3; element_nodes_7[3] = p_node_6; Tetrahedra3D4 tetrahedra_7( PointerVector{element_nodes_7} ); - + std::vector element_nodes_8 (4); element_nodes_8[0] = p_node_7; element_nodes_8[1] = p_node_8; element_nodes_8[2] = p_node_6; element_nodes_8[3] = p_node_9; Tetrahedra3D4 tetrahedra_8( PointerVector{element_nodes_8} ); - + std::vector element_nodes_9 (4); element_nodes_9[0] = p_node_4; element_nodes_9[1] = p_node_1; element_nodes_9[2] = p_node_6; element_nodes_9[3] = p_node_3; Tetrahedra3D4 tetrahedra_9( PointerVector{element_nodes_9} ); - + std::vector element_nodes_10 (4); element_nodes_10[0] = p_node_9; element_nodes_10[1] = p_node_12; element_nodes_10[2] = p_node_11; element_nodes_10[3] = p_node_8; Tetrahedra3D4 tetrahedra_10( PointerVector{element_nodes_10} ); - + std::vector element_nodes_11 (4); element_nodes_11[0] = p_node_3; element_nodes_11[1] = p_node_2; element_nodes_11[2] = p_node_1; element_nodes_11[3] = p_node_6; Tetrahedra3D4 tetrahedra_11( PointerVector{element_nodes_11} ); - + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D4N", 1, tetrahedra_0, p_elem_prop); Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D4N", 2, tetrahedra_1, p_elem_prop); Element::Pointer p_elem_2 = this_model_part.CreateNewElement("Element3D4N", 3, tetrahedra_2, p_elem_prop); @@ -258,22 +268,183 @@ namespace Kratos Element::Pointer p_elem_9 = this_model_part.CreateNewElement("Element3D4N", 10, tetrahedra_9, p_elem_prop); Element::Pointer p_elem_10 = this_model_part.CreateNewElement("Element3D4N", 11, tetrahedra_10, p_elem_prop); Element::Pointer p_elem_11 = this_model_part.CreateNewElement("Element3D4N", 12, tetrahedra_11, p_elem_prop); - + // Set DISTANCE for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { auto it_node = this_model_part.Nodes().begin() + i_node; it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; it_node->SetValue(NODAL_AREA, 0.0); } - + // Compute gradient - typedef ComputeNodalGradientProcess<3, Variable, Historical> GradientType; + typedef ComputeNodalGradientProcess GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_3->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_9->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_10->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_11->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_12->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test quadrilateral + */ + KRATOS_TEST_CASE_IN_SUITE(NodalGradient3, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2, 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3, 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4, 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5, 2.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6, 2.0 , 1.0 , 0.0); + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (4); + element_nodes_0[0] = p_node_1; + element_nodes_0[1] = p_node_2; + element_nodes_0[2] = p_node_3; + element_nodes_0[3] = p_node_4; + Quadrilateral2D4 quadrilateral_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (4); + element_nodes_1[0] = p_node_2; + element_nodes_1[1] = p_node_5; + element_nodes_1[2] = p_node_6; + element_nodes_1[3] = p_node_3; + Quadrilateral2D4 quadrilateral_1( PointerVector{element_nodes_1} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element2D4N", 1, quadrilateral_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element2D4N", 2, quadrilateral_1, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + typedef ComputeNodalGradientProcess GradientType; GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); process.Execute(); // // DEBUG // GiDIODebugGradient(this_model_part); + const double tolerance = 1.0e-8; + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_5->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_6->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); + } + + /** + * Checks the correct work of the nodal gradient compute + * Test hexahedra + */ + KRATOS_TEST_CASE_IN_SUITE(NodalGradient4, KratosCoreFastSuite) + { + Model current_model; + + ModelPart& this_model_part = current_model.CreateModelPart("Main"); + this_model_part.SetBufferSize(2); + + this_model_part.AddNodalSolutionStepVariable(DISTANCE); + this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); + + Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); + + auto& process_info = this_model_part.GetProcessInfo(); + process_info[STEP] = 1; + process_info[NL_ITERATION_NUMBER] = 1; + + // First we create the nodes + NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); + NodeType::Pointer p_node_2 = this_model_part.CreateNewNode(2 , 0.0 , 1.0 , 0.0); + NodeType::Pointer p_node_3 = this_model_part.CreateNewNode(3 , 0.0 , 0.0 , 1.0); + NodeType::Pointer p_node_4 = this_model_part.CreateNewNode(4 , 1.0 , 1.0 , 1.0); + NodeType::Pointer p_node_5 = this_model_part.CreateNewNode(5 , 0.0 , 0.0 , 0.0); + NodeType::Pointer p_node_6 = this_model_part.CreateNewNode(6 , 1.0 , 1.0 , 0.0); + NodeType::Pointer p_node_7 = this_model_part.CreateNewNode(7 , 1.0 , 0.0 , 1.0); + NodeType::Pointer p_node_8 = this_model_part.CreateNewNode(8 , 1.0 , 0.0 , 0.0); + NodeType::Pointer p_node_9 = this_model_part.CreateNewNode(9 , 2.0 , 1.0 , 1.0); + NodeType::Pointer p_node_10 = this_model_part.CreateNewNode(10 , 2.0 , 1.0 , 0.0); + NodeType::Pointer p_node_11 = this_model_part.CreateNewNode(11 , 2.0 , 0.0 , 1.0); + NodeType::Pointer p_node_12 = this_model_part.CreateNewNode(12 , 2.0 , 0.0 , 0.0); + + // Initialize nodal area + for (auto& node : this_model_part.Nodes()) + node.SetValue(NODAL_AREA, 0.0); + + // Now we create the "conditions" + std::vector element_nodes_0 (8); + element_nodes_0[0] = p_node_5; + element_nodes_0[1] = p_node_8; + element_nodes_0[2] = p_node_6; + element_nodes_0[3] = p_node_2; + element_nodes_0[4] = p_node_3; + element_nodes_0[5] = p_node_7; + element_nodes_0[6] = p_node_4; + element_nodes_0[7] = p_node_1; + Hexahedra3D8 hexahedra_0( PointerVector{element_nodes_0} ); + + std::vector element_nodes_1 (8); + element_nodes_1[0] = p_node_8; + element_nodes_1[1] = p_node_12; + element_nodes_1[2] = p_node_10; + element_nodes_1[3] = p_node_6; + element_nodes_1[4] = p_node_7; + element_nodes_1[5] = p_node_11; + element_nodes_1[6] = p_node_9; + element_nodes_1[7] = p_node_4; + Hexahedra3D8 hexahedra_1( PointerVector{element_nodes_1} ); + + Element::Pointer p_elem_0 = this_model_part.CreateNewElement("Element3D8N", 1, hexahedra_0, p_elem_prop); + Element::Pointer p_elem_1 = this_model_part.CreateNewElement("Element3D8N", 2, hexahedra_1, p_elem_prop); + + // Set DISTANCE + for (std::size_t i_node = 0; i_node < this_model_part.Nodes().size(); ++i_node) { + auto it_node = this_model_part.Nodes().begin() + i_node; + it_node->FastGetSolutionStepValue(DISTANCE) = (it_node->X() == 1.0) ? 0.0 : 1.0; + it_node->SetValue(NODAL_AREA, 0.0); + } + + // Compute gradient + typedef ComputeNodalGradientProcess GradientType; + GradientType process = GradientType(this_model_part, DISTANCE, DISTANCE_GRADIENT); + process.Execute(); + +// // DEBUG +// GiDIODebugGradient(this_model_part); + const double tolerance = 1.0e-8; KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_1->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); KRATOS_CHECK_LESS_EQUAL(std::abs(p_node_2->FastGetSolutionStepValue(DISTANCE_GRADIENT_X)) - 1.0, tolerance); From 8c74b175228d56953784bb530c9e731b9a25cf37 Mon Sep 17 00:00:00 2001 From: Philipp Bucher Date: Wed, 19 Dec 2018 23:49:55 +0100 Subject: [PATCH 20/31] Missing const Co-Authored-By: loumalouomega --- .../custom_processes/metrics_hessian_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index 7dd36f1c7339..43b883695232 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -67,7 +67,7 @@ void ComputeHessianSolMetricProcess::Execute() } else { VariableUtils().CheckVariableExists(mrOriginVariableComponentsList[0], nodes_array); } - for (auto& i_node : nodes_array) + for (const auto& i_node : nodes_array) KRATOS_ERROR_IF_NOT(i_node.Has(NODAL_H)) << "NODAL_H must be computed" << std::endl; const auto& it_element_begin = mThisModelPart.ElementsBegin(); From 32b2d3994d8af073ade835427b516de566902bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Fri, 21 Dec 2018 17:09:53 +0100 Subject: [PATCH 21/31] Suggestions by @philbucher --- .../metrics_hessian_process.cpp | 30 ++++++++++----- .../compute_nodal_gradient_process.cpp | 38 +++++++++++++------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index 43b883695232..f8898d618f9a 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -165,8 +165,6 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() // Geometry information const auto& r_first_element_geometry = it_element_begin->GetGeometry(); const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); - const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); - const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); // Declaring auxiliar vector const Vector aux_zero_hessian = ZeroVector(3 * (dimension - 1)); @@ -195,20 +193,32 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() gradient_process.Execute(); } - // The integration points - const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); - const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); - const std::size_t number_of_integration_points = integration_points.size(); - - Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); - Vector N = ZeroVector(number_of_nodes); - Matrix J0 = ZeroMatrix(dimension, local_space_dimension); + // Auxiliar containers + Matrix DN_DX, J0; + Vector N; #pragma omp parallel for firstprivate(DN_DX, N, J0) for(int i_elem = 0; i_elem < num_elements; ++i_elem) { auto it_elem = it_element_begin + i_elem; auto& r_geometry = it_elem->GetGeometry(); + // Current geometry information + const std::size_t local_space_dimension = r_geometry.LocalSpaceDimension(); + const std::size_t number_of_nodes = r_geometry.PointsNumber(); + + // Resize if needed + if (DN_DX.size1() != number_of_nodes || DN_DX.size2() != dimension) + DN_DX.resize(number_of_nodes, dimension); + if (N.size() != number_of_nodes) + N.resize(number_of_nodes); + if (J0.size1() != dimension || J0.size2() != local_space_dimension) + J0.resize(dimension, local_space_dimension); + + // The integration points + const auto& integration_method = r_geometry.GetDefaultIntegrationMethod(); + const auto& integration_points = r_geometry.IntegrationPoints(integration_method); + const std::size_t number_of_integration_points = integration_points.size(); + // The containers of the shape functions and the local gradients const auto& rNcontainer = r_geometry.ShapeFunctionsValues(integration_method); const auto& rDN_DeContainer = r_geometry.ShapeFunctionsLocalGradients(integration_method); diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 61c26108591e..2b74e64b1c76 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -31,26 +31,40 @@ void ComputeNodalGradientProcess::Execute() // Set to zero ClearGradient(); - const auto& it_element_begin = mrModelPart.ElementsBegin(); - const auto& r_first_element_geometry = it_element_begin->GetGeometry(); - const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); - const std::size_t local_space_dimension = r_first_element_geometry.LocalSpaceDimension(); - const std::size_t number_of_nodes = r_first_element_geometry.PointsNumber(); + // Auxiliar containers + Matrix DN_DX, J0; + Vector N; - // The integration points - const auto& integration_method = r_first_element_geometry.GetDefaultIntegrationMethod(); - const auto& integration_points = r_first_element_geometry.IntegrationPoints(integration_method); - const std::size_t number_of_integration_points = integration_points.size(); + // First element iterator + const auto it_element_begin = mrModelPart.ElementsBegin(); - Matrix DN_DX = ZeroMatrix(number_of_nodes, dimension); - Vector N = ZeroVector(number_of_nodes); - Matrix J0 = ZeroMatrix(dimension, local_space_dimension); + // Geometry information + const auto& r_first_element_geometry = it_element_begin->GetGeometry(); + const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + // Iterate over the elements #pragma omp parallel for firstprivate(DN_DX, N, J0) for(int i_elem=0; i_elem(mrModelPart.Elements().size()); ++i_elem) { auto it_elem = it_element_begin + i_elem; auto& r_geometry = it_elem->GetGeometry(); + // Current geometry information + const std::size_t local_space_dimension = r_geometry.LocalSpaceDimension(); + const std::size_t number_of_nodes = r_geometry.PointsNumber(); + + // Resize if needed + if (DN_DX.size1() != number_of_nodes || DN_DX.size2() != dimension) + DN_DX.resize(number_of_nodes, dimension); + if (N.size() != number_of_nodes) + N.resize(number_of_nodes); + if (J0.size1() != dimension || J0.size2() != local_space_dimension) + J0.resize(dimension, local_space_dimension); + + // The integration points + const auto& integration_method = r_geometry.GetDefaultIntegrationMethod(); + const auto& integration_points = r_geometry.IntegrationPoints(integration_method); + const std::size_t number_of_integration_points = integration_points.size(); + Vector values(number_of_nodes); if (mrOriginVariableDoubleList.size() > 0) { for(std::size_t i_node=0; i_node Date: Sat, 22 Dec 2018 13:28:54 +0100 Subject: [PATCH 22/31] Corrections --- .../metrics_hessian_process.cpp | 41 ++++-- .../metrics_hessian_process.h | 6 +- .../python_scripts/mmg_process.py | 11 +- .../beam2D_line_load_test_result.sol | 52 +++---- .../beam2D_test_result.sol | 138 +++++++++--------- 5 files changed, 133 insertions(+), 115 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index f8898d618f9a..33cf87a76b59 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -27,7 +27,7 @@ ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( ):mThisModelPart(rThisModelPart) { // We push the list of double variables - mrOriginVariableDoubleList.push_back(rVariable); + mrOriginVariableDoubleList.push_back(&rVariable); // We check the parameters Parameters default_parameters = GetDefaultParameters(); @@ -45,7 +45,7 @@ ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( ):mThisModelPart(rThisModelPart) { // We push the components list - mrOriginVariableComponentsList.push_back(rVariable); + mrOriginVariableComponentsList.push_back(&rVariable); // We check the parameters Parameters default_parameters = GetDefaultParameters(); @@ -63,9 +63,9 @@ void ComputeHessianSolMetricProcess::Execute() // Some checks NodesArrayType& nodes_array = mThisModelPart.Nodes(); if (mrOriginVariableDoubleList.size() > 0) { - VariableUtils().CheckVariableExists(mrOriginVariableDoubleList[0], nodes_array); + VariableUtils().CheckVariableExists(*mrOriginVariableDoubleList[0], nodes_array); } else { - VariableUtils().CheckVariableExists(mrOriginVariableComponentsList[0], nodes_array); + VariableUtils().CheckVariableExists(*mrOriginVariableComponentsList[0], nodes_array); } for (const auto& i_node : nodes_array) KRATOS_ERROR_IF_NOT(i_node.Has(NODAL_H)) << "NODAL_H must be computed" << std::endl; @@ -89,7 +89,7 @@ array_1d ComputeHessianSolMetricProcess::ComputeHessianM const Vector& rHessian, const double AnisotropicRatio, const double ElementMinSize, // This way we can impose as minimum as the previous size if we desire - const double ElementMaxSize // This way we can impose as maximum as the previous size if we desire + const double ElementMaxSize // This way we can impose as maximum as the previous size if we desire ) { /// The type of array considered for the tensor @@ -103,8 +103,10 @@ array_1d ComputeHessianSolMetricProcess::ComputeHessianM // Calculating Metric parameters double interpolation_error = mInterpError; - if (mEstimateInterpError) - interpolation_error = 2.0/9.0 * MathUtils::Max(ElementMaxSize, ElementMaxSize * norm_frobenius(hessian_matrix)); + if (mEstimateInterpError) { + const double mesh_constant = TDim == 3 ? 9.0/32.0 : 2.0/9.0; + interpolation_error = mesh_constant * MathUtils::Max(ElementMaxSize, ElementMaxSize * norm_frobenius(hessian_matrix)); + } KRATOS_ERROR_IF(interpolation_error < std::numeric_limits::epsilon()) << "ERROR: YOUR INTERPOLATION ERROR IS NEAR ZERO: " << interpolation_error << std::endl; const double c_epslilon = mMeshConstant/interpolation_error; @@ -186,10 +188,10 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() // Compute auxiliar gradient if (mrOriginVariableDoubleList.size() > 0) { - auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mrOriginVariableDoubleList[0], AUXILIAR_GRADIENT, NODAL_AREA); + auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, *mrOriginVariableDoubleList[0], AUXILIAR_GRADIENT, NODAL_AREA); gradient_process.Execute(); } else { - auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, mrOriginVariableComponentsList[0], AUXILIAR_GRADIENT, NODAL_AREA); + auto gradient_process = ComputeNodalGradientProcess(mThisModelPart, *mrOriginVariableComponentsList[0], AUXILIAR_GRADIENT, NODAL_AREA); gradient_process.Execute(); } @@ -353,14 +355,11 @@ void ComputeHessianSolMetricProcess::CalculateMetric() const Variable& tensor_variable = KratosComponents>::Get("METRIC_TENSOR_"+std::to_string(TDim)+"D"); // Setting metric in case not defined - if (!nodes_array.begin()->Has(tensor_variable)) { + const auto it_node_begin = nodes_array.begin(); + if (!it_node_begin->Has(tensor_variable)) { // Declaring auxiliar vector const TensorArrayType aux_zero_vector = ZeroVector(3 * (TDim - 1)); - #pragma omp parallel for - for(int i = 0; i < num_nodes; ++i) { - auto it_node = nodes_array.begin() + i; - it_node->SetValue(tensor_variable, aux_zero_vector); - } + VariableUtils().SetNonHistoricalVariable(tensor_variable, aux_zero_vector, nodes_array); } // Ratio reference variable @@ -369,7 +368,7 @@ void ComputeHessianSolMetricProcess::CalculateMetric() #pragma omp parallel for for(int i = 0; i < num_nodes; ++i) { - auto it_node = nodes_array.begin() + i; + auto it_node = it_node_begin + i; const Vector& hessian = it_node->GetValue(AUXILIAR_HESSIAN); @@ -433,6 +432,16 @@ Parameters ComputeHessianSolMetricProcess::GetDefaultParameters() "interpolation" : "Linear" } })" ); + + // Identify the dimension first + const SizeType dimension = mThisModelPart.GetProcessInfo()[DOMAIN_SIZE]; + + // The mesh dependent constant depends on dimension + if (dimension == 2) { + default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(2.0/9.0); + } else { + default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(9.0/32.0); + } return default_parameters; } diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h index 7e43c8d5d8d0..2ce6861a0a7f 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h @@ -212,9 +212,9 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess ///@name Private member Variables ///@{ - ModelPart& mThisModelPart; /// The model part to compute - std::vector> mrOriginVariableDoubleList; /// The scalar variable list to compute - std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) + ModelPart& mThisModelPart; /// The model part to compute + std::vector*> mrOriginVariableDoubleList; /// The scalar variable list to compute + std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) // TODO: Replace for Parameters std::string mRatioReferenceVariable = "DISTANCE"; /// Variable used to compute the anisotropic ratio diff --git a/applications/MeshingApplication/python_scripts/mmg_process.py b/applications/MeshingApplication/python_scripts/mmg_process.py index 5b6ad2b34a8f..ac358f965def 100644 --- a/applications/MeshingApplication/python_scripts/mmg_process.py +++ b/applications/MeshingApplication/python_scripts/mmg_process.py @@ -123,12 +123,21 @@ def __init__(self, Model, settings ): } """) + # Identify the dimension first + if not settings.Has("model_part_name"): + settings.AddValue("model_part_name", default_parameters["model_part_name"]) + self.dim = Model[settings["model_part_name"].GetString()].ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + # The mesh dependent constant depends on dimension + if self.dim == 2: + default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(2.0/9.0) + else: + default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(9.0/32.0) + # Overwrite the default settings with user-provided parameters self.settings = settings self.settings.RecursivelyValidateAndAssignDefaults(default_parameters) self.model_part= Model[self.settings["model_part_name"].GetString()] - self.dim = self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] self.enforce_current = self.settings["enforce_current"].GetBool() diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol index 2f3b6542c614..11bede126df0 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_line_load_test_result.sol @@ -21,38 +21,38 @@ SolAtVertices 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 2203.81475518259 0 2203.81475518259 + 1741.2857324904 0 1741.2857324904 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 1596.1682065273 0 1596.1682065273 - 1937.36282929371 0 1937.36282929371 - 2390.02732073372 0 2390.02732073372 - 1694.57412015215 0 1694.57412015215 1596.1682065273 0 1596.1682065273 - 3211.5413239035 0 3211.5413239035 - 2544.19608405931 0 2544.19608405931 - 2832.82832148862 0 2832.82832148862 - 3497.44690606323 0 3497.44690606323 - 1987.67504725415 0 1987.67504725415 - 4176.49189592067 0 4176.49189592067 - 3522.07756928224 0 3522.07756928224 - 2941.860926844 0 2941.860926844 - 4052.02609761579 0 4052.02609761579 - 4430.41381078589 0 4430.41381078589 - 5180.34409800205 0 5180.34409800205 - 4016.81056973862 0 4016.81056973862 - 4840.25254877213 0 4840.25254877213 - 5345.96584549973 0 5345.96584549973 - 6017.97906558297 0 6017.97906558297 - 6384.67282610918 0 6384.67282610918 - 5260.70110314265 0 5260.70110314265 - 6289.51969324357 0 6289.51969324357 - 6384.67282610918 0 6384.67282610918 - 6384.67282610918 0 6384.67282610918 - 6384.67282610918 0 6384.67282610918 - 6384.67282610918 0 6384.67282610918 + 1888.41664848122 0 1888.41664848122 + 1596.1682065273 0 1596.1682065273 + 1596.1682065273 0 1596.1682065273 + 2537.51413246724 0 2537.51413246724 + 2010.22900468851 0 2010.22900468851 + 2238.28410586729 0 2238.28410586729 + 2763.41483935871 0 2763.41483935871 + 1596.1682065273 0 1596.1682065273 + 3299.94421406067 0 3299.94421406067 + 2782.8761041239 0 2782.8761041239 + 2324.43332491443 0 2324.43332491443 + 3201.60086725174 0 3201.60086725174 + 3500.57387518879 0 3500.57387518879 + 4093.11138607511 0 4093.11138607511 + 3173.77625263271 0 3173.77625263271 + 3824.39707557243 0 3824.39707557243 + 4223.97301372814 0 4223.97301372814 + 4754.94642218925 0 4754.94642218925 + 5513.76587138039 0 5513.76587138039 + 4156.60334075396 0 4156.60334075396 + 4969.4970415752 0 4969.4970415752 + 5325.65916538894 0 5325.65916538894 + 5933.73545574369 0 5933.73545574369 + 5372.02361021606 0 5372.02361021606 6384.67282610918 0 6384.67282610918 + 6205.42714745037 0 6205.42714745037 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 6384.67282610918 0 6384.67282610918 diff --git a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol index ace1ea16c17c..e6e4dc52bc20 100644 --- a/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol +++ b/applications/MeshingApplication/tests/mmg_lagrangian_test/beam2D_test_result.sol @@ -7,77 +7,77 @@ Dimension SolAtVertices 205 1 3 - 35.9143759191543 0 35.9143759191543 - 37.4400098128027 0 37.4400098128027 - 26.2586649981814 0 26.2586649981814 - 33.413444384322 0 33.413444384322 + 28.3767908497022 0 28.3767908497022 + 29.5822299755478 0 29.5822299755478 + 20.7475871590569 0 20.7475871590569 + 26.400746180205 0 26.400746180205 30.2668616137121 0 30.2668616137121 - 39.5038146087083 0 39.5038146087083 - 21.7522982463049 0 21.7522982463049 + 31.2128905550287 0 31.2128905550287 + 19.4301897481549 0 19.4301897481549 30.2668616137121 0 30.2668616137121 - 34.7912241547683 0 34.7912241547683 - 37.2336442240363 0 37.2336442240363 - 36.031221403295 0 36.031221403295 - 25.0190046788027 0 25.0190046788027 - 33.2502322505889 0 33.2502322505889 - 32.7387665731833 0 32.7387665731833 - 32.3642617399157 0 32.3642617399157 - 34.6441261821053 0 34.6441261821053 - 30.4527623066976 0 30.4527623066976 - 35.7721819262914 0 35.7721819262914 - 34.5191770987428 0 34.5191770987428 - 38.5824193988693 0 38.5824193988693 - 31.8200258225015 0 31.8200258225015 - 28.8344978294523 0 28.8344978294523 - 32.831409905737 0 32.831409905737 - 35.2775147501514 0 35.2775147501514 - 27.5595729207846 0 27.5595729207846 - 31.371208273239 0 31.371208273239 - 29.7161133275109 0 29.7161133275109 - 27.2124194366223 0 27.2124194366223 - 32.3131692241774 0 32.3131692241774 - 27.0396775965852 0 27.0396775965852 - 28.3085946349283 0 28.3085946349283 - 27.8824779541497 0 27.8824779541497 - 29.6289246620822 0 29.6289246620822 - 26.3351778770106 0 26.3351778770106 - 25.0894963199882 0 25.0894963199882 - 27.7206677923888 0 27.7206677923888 - 25.995321563843 0 25.995321563843 - 25.5276047877789 0 25.5276047877789 - 24.354462501175 0 24.354462501175 - 23.5124637362395 0 23.5124637362395 - 25.4954183637171 0 25.4954183637171 - 24.6380724373713 0 24.6380724373713 - 24.2551913147001 0 24.2551913147001 - 23.2552504847589 0 23.2552504847589 - 23.9446765343999 0 23.9446765343999 - 22.7005417609784 0 22.7005417609784 - 22.8711404352926 0 22.8711404352926 - 22.4440885928833 0 22.4440885928833 - 21.8179849340975 0 21.8179849340975 - 22.2653333934246 0 22.2653333934246 - 21.3909586451322 0 21.3909586451322 - 21.3290644564547 0 21.3290644564547 - 20.6985501936326 0 20.6985501936326 - 19.9871802434071 0 19.9871802434071 - 20.6942778113269 0 20.6942778113269 - 20.1128494721444 0 20.1128494721444 - 19.3939342093955 0 19.3939342093955 - 19.3516002844571 0 19.3516002844571 - 19.1092008484915 0 19.1092008484915 - 19.294741544997 0 19.294741544997 - 18.7630484521628 0 18.7630484521628 - 19.4354254403624 0 19.4354254403624 - 17.8635483593958 0 17.8635483593958 - 17.9169890265432 0 17.9169890265432 - 17.9633064984183 0 17.9633064984183 - 17.4103345211041 0 17.4103345211041 - 17.8054353019448 0 17.8054353019448 - 16.6544544211057 0 16.6544544211057 - 16.6806735919392 0 16.6806735919392 - 16.9075081806209 0 16.9075081806209 - 16.5472820847962 0 16.5472820847962 + 27.4893622951255 0 27.4893622951255 + 29.4191756831891 0 29.4191756831891 + 28.4691132075417 0 28.4691132075417 + 19.7681024622638 0 19.7681024622638 + 26.2717884449097 0 26.2717884449097 + 25.8676674158485 0 25.8676674158485 + 25.5717623624025 0 25.5717623624025 + 27.3731367364782 0 27.3731367364782 + 24.0614418225759 0 24.0614418225759 + 28.2644400405265 0 28.2644400405265 + 27.2744115348091 0 27.2744115348091 + 30.4848745867609 0 30.4848745867609 + 25.1417487980258 0 25.1417487980258 + 22.7828130998142 0 22.7828130998142 + 25.9408670860144 0 25.9408670860144 + 27.8735919013541 0 27.8735919013541 + 21.7754650238298 0 21.7754650238298 + 24.7871275245345 0 24.7871275245345 + 23.4793981846999 0 23.4793981846999 + 21.5011709128867 0 21.5011709128867 + 25.5313929672512 0 25.5313929672512 + 21.3646835331044 0 21.3646835331044 + 22.3672846498199 0 22.3672846498199 + 22.0305998650072 0 22.0305998650072 + 23.4105083749785 0 23.4105083749785 + 20.8080417793664 0 20.8080417793664 + 19.8237995614721 0 19.8237995614721 + 21.9027498606528 0 21.9027498606528 + 20.5395133343945 0 20.5395133343945 + 20.169959338492 0 20.169959338492 + 19.2430320996938 0 19.2430320996938 + 18.5777491249299 0 18.5777491249299 + 20.1445280898505 0 20.1445280898505 + 19.4671189628613 0 19.4671189628613 + 19.1645956066766 0 19.1645956066766 + 18.3745189015379 0 18.3745189015379 + 18.9192505950814 0 18.9192505950814 + 17.9362305271928 0 17.9362305271928 + 18.0710245414658 0 18.0710245414658 + 17.7336008635128 0 17.7336008635128 + 17.238901676324 0 17.238901676324 + 17.5923621873972 0 17.5923621873972 + 16.9014981887464 0 16.9014981887464 + 16.8525941384334 0 16.8525941384334 + 16.3544100295369 0 16.3544100295369 + 16.2448121764785 0 16.2448121764785 + 16.3510343200608 0 16.3510343200608 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 + 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 16.2448121764785 0 16.2448121764785 From 31d471bd77ae8332761903ed64842dcf026d777f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 23 Dec 2018 13:38:06 +0100 Subject: [PATCH 23/31] Last correction --- .../metrics_hessian_process.cpp | 18 +++++++++++++----- .../custom_processes/metrics_hessian_process.h | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index 33cf87a76b59..dd870cd9bf47 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -89,7 +89,8 @@ array_1d ComputeHessianSolMetricProcess::ComputeHessianM const Vector& rHessian, const double AnisotropicRatio, const double ElementMinSize, // This way we can impose as minimum as the previous size if we desire - const double ElementMaxSize // This way we can impose as maximum as the previous size if we desire + const double ElementMaxSize, // This way we can impose as maximum as the previous size if we desire + const double NodalH ) { /// The type of array considered for the tensor @@ -102,13 +103,20 @@ array_1d ComputeHessianSolMetricProcess::ComputeHessianM const MatrixType hessian_matrix = MathUtils::VectorToSymmetricTensor(rHessian); // Calculating Metric parameters + const double mesh_constant = TDim == 3 ? 9.0/32.0 : 2.0/9.0; double interpolation_error = mInterpError; if (mEstimateInterpError) { - const double mesh_constant = TDim == 3 ? 9.0/32.0 : 2.0/9.0; interpolation_error = mesh_constant * MathUtils::Max(ElementMaxSize, ElementMaxSize * norm_frobenius(hessian_matrix)); } - KRATOS_ERROR_IF(interpolation_error < std::numeric_limits::epsilon()) << "ERROR: YOUR INTERPOLATION ERROR IS NEAR ZERO: " << interpolation_error << std::endl; + // We check is the interpolation error is near zero. If it is we will correct it + if (interpolation_error < std::numeric_limits::epsilon()) { + KRATOS_WARNING("ComputeHessianSolMetricProcess") << "WARNING: Your interpolation error is near zero: " << interpolation_error << ". Computing a local L(inf) upper bound of the interpolation error"<< std::endl; + const double l_square = std::pow(NodalH, 2); + for (IndexType i = 0; i < 3 * (TDim - 1); ++i) { + interpolation_error = mesh_constant * MathUtils::Max(interpolation_error, l_square * std::abs(rHessian[i])); + } + } const double c_epslilon = mMeshConstant/interpolation_error; const double min_ratio = 1.0/(ElementMinSize * ElementMinSize); const double max_ratio = 1.0/(ElementMaxSize * ElementMaxSize); @@ -397,11 +405,11 @@ void ComputeHessianSolMetricProcess::CalculateMetric() const double norm_metric = norm_2(metric); if (norm_metric > 0.0) {// NOTE: This means we combine differents metrics, at the same time means that the metric should be reseted each time const TensorArrayType& old_metric = it_node->GetValue(tensor_variable); - const TensorArrayType& new_metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); + const TensorArrayType& new_metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size, nodal_h); metric = MetricsMathUtils::IntersectMetrics(old_metric, new_metric); } else { - metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size); + metric = ComputeHessianMetricTensor(hessian, ratio, element_min_size, element_max_size, nodal_h); } } } diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h index 2ce6861a0a7f..8b3a46aac8a0 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h @@ -243,13 +243,15 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess * @param AnisotropicRatio The anisotropic ratio * @param ElementMinSize The min size of element * @param ElementMaxSize The maximal size of the elements + * @param NodalH The size of the local node */ template array_1d ComputeHessianMetricTensor( const Vector& rHessian, const double AnisotropicRatio, const double ElementMinSize, // This way we can impose as minimum as the previous size if we desire - const double ElementMaxSize // This way we can impose as maximum as the previous size if we desire + const double ElementMaxSize, // This way we can impose as maximum as the previous size if we desire + const double NodalH ); /** From 3cb7d6eedb314dd6102888358631635a92f65ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 25 Dec 2018 20:17:54 +0100 Subject: [PATCH 24/31] Domain size --- kratos/processes/compute_nodal_gradient_process.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 2b74e64b1c76..46a444731770 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -38,9 +38,8 @@ void ComputeNodalGradientProcess::Execute() // First element iterator const auto it_element_begin = mrModelPart.ElementsBegin(); - // Geometry information - const auto& r_first_element_geometry = it_element_begin->GetGeometry(); - const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + // Current domain size + const std::size_t dimension = mrModelPart.GetProcessInfo()[DOMAIN_SIZE]; // Iterate over the elements #pragma omp parallel for firstprivate(DN_DX, N, J0) From ad25195b5e7a6bedaed8e9bc76cb3be4f0214fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 25 Dec 2018 20:20:54 +0100 Subject: [PATCH 25/31] DOMAIN_SIZE --- .../custom_processes/metrics_hessian_process.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index dd870cd9bf47..a0dfe0f35276 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -173,8 +173,7 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() const auto& it_element_begin = elements_array.begin(); // Geometry information - const auto& r_first_element_geometry = it_element_begin->GetGeometry(); - const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + const std::size_t dimension = mThisModelPart.GetProcessInfo()[DOMAIN_SIZE]; // Declaring auxiliar vector const Vector aux_zero_hessian = ZeroVector(3 * (dimension - 1)); From 07bf4488177fc0b4437a08c45ea07480ace41346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 25 Dec 2018 23:38:44 +0100 Subject: [PATCH 26/31] Trailing whitespace --- applications/MeshingApplication/python_scripts/mmg_process.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/MeshingApplication/python_scripts/mmg_process.py b/applications/MeshingApplication/python_scripts/mmg_process.py index ac358f965def..3b938d33d270 100644 --- a/applications/MeshingApplication/python_scripts/mmg_process.py +++ b/applications/MeshingApplication/python_scripts/mmg_process.py @@ -132,7 +132,7 @@ def __init__(self, Model, settings ): default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(2.0/9.0) else: default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(9.0/32.0) - + # Overwrite the default settings with user-provided parameters self.settings = settings self.settings.RecursivelyValidateAndAssignDefaults(default_parameters) From aafd81ebf14a1a69e318463e2747cb6d672b8ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Tue, 25 Dec 2018 23:40:57 +0100 Subject: [PATCH 27/31] Setting DOMAIN_SIZE on tests --- .../tests/cpp_tests/test_metric_process.cpp | 30 +++++++++++-------- .../test_compute_nodal_gradient_process.cpp | 20 ++++++++----- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp index fd42acf729b9..ad813121427f 100644 --- a/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp +++ b/applications/MeshingApplication/tests/cpp_tests/test_metric_process.cpp @@ -244,8 +244,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 2); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); Create2DGeometry(this_model_part, "Element2D3N"); @@ -294,8 +295,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 3); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); Create3DGeometry(this_model_part, "Element3D4N"); @@ -349,8 +351,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 2); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); Create2DGeometry(this_model_part, "Element2D3N"); @@ -394,8 +397,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISTANCE_GRADIENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 3); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); Create3DGeometry(this_model_part, "Element3D4N"); @@ -442,8 +446,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISPLACEMENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 2); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // In case the StructuralMechanicsApplciation is not compiled we skip the test Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); @@ -506,8 +511,9 @@ namespace Kratos this_model_part.AddNodalSolutionStepVariable(DISPLACEMENT); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 3); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // In case the StructuralMechanicsApplciation is not compiled we skip the test Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); diff --git a/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp index 37606adba997..a49d3cbe7d90 100644 --- a/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp +++ b/kratos/tests/cpp_tests/processes/test_compute_nodal_gradient_process.cpp @@ -65,8 +65,9 @@ namespace Kratos Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 2); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); @@ -149,8 +150,9 @@ namespace Kratos Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 3); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); @@ -312,8 +314,9 @@ namespace Kratos Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 2); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1, 0.0 , 0.0 , 0.0); @@ -383,8 +386,9 @@ namespace Kratos Properties::Pointer p_elem_prop = this_model_part.pGetProperties(0); auto& process_info = this_model_part.GetProcessInfo(); - process_info[STEP] = 1; - process_info[NL_ITERATION_NUMBER] = 1; + process_info.SetValue(DOMAIN_SIZE, 3); + process_info.SetValue(STEP, 1); + process_info.SetValue(NL_ITERATION_NUMBER, 1); // First we create the nodes NodeType::Pointer p_node_1 = this_model_part.CreateNewNode(1 , 0.0 , 1.0 , 1.0); From bfb4b2556398e73bc95a81ee7708e781cbcfd207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Wed, 26 Dec 2018 11:43:47 +0100 Subject: [PATCH 28/31] Some suggestions --- .../compute_nodal_gradient_process.cpp | 123 +++++++++--------- .../compute_nodal_gradient_process.h | 40 +++--- 2 files changed, 80 insertions(+), 83 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index 46a444731770..f29ff045432f 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -7,7 +7,7 @@ // License: BSD License // Kratos default license: kratos/license.txt // -// Main authors: Riccardo Rossi +// Main authors: Riccardo Rossi // Vicente Mataix Ferrandiz // // @@ -23,34 +23,34 @@ namespace Kratos { -template +template void ComputeNodalGradientProcess::Execute() { KRATOS_TRY; - + // Set to zero ClearGradient(); - + // Auxiliar containers Matrix DN_DX, J0; Vector N; - + // First element iterator const auto it_element_begin = mrModelPart.ElementsBegin(); - + // Current domain size const std::size_t dimension = mrModelPart.GetProcessInfo()[DOMAIN_SIZE]; - + // Iterate over the elements #pragma omp parallel for firstprivate(DN_DX, N, J0) for(int i_elem=0; i_elem(mrModelPart.Elements().size()); ++i_elem) { auto it_elem = it_element_begin + i_elem; auto& r_geometry = it_elem->GetGeometry(); - + // Current geometry information const std::size_t local_space_dimension = r_geometry.LocalSpaceDimension(); const std::size_t number_of_nodes = r_geometry.PointsNumber(); - + // Resize if needed if (DN_DX.size1() != number_of_nodes || DN_DX.size2() != dimension) DN_DX.resize(number_of_nodes, dimension); @@ -58,29 +58,29 @@ void ComputeNodalGradientProcess::Execute() N.resize(number_of_nodes); if (J0.size1() != dimension || J0.size2() != local_space_dimension) J0.resize(dimension, local_space_dimension); - + // The integration points const auto& integration_method = r_geometry.GetDefaultIntegrationMethod(); const auto& integration_points = r_geometry.IntegrationPoints(integration_method); const std::size_t number_of_integration_points = integration_points.size(); - + Vector values(number_of_nodes); if (mrOriginVariableDoubleList.size() > 0) { for(std::size_t i_node=0; i_node::Execute() MathUtils::InvertMatrix(J0, InvJ0, detJ0); const Matrix& rDN_De = rDN_DeContainer[point_number]; GeometryUtils::ShapeFunctionsGradients(rDN_De, InvJ0, DN_DX); - + const Vector grad = prod(trans(DN_DX), values); const double gauss_point_volume = integration_points[point_number].Weight() * detJ0; - + for(std::size_t i_node=0; i_node& r_gradient = GetGradient(r_geometry, i_node); for(std::size_t k=0; k ComputeNodalGradientProcess::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, + ModelPart& rModelPart, + Variable& rOriginVariable, + Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - + // We push the list of double variables - mrOriginVariableDoubleList.push_back(rOriginVariable); - + mrOriginVariableDoubleList.push_back(&rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); // In case the area or gradient variable is not initialized we initialize it @@ -136,7 +137,7 @@ ComputeNodalGradientProcessHas( rAreaVariable )) { VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); } - + KRATOS_CATCH("") } @@ -145,17 +146,17 @@ ComputeNodalGradientProcess ComputeNodalGradientProcess::ComputeNodalGradientProcess( - ModelPart& rModelPart, - Variable& rOriginVariable, - Variable >& rGradientVariable, + ModelPart& rModelPart, + Variable& rOriginVariable, + Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - + // We push the list of double variables - mrOriginVariableDoubleList.push_back(rOriginVariable); - + mrOriginVariableDoubleList.push_back(&rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); // In case the area or gradient variable is not initialized we initialize it auto& r_nodes = rModelPart.Nodes(); @@ -166,7 +167,7 @@ ComputeNodalGradientProcessHas( rAreaVariable )) { VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); } - + KRATOS_CATCH("") } @@ -175,17 +176,17 @@ ComputeNodalGradientProcess ComputeNodalGradientProcess::ComputeNodalGradientProcess( - ModelPart& rModelPart, + ModelPart& rModelPart, ComponentType& rOriginVariable, - Variable >& rGradientVariable, + Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - + // We push the components list - mrOriginVariableComponentsList.push_back(rOriginVariable); - + mrOriginVariableComponentsList.push_back(&rOriginVariable); + VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); VariableUtils().CheckVariableExists(rGradientVariable, mrModelPart.Nodes()); // In case the area or gradient variable is not initialized we initialize it @@ -193,7 +194,7 @@ ComputeNodalGradientProcessHas( rAreaVariable )) { VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); } - + KRATOS_CATCH("") } @@ -202,16 +203,16 @@ ComputeNodalGradientProcess ComputeNodalGradientProcess::ComputeNodalGradientProcess( - ModelPart& rModelPart, + ModelPart& rModelPart, ComponentType& rOriginVariable, - Variable >& rGradientVariable, + Variable >& rGradientVariable, Variable& rAreaVariable) :mrModelPart(rModelPart), mrGradientVariable(rGradientVariable), mrAreaVariable(rAreaVariable) { KRATOS_TRY - + // We push the components list - mrOriginVariableComponentsList.push_back(rOriginVariable); + mrOriginVariableComponentsList.push_back(&rOriginVariable); VariableUtils().CheckVariableExists(rOriginVariable, mrModelPart.Nodes()); // In case the area or gradient variable is not initialized we initialize it @@ -223,7 +224,7 @@ ComputeNodalGradientProcessHas( rAreaVariable )) { VariableUtils().SetNonHistoricalVariable(rAreaVariable, 0.0, r_nodes); } - + KRATOS_CATCH("") } @@ -248,7 +249,7 @@ template <> void ComputeNodalGradientProcess::ClearGradient() { const array_1d aux_zero_vector = ZeroVector(3); - + #pragma omp parallel for for(int i = 0; i < static_cast(mrModelPart.Nodes().size()); ++i) { auto it_node=mrModelPart.NodesBegin()+i; @@ -261,14 +262,13 @@ void ComputeNodalGradientProcess -double& ComputeNodalGradientProcess::GetGradient( +array_1d& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k + unsigned int i ) { - double& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable)[k]; - + array_1d& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable); + return val; } @@ -276,14 +276,13 @@ double& ComputeNodalGradientProcess -double& ComputeNodalGradientProcess::GetGradient( +array_1d& ComputeNodalGradientProcess::GetGradient( Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k + unsigned int i ) { - double& val = rThisGeometry[i].GetValue(mrGradientVariable)[k]; - + array_1d& val = rThisGeometry[i].GetValue(mrGradientVariable); + return val; } diff --git a/kratos/processes/compute_nodal_gradient_process.h b/kratos/processes/compute_nodal_gradient_process.h index 7acd8889cbff..70b621f1045a 100644 --- a/kratos/processes/compute_nodal_gradient_process.h +++ b/kratos/processes/compute_nodal_gradient_process.h @@ -38,7 +38,7 @@ namespace Kratos ///@} ///@name Enum's ///@{ - + ///@} ///@name Functions ///@{ @@ -56,7 +56,7 @@ struct ComputeNodalGradientProcessSettings constexpr static bool SaveAsHistoricalVariable = true; constexpr static bool SaveAsNonHistoricalVariable = false; }; - + /** * @class ComputeNodalGradientProcess * @ingroup KratosCore @@ -66,14 +66,14 @@ struct ComputeNodalGradientProcessSettings * @author Vicente Mataix Ferrandiz * @tparam THistorical If the variable is historical or not */ -template +template class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess : public Process { public: ///@name Type Definitions ///@{ - + /// Pointer definition of ComputeNodalGradientProcess KRATOS_CLASS_POINTER_DEFINITION(ComputeNodalGradientProcess); @@ -88,7 +88,7 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess Variable >& rGradientVariable, Variable& rAreaVariable = NODAL_AREA ); - + /// Default constructor. (component) ComputeNodalGradientProcess( ModelPart& rModelPart, @@ -208,12 +208,12 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ///@} ///@name Member Variables ///@{ - - ModelPart& mrModelPart; /// The main model part - std::vector> mrOriginVariableDoubleList; /// The scalar variable list to compute - std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) - Variable >& mrGradientVariable; /// The resultant gradient variable - Variable& mrAreaVariable; /// The auxiliar area variable + + ModelPart& mrModelPart; /// The main model part + std::vector*> mrOriginVariableDoubleList; /// The scalar variable list to compute + std::vector mrOriginVariableComponentsList; /// The scalar variable list to compute (components) + Variable >& mrGradientVariable; /// The resultant gradient variable + Variable& mrAreaVariable; /// The auxiliar area variable ///@} ///@name Private Operators @@ -224,7 +224,7 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess ///@{ // TODO: Try to use enable_if!!! - + /** * This clears the gradient */ @@ -234,14 +234,12 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess * This gets the gradient value * @param rThisGeometry The geometry of the element * @param i The node index - * @param k The component index */ - double& GetGradient( + array_1d& GetGradient( Element::GeometryType& rThisGeometry, - unsigned int i, - unsigned int k + unsigned int i ); - + /** * This divides the gradient value by the nodal area */ @@ -285,7 +283,7 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess /// input stream function // inline std::istream& operator >> (std::istream& rIStream, // ComputeNodalGradientProcess& rThis); -// +// // /// output stream function // inline std::ostream& operator << (std::ostream& rOStream, // const ComputeNodalGradientProcess& rThis) @@ -293,13 +291,13 @@ class KRATOS_API(KRATOS_CORE) ComputeNodalGradientProcess // rThis.PrintInfo(rOStream); // rOStream << std::endl; // rThis.PrintData(rOStream); -// +// // return rOStream; // } ///@} - + } // namespace Kratos. -#endif // KRATOS_COMPUTE_GRADIENT_PROCESS_INCLUDED defined +#endif // KRATOS_COMPUTE_GRADIENT_PROCESS_INCLUDED defined From 93a7a228fb9818d7efdd5642b7ff77f557aa0cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Wed, 26 Dec 2018 12:44:08 +0100 Subject: [PATCH 29/31] Removing commented line --- kratos/processes/compute_nodal_gradient_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index f29ff045432f..e8cdd714ccb4 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -95,7 +95,7 @@ void ComputeNodalGradientProcess::Execute() for(std::size_t i_node=0; i_node& r_gradient = GetGradient(r_geometry, i_node); for(std::size_t k=0; k Date: Wed, 26 Dec 2018 19:12:13 +0100 Subject: [PATCH 30/31] Clean up --- kratos/processes/compute_nodal_gradient_process.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kratos/processes/compute_nodal_gradient_process.cpp b/kratos/processes/compute_nodal_gradient_process.cpp index e8cdd714ccb4..f7f9cce07dbf 100644 --- a/kratos/processes/compute_nodal_gradient_process.cpp +++ b/kratos/processes/compute_nodal_gradient_process.cpp @@ -95,8 +95,6 @@ void ComputeNodalGradientProcess::Execute() for(std::size_t i_node=0; i_node& r_gradient = GetGradient(r_geometry, i_node); for(std::size_t k=0; k& ComputeNodalGradientProcess& val = rThisGeometry[i].FastGetSolutionStepValue(mrGradientVariable); - return val; } @@ -282,7 +279,6 @@ array_1d& ComputeNodalGradientProcess& val = rThisGeometry[i].GetValue(mrGradientVariable); - return val; } From e431150a0dbcfbddf6ed40f4025595ff96433c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Mataix=20Ferr=C3=A1ndiz?= Date: Sun, 30 Dec 2018 15:51:16 +0100 Subject: [PATCH 31/31] Suggestions by @philbucher --- .../metrics_hessian_process.cpp | 40 ++++++++++--------- .../metrics_hessian_process.h | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp index a0dfe0f35276..ba7d90ec3f08 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.cpp @@ -58,6 +58,7 @@ ComputeHessianSolMetricProcess::ComputeHessianSolMetricProcess( void ComputeHessianSolMetricProcess::Execute() { + // Computing auxiliar Hessian CalculateAuxiliarHessian(); // Some checks @@ -67,17 +68,21 @@ void ComputeHessianSolMetricProcess::Execute() } else { VariableUtils().CheckVariableExists(*mrOriginVariableComponentsList[0], nodes_array); } - for (const auto& i_node : nodes_array) + + // Checking NODAL_H + for (const auto& i_node : nodes_array) KRATOS_ERROR_IF_NOT(i_node.Has(NODAL_H)) << "NODAL_H must be computed" << std::endl; - const auto& it_element_begin = mThisModelPart.ElementsBegin(); - const auto& r_first_element_geometry = it_element_begin->GetGeometry(); - const std::size_t dimension = r_first_element_geometry.WorkingSpaceDimension(); + // Getting dimension + const std::size_t dimension = mThisModelPart.GetProcessInfo()[DOMAIN_SIZE]; - if (dimension == 2) { + // Computing metric + if (dimension == 2) { // 2D CalculateMetric<2>(); - } else { + } else if (dimension == 3) { // 3D CalculateMetric<3>(); + } else { + KRATOS_ERROR << "Dimension can be only 2D or 3D. Dimension: " << dimension << std::endl; } } @@ -251,8 +256,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() Matrix values(number_of_nodes, 2); for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { const array_1d& aux_grad = r_geometry[i_node].GetValue(AUXILIAR_GRADIENT); - values(i_node, 0) = aux_grad[0]; - values(i_node, 1) = aux_grad[1]; + for (IndexType i_dim = 0; i_dim < 2; ++i_dim) + values(i_node, i_dim) = aux_grad[i_dim]; } const BoundedMatrix& hessian = prod(trans(DN_DX), values); @@ -261,10 +266,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { auto& aux_hessian = r_geometry[i_node].GetValue(AUXILIAR_HESSIAN); for(IndexType k = 0; k < 3; ++k) { - double& val = aux_hessian[k]; - #pragma omp atomic - val += N[i_node] * gauss_point_volume * hessian_cond[k]; + aux_hessian[k] += N[i_node] * gauss_point_volume * hessian_cond[k]; } } } @@ -286,9 +289,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() Matrix values(number_of_nodes, 3); for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { const array_1d& aux_grad = r_geometry[i_node].GetValue(AUXILIAR_GRADIENT); - values(i_node, 0) = aux_grad[0]; - values(i_node, 1) = aux_grad[1]; - values(i_node, 2) = aux_grad[2]; + for (IndexType i_dim = 0; i_dim < 3; ++i_dim) + values(i_node, i_dim) = aux_grad[i_dim]; } const BoundedMatrix hessian = prod(trans(DN_DX), values); @@ -297,10 +299,8 @@ void ComputeHessianSolMetricProcess::CalculateAuxiliarHessian() for(IndexType i_node = 0; i_node < number_of_nodes; ++i_node) { auto& aux_hessian = r_geometry[i_node].GetValue(AUXILIAR_HESSIAN); for(IndexType k = 0; k < 6; ++k) { - double& val = aux_hessian[k]; - #pragma omp atomic - val += N[i_node] * gauss_point_volume * hessian_cond[k]; + aux_hessian[k] += N[i_node] * gauss_point_volume * hessian_cond[k]; } } } @@ -416,7 +416,7 @@ void ComputeHessianSolMetricProcess::CalculateMetric() /***********************************************************************************/ /***********************************************************************************/ -Parameters ComputeHessianSolMetricProcess::GetDefaultParameters() +Parameters ComputeHessianSolMetricProcess::GetDefaultParameters() const { Parameters default_parameters = Parameters(R"( { @@ -446,8 +446,10 @@ Parameters ComputeHessianSolMetricProcess::GetDefaultParameters() // The mesh dependent constant depends on dimension if (dimension == 2) { default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(2.0/9.0); - } else { + } else if (dimension == 3) { default_parameters["hessian_strategy_parameters"]["mesh_dependent_constant"].SetDouble(9.0/32.0); + } else { + KRATOS_ERROR << "Dimension can be only 2D or 3D. Dimension: " << dimension << std::endl; } return default_parameters; diff --git a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h index 8b3a46aac8a0..1eb908e20cb5 100755 --- a/applications/MeshingApplication/custom_processes/metrics_hessian_process.h +++ b/applications/MeshingApplication/custom_processes/metrics_hessian_process.h @@ -299,7 +299,7 @@ class KRATOS_API(MESHING_APPLICATION) ComputeHessianSolMetricProcess /** * @brief This method provides the defaults parameters to avoid conflicts between the different constructors */ - Parameters GetDefaultParameters(); + Parameters GetDefaultParameters() const; /** * @brief This method provides the defaults parameters to avoid conflicts between the different constructors