diff --git a/applications/MeshingApplication/CMakeLists.txt b/applications/MeshingApplication/CMakeLists.txt index 43ae2f76261b..05595a319e84 100644 --- a/applications/MeshingApplication/CMakeLists.txt +++ b/applications/MeshingApplication/CMakeLists.txt @@ -219,6 +219,7 @@ endif(CMAKE_UNITY_BUILD MATCHES ON) # Add to the KratosMultiphisics Python module kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/MeshingApplication.py KratosMultiphysics/MeshingApplication/__init__.py ) +kratos_python_install(${INSTALL_PYTHON_USING_LINKS} ${CMAKE_CURRENT_SOURCE_DIR}/python_registry_lists.py KratosMultiphysics/MeshingApplication/python_registry_lists.py ) # Install python files get_filename_component (CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) diff --git a/applications/MeshingApplication/MeshingApplication.py b/applications/MeshingApplication/MeshingApplication.py index 028fb7ded8d0..118c82701c0d 100644 --- a/applications/MeshingApplication/MeshingApplication.py +++ b/applications/MeshingApplication/MeshingApplication.py @@ -8,3 +8,7 @@ application_name = "KratosMeshingApplication" _ImportApplication(application, application_name) + +from KratosMultiphysics import python_registry_utilities +from . import python_registry_lists +python_registry_utilities.RegisterAll("KratosMultiphysics.MeshingApplication", python_registry_lists) \ No newline at end of file diff --git a/applications/MeshingApplication/custom_utilities/linear_to_quadratic_tetrahedra_mesh_converter_utility.cpp b/applications/MeshingApplication/custom_utilities/linear_to_quadratic_tetrahedra_mesh_converter_utility.cpp index 6bd5784d2469..f48f5c45b2f7 100644 --- a/applications/MeshingApplication/custom_utilities/linear_to_quadratic_tetrahedra_mesh_converter_utility.cpp +++ b/applications/MeshingApplication/custom_utilities/linear_to_quadratic_tetrahedra_mesh_converter_utility.cpp @@ -14,23 +14,28 @@ #include "custom_utilities/linear_to_quadratic_tetrahedra_mesh_converter_utility.h" namespace Kratos { - + void LinearToQuadraticTetrahedraMeshConverter::LocalConvertLinearToQuadraticTetrahedraMesh( - bool RefineOnReference, - bool InterpolateInternalVariables) + bool RefineOnReference, + bool InterpolateInternalVariables) { //checking all elements to be refined are linear tets - block_for_each(mModelPart.Elements(), [&](Element element) { - if(element.Has(SPLIT_ELEMENT) && element.GetValue(SPLIT_ELEMENT)){ - KRATOS_ERROR_IF_NOT(element.GetGeometry().GetGeometryType() == GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4) << "Element #" << element.Id() << " is not a linear tetrahedron" << std::endl; + block_for_each(mModelPart.Elements(), [](const Element& r_element) { + if(r_element.Has(SPLIT_ELEMENT) && r_element.GetValue(SPLIT_ELEMENT)){ + KRATOS_ERROR_IF_NOT(r_element.GetGeometry().GetGeometryType() == GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4) << "Element #" << r_element.Id() << " is not a linear tetrahedron" << std::endl; + } + }); + block_for_each(mModelPart.Conditions(), [](const Condition& r_condition) { + if(r_condition.Has(SPLIT_ELEMENT) && r_condition.GetValue(SPLIT_ELEMENT)){ + KRATOS_ERROR_IF_NOT(r_condition.GetGeometry().GetGeometryType() == GeometryData::KratosGeometryType::Kratos_Triangle3D3) << "Condition #" << r_condition.Id() << " is not a linear tetrahedron" << std::endl; } }); LocalRefineMesh(RefineOnReference, InterpolateInternalVariables); - } + } Tetrahedra3D10 LinearToQuadraticTetrahedraMeshConverter::GenerateTetrahedra( - ModelPart& rThisModelPart, - const std::vector& rNodeIds) + ModelPart& rThisModelPart, + const std::vector& rNodeIds) { unsigned int i0 = rNodeIds[0]; unsigned int i1 = rNodeIds[1]; @@ -59,8 +64,8 @@ namespace Kratos { } Triangle3D6 LinearToQuadraticTetrahedraMeshConverter::GenerateTriangle3D6( - ModelPart& rThisModelPart, - const array_1d& rNodeIds) + ModelPart& rThisModelPart, + const array_1d& rNodeIds) { unsigned int i0 = rNodeIds[0]; unsigned int i1 = rNodeIds[1]; @@ -120,7 +125,7 @@ namespace Kratos { //This method only copies the current information to the new element InterpolateInteralVariables(0, *it.base(), p_element, r_current_process_info); } - + // Transfer elemental variables to new element p_element->GetData() = it->GetData(); p_element->GetValue(SPLIT_ELEMENT) = false; @@ -168,7 +173,7 @@ namespace Kratos { // GlobalPointersVector< Element >& children = p_element->GetValue(NEIGHBOUR_ELEMENTS); auto& children = p_element->GetValue(NEIGHBOUR_ELEMENTS); p_element = children[0].shared_from_this(); - } + } } //Recursively for all subModelParts @@ -239,7 +244,7 @@ namespace Kratos { // GlobalPointersVector< Condition >& children = p_cond->GetValue(NEIGHBOUR_CONDITIONS); auto& children = p_cond->GetValue(NEIGHBOUR_CONDITIONS); p_cond = children[0].shared_from_this(); - } + } } for (ModelPart::SubModelPartIterator i_submodelpart = rThisModelPart.SubModelPartsBegin(); i_submodelpart != rThisModelPart.SubModelPartsEnd(); i_submodelpart++) diff --git a/applications/MeshingApplication/python_registry_lists.py b/applications/MeshingApplication/python_registry_lists.py new file mode 100644 index 000000000000..36c2595a9771 --- /dev/null +++ b/applications/MeshingApplication/python_registry_lists.py @@ -0,0 +1,11 @@ +python_modelers_to_be_registered = [ + "modelers.convert_linear_tetrahedra_to_quadratic_modeler.ConvertLinearTetrahedraToQuadraticModeler", +] + +python_operations_to_be_registered = [] + +python_processes_to_be_registered = [] + +python_stages_to_be_registered = [] + +python_orchestrators_to_be_registered = [] \ No newline at end of file diff --git a/applications/MeshingApplication/python_scripts/modelers/convert_linear_tetrahedra_to_quadratic_modeler.py b/applications/MeshingApplication/python_scripts/modelers/convert_linear_tetrahedra_to_quadratic_modeler.py new file mode 100644 index 000000000000..08fc75b20ee8 --- /dev/null +++ b/applications/MeshingApplication/python_scripts/modelers/convert_linear_tetrahedra_to_quadratic_modeler.py @@ -0,0 +1,94 @@ +import KratosMultiphysics +from KratosMultiphysics import MeshingApplication as Meshing + +class ConvertLinearTetrahedraToQuadraticModeler(KratosMultiphysics.Modeler): + """ + This class is a modeler in KratosMultiphysics that converts linear tetrahedral (tet) elements to quadratic tet elements within a specified model part. + + Attributes: + model (KratosMultiphysics.Model): The Kratos model containing the model part to be modified. + settings (KratosMultiphysics.Parameters): Settings for the conversion process. + + Methods: + __init__(model, settings): Constructor for the class. + SetupModelPart(): Performs the conversion from linear to quadratic tet elements. + __GetDefaultSettings(): Provides default settings for the modeler. + __str__(): String representation of the class. + Factory(model, settings): Factory method to create an instance of the class. + """ + + def __init__(self, model, settings): + """ + Constructor for the ConvertLinearTetrahedraToQuadraticModeler class. + + Args: + model (KratosMultiphysics.Model): The Kratos model containing the model part to be modified. + settings (KratosMultiphysics.Parameters): Configuration settings for the modeler. + + The constructor initializes the modeler with the provided model and settings, and validates and assigns default settings. + """ + super().__init__(model, settings) + settings.ValidateAndAssignDefaults(self.__GetDefaultSettings()) + self.model = model + self.settings = settings + + def SetupModelPart(self): + """ + Converts the specified model part's linear tet elements to quadratic tets. + + Raises: + Exception: If the operation is attempted in a distributed (MPI) run or if the input elements are not linear tets (4 nodes). + + This method checks the model part for compatibility, sets necessary variables, and calls the utility function for conversion. It also handles the replacement of elements and conditions based on provided settings. + """ + super().SetupModelPart() + + if KratosMultiphysics.IsDistributedRun(): + raise Exception("ConvertLinearTetrahedraToQuadraticModeler is not MPI-ready") + + model_part = self.model[self.settings["model_part_name"].GetString()] + if model_part != model_part.GetRootModelPart(): + raise Exception(f"A root ModelPart is required, got SubModelPart {model_part.FullName()}") + + KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( + KratosMultiphysics.SPLIT_ELEMENT, + True, + model_part.Elements) + KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( + KratosMultiphysics.SPLIT_ELEMENT, + True, + model_part.Conditions) + + Meshing.LinearToQuadraticTetrahedraMeshConverter(model_part).LocalConvertLinearToQuadraticTetrahedraMesh(False, False) + + element_name = self.settings["element_name"].GetString() + condition_name = self.settings["condition_name"].GetString() + if element_name or condition_name: + replace_settings = KratosMultiphysics.Parameters("{}") + replace_settings.AddString("element_name", element_name) + replace_settings.AddString("condition_name", condition_name) + KratosMultiphysics.ReplaceElementsAndConditionsProcess(model_part, replace_settings).Execute() + + def __GetDefaultSettings(self): + """ + Provides the default settings for the modeler. + + Returns: + KratosMultiphysics.Parameters: The default settings as a Parameters object. + + These settings include the name of the model part to be modified and the name of the element to use for replacement, if specified. + """ + return KratosMultiphysics.Parameters('''{ + "model_part_name" : "main_model_part", + "element_name" : "", + "condition_name": "" + }''') + + def __str__(self): + """ + String representation of the ConvertLinearTetrahedraToQuadraticModeler class. + + Returns: + str: A string describing the class. + """ + return "ConvertLinearTetrahedraToQuadraticModeler" diff --git a/applications/MeshingApplication/tests/test_MeshingApplication.py b/applications/MeshingApplication/tests/test_MeshingApplication.py index 2b8b4f6b3a45..29804a87e116 100644 --- a/applications/MeshingApplication/tests/test_MeshingApplication.py +++ b/applications/MeshingApplication/tests/test_MeshingApplication.py @@ -19,6 +19,7 @@ from test_local_refine_triangle_conditions import TestLocalRefineTriangleMeshConditions as TTestLocalRefineTriangleMeshConditions from test_local_refine_only_on_boundaries import TestLocalRefineOnlyOnBoundaries as TTestLocalRefineOnlyOnBoundaries from test_gradual_variable_interpolation_process import TestGradualVariableInterpolationProcess as TTestGradualVariableInterpolationProcess +from test_convert_linear_tetrahedra_to_quadratic_modeler import TestConvertLinearTetrahedraToQuadraticModeler ## NIGHTLY TESTS ## VALIDATION TESTS @@ -43,6 +44,8 @@ def AssembleTestSuites(): smallSuite.addTest(TTestLocalRefineTriangleMeshConditions('test_refine_condition_mesh')) smallSuite.addTest(TTestLocalRefineOnlyOnBoundaries('test_refine_on_boundary_edges')) smallSuite.addTest(TTestGradualVariableInterpolationProcess('test_gradual_variable_interpolation_process')) + smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([ + TestConvertLinearTetrahedraToQuadraticModeler])) if hasattr(MeshingApplication, "TetrahedraReconnectUtility") : smallSuite.addTest(TTestRedistance('test_refine_all')) smallSuite.addTest(TTestRedistance('test_refine_half')) diff --git a/applications/MeshingApplication/tests/test_convert_linear_tetrahedra_to_quadratic_modeler.py b/applications/MeshingApplication/tests/test_convert_linear_tetrahedra_to_quadratic_modeler.py new file mode 100644 index 000000000000..d4e50b2ff4aa --- /dev/null +++ b/applications/MeshingApplication/tests/test_convert_linear_tetrahedra_to_quadratic_modeler.py @@ -0,0 +1,78 @@ +from importlib import import_module +from pathlib import Path + +import KratosMultiphysics as kratos + +from KratosMultiphysics import KratosUnittest +from KratosMultiphysics.MeshingApplication.modelers.convert_linear_tetrahedra_to_quadratic_modeler import ConvertLinearTetrahedraToQuadraticModeler + + +class TestConvertLinearTetrahedraToQuadraticModeler(KratosUnittest.TestCase): + + def setUp(self): + self.model = kratos.Model() + model_part = self.model.CreateModelPart("main_model_part") + model_part.ProcessInfo.SetValue(kratos.DOMAIN_SIZE, 3) + + work_dir = Path(__file__).parent.absolute() + mdpa_io = kratos.ModelPartIO(work_dir / "cube_with_5_faces") + mdpa_io.ReadModelPart(model_part) + + + def make_modeler(self, parameters: kratos.Parameters): + registry_data = kratos.Registry[ + "Modelers.KratosMultiphysics.MeshingApplication.ConvertLinearTetrahedraToQuadraticModeler" + ] + module = import_module(registry_data["ModuleName"]) + return getattr(module, registry_data["ClassName"])(self.model, parameters) + + + def test_creation_from_registry(self): + modeler = self.make_modeler(kratos.Parameters('''{ + "model_part_name": "main_model_part" + }''')) + + self.assertIsInstance(modeler, ConvertLinearTetrahedraToQuadraticModeler) + + + def test_quadratic_refinement(self): + + model_part = self.model.GetModelPart("main_model_part") + + self.assertEqual(model_part.NumberOfNodes(), 64) + self.assertEqual(model_part.NumberOfElements(), 162) + self.assertEqual(model_part.NumberOfConditions(), 90) + self.assertEqual(len(model_part.Elements[1].GetNodes()), 4) + self.assertEqual(len(model_part.Conditions[163].GetNodes()), 3) + + modeler = ConvertLinearTetrahedraToQuadraticModeler( + self.model, + kratos.Parameters('''{ + "model_part_name": "main_model_part" + }''')) + + modeler.SetupModelPart() + + self.assertEqual(model_part.NumberOfNodes(), 343) + self.assertEqual(model_part.NumberOfElements(), 162) + self.assertEqual(model_part.NumberOfConditions(), 90) + self.assertEqual(len(model_part.Elements[1].GetNodes()), 10) + self.assertEqual(len(model_part.Conditions[163].GetNodes()), 6) + + + def test_root_required(self): + + modeler = ConvertLinearTetrahedraToQuadraticModeler( + self.model, + kratos.Parameters('''{ + "model_part_name": "main_model_part.MainPart.VolumeParts.Body1" + }''')) + + msg = "A root ModelPart is required, got SubModelPart main_model_part.MainPart.VolumeParts.Body1" + with self.assertRaisesRegex(Exception, msg): + modeler.SetupModelPart() + + + +if __name__ == "__main__": + KratosUnittest.main() \ No newline at end of file diff --git a/kratos/python/add_geometries_to_python.cpp b/kratos/python/add_geometries_to_python.cpp index eea926cdedb6..c8e0ff82b30a 100644 --- a/kratos/python/add_geometries_to_python.cpp +++ b/kratos/python/add_geometries_to_python.cpp @@ -140,6 +140,10 @@ void AddGeometriesToPython(pybind11::module& m) .def("PointsNumber", &GeometryType::PointsNumber) .def("PointsNumberInDirection", &GeometryType::PointsNumberInDirection) .def("PolynomialDegree", &GeometryType::PolynomialDegree) + // Geometry data + .def("GetDefaultIntegrationMethod", &GeometryType::GetDefaultIntegrationMethod) + .def("GetGeometryFamily", &GeometryType::GetGeometryFamily) + .def("GetGeometryType", &GeometryType::GetGeometryType) // Geometry Parts .def("GetGeometryPart", [](GeometryType& self, IndexType Index) { return(self.GetGeometryPart(Index)); }) diff --git a/kratos/python/add_geometry_data_to_python.cpp b/kratos/python/add_geometry_data_to_python.cpp new file mode 100644 index 000000000000..0508a50373f4 --- /dev/null +++ b/kratos/python/add_geometry_data_to_python.cpp @@ -0,0 +1,108 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Jordi Cotela +// + +// System includes + +// External includes + +// Project includes +#include "geometries/geometry_data.h" +#include "add_geometry_data_to_python.h" + +namespace Kratos::Python +{ + +void AddGeometryDataToPython(pybind11::module& m) +{ + namespace py = pybind11; + + auto integration_method = py::enum_(m, "GeometryData_IntegrationMethod") + .value("GI_GAUSS_1", GeometryData::IntegrationMethod::GI_GAUSS_1) + .value("GI_GAUSS_2", GeometryData::IntegrationMethod::GI_GAUSS_2) + .value("GI_GAUSS_3", GeometryData::IntegrationMethod::GI_GAUSS_3) + .value("GI_GAUSS_4", GeometryData::IntegrationMethod::GI_GAUSS_4) + .value("GI_GAUSS_5", GeometryData::IntegrationMethod::GI_GAUSS_5) + .value("GI_EXTENDED_GAUSS_1", GeometryData::IntegrationMethod::GI_EXTENDED_GAUSS_1) + .value("GI_EXTENDED_GAUSS_2", GeometryData::IntegrationMethod::GI_EXTENDED_GAUSS_2) + .value("GI_EXTENDED_GAUSS_3", GeometryData::IntegrationMethod::GI_EXTENDED_GAUSS_3) + .value("GI_EXTENDED_GAUSS_4", GeometryData::IntegrationMethod::GI_EXTENDED_GAUSS_4) + .value("GI_EXTENDED_GAUSS_5", GeometryData::IntegrationMethod::GI_EXTENDED_GAUSS_5); + + auto geometry_family = py::enum_(m, "GeometryData_KratosGeometryFamily") + .value("Kratos_NoElement", GeometryData::KratosGeometryFamily::Kratos_NoElement) + .value("Kratos_Point", GeometryData::KratosGeometryFamily::Kratos_Point) + .value("Kratos_Linear", GeometryData::KratosGeometryFamily::Kratos_Linear) + .value("Kratos_Triangle", GeometryData::KratosGeometryFamily::Kratos_Triangle) + .value("Kratos_Quadrilateral", GeometryData::KratosGeometryFamily::Kratos_Quadrilateral) + .value("Kratos_Tetrahedra", GeometryData::KratosGeometryFamily::Kratos_Tetrahedra) + .value("Kratos_Hexahedra", GeometryData::KratosGeometryFamily::Kratos_Hexahedra) + .value("Kratos_Prism", GeometryData::KratosGeometryFamily::Kratos_Prism) + .value("Kratos_Pyramid", GeometryData::KratosGeometryFamily::Kratos_Pyramid) + .value("Kratos_Nurbs", GeometryData::KratosGeometryFamily::Kratos_Nurbs) + .value("Kratos_Brep", GeometryData::KratosGeometryFamily::Kratos_Brep) + .value("Kratos_Quadrature_Geometry", GeometryData::KratosGeometryFamily::Kratos_Quadrature_Geometry) + .value("Kratos_Composite", GeometryData::KratosGeometryFamily::Kratos_Composite) + .value("Kratos_generic_family", GeometryData::KratosGeometryFamily::Kratos_generic_family); + + auto geometry_type = py::enum_(m, "GeometryData_KratosGeometryType") + .value("Kratos_generic_type", GeometryData::KratosGeometryType::Kratos_generic_type) + .value("Kratos_Hexahedra3D20", GeometryData::KratosGeometryType::Kratos_Hexahedra3D20) + .value("Kratos_Hexahedra3D27", GeometryData::KratosGeometryType::Kratos_Hexahedra3D27) + .value("Kratos_Hexahedra3D8", GeometryData::KratosGeometryType::Kratos_Hexahedra3D8) + .value("Kratos_Prism3D15", GeometryData::KratosGeometryType::Kratos_Prism3D15) + .value("Kratos_Prism3D6", GeometryData::KratosGeometryType::Kratos_Prism3D6) + .value("Kratos_Pyramid3D13", GeometryData::KratosGeometryType::Kratos_Pyramid3D13) + .value("Kratos_Pyramid3D5", GeometryData::KratosGeometryType::Kratos_Pyramid3D5) + .value("Kratos_Quadrilateral2D4", GeometryData::KratosGeometryType::Kratos_Quadrilateral2D4) + .value("Kratos_Quadrilateral2D8", GeometryData::KratosGeometryType::Kratos_Quadrilateral2D8) + .value("Kratos_Quadrilateral2D9", GeometryData::KratosGeometryType::Kratos_Quadrilateral2D9) + .value("Kratos_Quadrilateral3D4", GeometryData::KratosGeometryType::Kratos_Quadrilateral3D4) + .value("Kratos_Quadrilateral3D8", GeometryData::KratosGeometryType::Kratos_Quadrilateral3D8) + .value("Kratos_Quadrilateral3D9", GeometryData::KratosGeometryType::Kratos_Quadrilateral3D9) + .value("Kratos_Tetrahedra3D10", GeometryData::KratosGeometryType::Kratos_Tetrahedra3D10) + .value("Kratos_Tetrahedra3D4", GeometryData::KratosGeometryType::Kratos_Tetrahedra3D4) + .value("Kratos_Triangle2D3", GeometryData::KratosGeometryType::Kratos_Triangle2D3) + .value("Kratos_Triangle2D6", GeometryData::KratosGeometryType::Kratos_Triangle2D6) + .value("Kratos_Triangle2D10", GeometryData::KratosGeometryType::Kratos_Triangle2D10) + .value("Kratos_Triangle2D15", GeometryData::KratosGeometryType::Kratos_Triangle2D15) + .value("Kratos_Triangle3D3", GeometryData::KratosGeometryType::Kratos_Triangle3D3) + .value("Kratos_Triangle3D6", GeometryData::KratosGeometryType::Kratos_Triangle3D6) + .value("Kratos_Line2D2", GeometryData::KratosGeometryType::Kratos_Line2D2) + .value("Kratos_Line2D3", GeometryData::KratosGeometryType::Kratos_Line2D3) + .value("Kratos_Line2D4", GeometryData::KratosGeometryType::Kratos_Line2D4) + .value("Kratos_Line2D5", GeometryData::KratosGeometryType::Kratos_Line2D5) + .value("Kratos_Line3D2", GeometryData::KratosGeometryType::Kratos_Line3D2) + .value("Kratos_Line3D3", GeometryData::KratosGeometryType::Kratos_Line3D3) + .value("Kratos_Point2D", GeometryData::KratosGeometryType::Kratos_Point2D) + .value("Kratos_Point3D", GeometryData::KratosGeometryType::Kratos_Point3D) + .value("Kratos_Sphere3D1", GeometryData::KratosGeometryType::Kratos_Sphere3D1) + .value("Kratos_Nurbs_Curve", GeometryData::KratosGeometryType::Kratos_Nurbs_Curve) + .value("Kratos_Nurbs_Surface", GeometryData::KratosGeometryType::Kratos_Nurbs_Surface) + .value("Kratos_Nurbs_Volume", GeometryData::KratosGeometryType::Kratos_Nurbs_Volume) + .value("Kratos_Nurbs_Curve_On_Surface", GeometryData::KratosGeometryType::Kratos_Nurbs_Curve_On_Surface) + .value("Kratos_Surface_In_Nurbs_Volume", GeometryData::KratosGeometryType::Kratos_Surface_In_Nurbs_Volume) + .value("Kratos_Brep_Curve", GeometryData::KratosGeometryType::Kratos_Brep_Curve) + .value("Kratos_Brep_Surface", GeometryData::KratosGeometryType::Kratos_Brep_Surface) + .value("Kratos_Brep_Curve_On_Surface", GeometryData::KratosGeometryType::Kratos_Brep_Curve_On_Surface) + .value("Kratos_Quadrature_Point_Geometry", GeometryData::KratosGeometryType::Kratos_Quadrature_Point_Geometry) + .value("Kratos_Coupling_Geometry", GeometryData::KratosGeometryType::Kratos_Coupling_Geometry) + .value("Kratos_Quadrature_Point_Curve_On_Surface_Geometry", GeometryData::KratosGeometryType::Kratos_Quadrature_Point_Curve_On_Surface_Geometry) + .value("Kratos_Quadrature_Point_Surface_In_Volume_Geometry", GeometryData::KratosGeometryType::Kratos_Quadrature_Point_Surface_In_Volume_Geometry); + + py::class_(m, "GeometryData") + .def_property_readonly_static("IntegrationMethod", [integration_method](py::object) { return integration_method; }) + .def_property_readonly_static("KratosGeometryFamily", [geometry_family](py::object) { return geometry_family; }) + .def_property_readonly_static("KratosGeometryType", [geometry_type](py::object) { return geometry_type; }); + +} + +} \ No newline at end of file diff --git a/kratos/python/add_geometry_data_to_python.h b/kratos/python/add_geometry_data_to_python.h new file mode 100644 index 000000000000..d690f579f91f --- /dev/null +++ b/kratos/python/add_geometry_data_to_python.h @@ -0,0 +1,27 @@ +// | / | +// ' / __| _` | __| _ \ __| +// . \ | ( | | ( |\__ ` +// _|\_\_| \__,_|\__|\___/ ____/ +// Multi-Physics +// +// License: BSD License +// Kratos default license: kratos/license.txt +// +// Main authors: Jordi Cotela +// + +#pragma once + +// System includes +#include + +// External includes + +// Project includes + +namespace Kratos::Python +{ + +void AddGeometryDataToPython(pybind11::module& m); + +} // namespace Kratos::Python. diff --git a/kratos/python/kratos_python.cpp b/kratos/python/kratos_python.cpp index 74486fafaa67..bc02d503c267 100644 --- a/kratos/python/kratos_python.cpp +++ b/kratos/python/kratos_python.cpp @@ -76,6 +76,7 @@ #include "add_container_expression_to_python.h" #include "add_accessors_to_python.h" #include "add_globals_to_python.h" +#include "add_geometry_data_to_python.h" namespace Kratos::Python { @@ -134,6 +135,7 @@ PYBIND11_MODULE(Kratos, m) AddConstitutiveLawToPython(m); AddSerializerToPython(m); AddTableToPython(m); + AddGeometryDataToPython(m); AddGeometriesToPython(m); AddBoundingBoxToPython(m); diff --git a/kratos/tests/test_geometry_data.py b/kratos/tests/test_geometry_data.py new file mode 100644 index 000000000000..a57120b53cc8 --- /dev/null +++ b/kratos/tests/test_geometry_data.py @@ -0,0 +1,75 @@ +import KratosMultiphysics as kratos +from KratosMultiphysics import KratosUnittest + +class TestGeometryData(KratosUnittest.TestCase): + + def setUp(self): + self.model = kratos.Model() + self.model_part = self.model.CreateModelPart("model_part") + + self.model_part.CreateNewNode(1, 0.0, 0.0, 0.0) + self.model_part.CreateNewNode(2, 1.0, 0.0, 0.0) + self.model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + self.model_part.CreateNewNode(4, 0.5, 0.0, 0.0) + self.model_part.CreateNewNode(5, 0.5, 0.5, 0.0) + self.model_part.CreateNewNode(6, 0.0, 0.5, 0.0) + + self.model_part.CreateNewNode(7, 0.0, 0.0, 1.0) + + prop = self.model_part.GetProperties()[1] + + self.model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) + self.model_part.CreateNewElement("Element2D6N", 2, [1, 2, 3, 4, 5, 6], prop) + self.model_part.CreateNewElement("Element3D4N", 3, [1, 2, 3, 7], prop) + + self.model_part.CreateNewCondition("LineCondition3D2N", 1, [1, 7], prop) + + + def test_geometry_data(self): + + triangle_2d_3 = self.model_part.Elements[1].GetGeometry() + self.assertEqual( + triangle_2d_3.GetDefaultIntegrationMethod(), + kratos.GeometryData.IntegrationMethod.GI_GAUSS_1) + self.assertEqual( + triangle_2d_3.GetGeometryFamily(), + kratos.GeometryData.KratosGeometryFamily.Kratos_Triangle) + self.assertEqual( + triangle_2d_3.GetGeometryType(), + kratos.GeometryData.KratosGeometryType.Kratos_Triangle2D3) + + triangle_2d_6 = self.model_part.Elements[2].GetGeometry() + self.assertEqual( + triangle_2d_6.GetDefaultIntegrationMethod(), + kratos.GeometryData.IntegrationMethod.GI_GAUSS_2) + self.assertEqual( + triangle_2d_6.GetGeometryFamily(), + kratos.GeometryData.KratosGeometryFamily.Kratos_Triangle) + self.assertEqual( + triangle_2d_6.GetGeometryType(), + kratos.GeometryData.KratosGeometryType.Kratos_Triangle2D6) + + tetrahedron_3d_4 = self.model_part.Elements[3].GetGeometry() + self.assertEqual( + tetrahedron_3d_4.GetDefaultIntegrationMethod(), + kratos.GeometryData.IntegrationMethod.GI_GAUSS_1) + self.assertEqual( + tetrahedron_3d_4.GetGeometryFamily(), + kratos.GeometryData.KratosGeometryFamily.Kratos_Tetrahedra) + self.assertEqual( + tetrahedron_3d_4.GetGeometryType(), + kratos.GeometryData.KratosGeometryType.Kratos_Tetrahedra3D4) + + line_3d_2 = self.model_part.Conditions[1].GetGeometry() + self.assertEqual( + line_3d_2.GetDefaultIntegrationMethod(), + kratos.GeometryData.IntegrationMethod.GI_GAUSS_1) + self.assertEqual( + line_3d_2.GetGeometryFamily(), + kratos.GeometryData.KratosGeometryFamily.Kratos_Linear) + self.assertEqual( + line_3d_2.GetGeometryType(), + kratos.GeometryData.KratosGeometryType.Kratos_Line3D2) + +if __name__ == "__main__": + KratosUnittest.main() \ No newline at end of file