From 91a8975ec13dab7b86acccfbd2160045c2469e5f Mon Sep 17 00:00:00 2001 From: philbucher Date: Mon, 16 Oct 2023 01:31:24 +0200 Subject: [PATCH 01/12] WIP support more geometries --- .../custom_io/med_model_part_io.cpp | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/applications/MedApplication/custom_io/med_model_part_io.cpp b/applications/MedApplication/custom_io/med_model_part_io.cpp index fd0bc2afbbbd..7136fdda9028 100644 --- a/applications/MedApplication/custom_io/med_model_part_io.cpp +++ b/applications/MedApplication/custom_io/med_model_part_io.cpp @@ -34,6 +34,7 @@ static const std::map Krato { GeometryData::KratosGeometryType::Kratos_Line3D2, MED_SEG2 }, { GeometryData::KratosGeometryType::Kratos_Line2D3, MED_SEG3 }, { GeometryData::KratosGeometryType::Kratos_Line3D3, MED_SEG3 }, + { GeometryData::KratosGeometryType::Kratos_Line2D4, MED_SEG4 }, { GeometryData::KratosGeometryType::Kratos_Triangle2D3, MED_TRIA3 }, { GeometryData::KratosGeometryType::Kratos_Triangle3D3, MED_TRIA3 }, @@ -86,7 +87,7 @@ std::function&)> GetReorderFunction(const med_geometry_type }; case MED_TRIA6: - return [](auto& rConnectivities) -> void { + return [](auto& rConnectivities){ CheckConnectivitiesSize(6, rConnectivities); std::swap(rConnectivities[1], rConnectivities[2]); std::swap(rConnectivities[3], rConnectivities[5]); @@ -99,28 +100,73 @@ std::function&)> GetReorderFunction(const med_geometry_type }; case MED_QUAD8: - KRATOS_ERROR << "MED_QUAD8 is med_quad8 is not implemented!" << std::endl; + return [](auto& Connectivities){ + CheckConnectivitiesSize(8, Connectivities); + std::swap(Connectivities[1], Connectivities[3]); + std::swap(Connectivities[4], Connectivities[7]); + std::swap(Connectivities[5], Connectivities[6]); + }; - case MED_QUAD9: // should be same as MED_QUAD8 - KRATOS_ERROR << "MED_QUAD9 is not implemented!" << std::endl; + case MED_QUAD9: + return [](auto& Connectivities){ + CheckConnectivitiesSize(9, Connectivities); + std::swap(Connectivities[1], Connectivities[3]); + std::swap(Connectivities[4], Connectivities[7]); + std::swap(Connectivities[5], Connectivities[6]); + }; case MED_TETRA10: - return [](auto& rConnectivities) -> void { + return [](auto& rConnectivities){ CheckConnectivitiesSize(10, rConnectivities); std::swap(rConnectivities[1], rConnectivities[2]); std::swap(rConnectivities[4], rConnectivities[6]); std::swap(rConnectivities[8], rConnectivities[9]); }; + case MED_HEXA8: + return [](auto& rConnectivities){ + CheckConnectivitiesSize(8, rConnectivities); + std::swap(rConnectivities[1], rConnectivities[4]); + std::swap(rConnectivities[2], rConnectivities[7]); + }; + + case MED_HEXA20: + KRATOS_ERROR << "MED_HEXA20 is not implemented!" << std::endl; + return [](auto& rConnectivities){ + CheckConnectivitiesSize(20, rConnectivities); + std::swap(rConnectivities[1], rConnectivities[4]); + std::swap(rConnectivities[2], rConnectivities[7]); + }; + + case MED_HEXA27: + KRATOS_ERROR << "MED_HEXA27 is not implemented!" << std::endl; + return [](auto& rConnectivities){ + CheckConnectivitiesSize(20, rConnectivities); + std::swap(rConnectivities[1], rConnectivities[4]); + std::swap(rConnectivities[2], rConnectivities[7]); + }; + case MED_PYRA5: KRATOS_ERROR << "MED_PYRA5 is not implemented!" << std::endl; case MED_PYRA13: KRATOS_ERROR << "MED_PYRA13 is not implemented!" << std::endl; + case MED_PENTA6: + KRATOS_ERROR << "MED_PENTA6 is not implemented!" << std::endl; + + case MED_PENTA15: + KRATOS_ERROR << "MED_PENTA15 is not implemented!" << std::endl; + default: return [](auto& Connectivities){ // does nothing if no reordering is needed + /* + - MED_POINT1 + - MED_SEG2 + - MED_SEG3 + - MED_SEG4 + */ }; } } From 2a6a12a727a1fa83c8c1e683e6515eb1aa0edd70 Mon Sep 17 00:00:00 2001 From: philbucher Date: Mon, 16 Oct 2023 01:39:13 +0200 Subject: [PATCH 02/12] WIP hexa test --- .../med_files/hexahedral_8N/create_mesh.py | 13 +++--- .../tests/med_files/hexahedral_8N/mesh.med | Bin 17855 -> 25631 bytes .../tests/test_med_model_part_io.py | 42 ++++++++++++++++-- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/applications/MedApplication/tests/med_files/hexahedral_8N/create_mesh.py b/applications/MedApplication/tests/med_files/hexahedral_8N/create_mesh.py index bc7091a1c59c..6e056c1edd68 100644 --- a/applications/MedApplication/tests/med_files/hexahedral_8N/create_mesh.py +++ b/applications/MedApplication/tests/med_files/hexahedral_8N/create_mesh.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ### -### This file is generated automatically by SALOME v9.6.0 with dump python functionality +### This file is generated automatically by SALOME v9.4.0 with dump python functionality ### import salome @@ -46,26 +46,23 @@ Mesh_1 = smesh.Mesh(Box_1) Regular_1D = Mesh_1.Segment() -Number_of_Segments_1 = Regular_1D.NumberOfSegments(50) +Number_of_Segments_1 = Regular_1D.NumberOfSegments(5) Quadrangle_2D = Mesh_1.Quadrangle(algo=smeshBuilder.QUADRANGLE) Hexa_3D = Mesh_1.Hexahedron(algo=smeshBuilder.Hexa) -Number_of_Segments_1.SetNumberOfSegments( 3 ) isDone = Mesh_1.Compute() smesh.SetName(Mesh_1, 'Mesh_1') try: - Mesh_1.ExportMED(r'applications/MedApplication/tests/med_files/hexahedral_8N/mesh.med',auto_groups=0,version=41,overwrite=1,meshPart=None,autoDimension=1) + Mesh_1.ExportMED(r'applications/MedApplication/tests/med_files/hexahedral_8N/mesh.med',auto_groups=0,minor=40,overwrite=1,meshPart=None,autoDimension=1) pass except: print('ExportMED() failed. Invalid file name?') - ## Set names of Mesh objects smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D') -smesh.SetName(Hexa_3D.GetAlgorithm(), 'Hexa_3D') smesh.SetName(Quadrangle_2D.GetAlgorithm(), 'Quadrangle_2D') -smesh.SetName(Number_of_Segments_1, 'Number of Segments_1') +smesh.SetName(Hexa_3D.GetAlgorithm(), 'Hexa_3D') smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1') - +smesh.SetName(Number_of_Segments_1, 'Number of Segments_1') if salome.sg.hasDesktop(): salome.sg.updateObjBrowser() diff --git a/applications/MedApplication/tests/med_files/hexahedral_8N/mesh.med b/applications/MedApplication/tests/med_files/hexahedral_8N/mesh.med index bad5523461ac305fd163ef6e33500b15c5a52685..139ba4a2a6712b46da46adc88c293644f190f926 100644 GIT binary patch literal 25631 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 diff --git a/applications/MedApplication/tests/test_med_model_part_io.py b/applications/MedApplication/tests/test_med_model_part_io.py index 5398fa814da4..daa03788d822 100644 --- a/applications/MedApplication/tests/test_med_model_part_io.py +++ b/applications/MedApplication/tests/test_med_model_part_io.py @@ -20,10 +20,13 @@ def setUp(self): self.mp_read_1 = self.model.CreateModelPart("read_1") self.mp_read_2 = self.model.CreateModelPart("read_2") - def _execute_tests(self, med_path, check_fct): + def _execute_tests(self, med_path, check_fct, print_vtk=False): med_io_read_1 = KratosMed.MedModelPartIO(GetMedPath(med_path)) med_io_read_1.ReadModelPart(self.mp_read_1) + if print_vtk: + write_vtk(self.mp_read_1, med_path) + self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeLength(self.mp_read_1), 0.0) self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeArea(self.mp_read_1), 0.0) self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeVolume(self.mp_read_1), 0.0) @@ -114,8 +117,41 @@ def test_tetrahedra_4N_linear_mesh(self): raise NotImplementedError def test_hexahedra_8N_linear_mesh(self): - self.skipTest("This test is not yet implemented") - raise NotImplementedError + def mp_check_fct(model_part): + self.assertEqual(model_part.NumberOfNodes(), 4) + + exp_coords = [ + (0,0,0), (0,0,1),(0,1,1),(1,1,1) + ] + + for coords, node in zip(exp_coords, model_part.Nodes): + self.assertAlmostEqual(node.X, coords[0]) + self.assertAlmostEqual(node.X0, coords[0]) + self.assertAlmostEqual(node.Y, coords[1]) + self.assertAlmostEqual(node.Y0, coords[1]) + self.assertAlmostEqual(node.Z, coords[2]) + self.assertAlmostEqual(node.Z0, coords[2]) + + self._execute_tests("hexahedral_8N", mp_check_fct, True) + +def write_vtk(model_part, name): + modeler_parameters = KM.Parameters("""{ + "elements_list" : [{ + "model_part_name" : "read_1", + "element_name" : "Element2D3N;Element2D4N;Element3D8N" + }] + }""") + modeler = KM.CreateEntitiesFromGeometriesModeler(model_part.GetModel(), modeler_parameters) + modeler.SetupModelPart(); + + vtk_parameters = KM.Parameters("""{ + "file_format" : "binary", + "output_sub_model_parts" : false, + "save_output_files_in_folder" : true + }""") + + vtk_io = KM.VtkOutput(model_part, vtk_parameters) + vtk_io.PrintOutput(name) if __name__ == '__main__': From 6ac10e6c01a1497c57efa2a7f0fd4bdeb8eba473 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 21:20:43 +0200 Subject: [PATCH 03/12] minor simplification --- .../MedApplication/custom_utilities/med_testing_utilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/MedApplication/custom_utilities/med_testing_utilities.cpp b/applications/MedApplication/custom_utilities/med_testing_utilities.cpp index 8b3c9e6e97c8..3d76d2c20abe 100644 --- a/applications/MedApplication/custom_utilities/med_testing_utilities.cpp +++ b/applications/MedApplication/custom_utilities/med_testing_utilities.cpp @@ -165,7 +165,7 @@ double ComputeGeometricalQuantity( const ModelPart& rModelPart, const QuantityType Quantity) { - std::function access_function; + std::function access_function; switch (Quantity) { From c72c173ed973b588bd1f29684e2ef30853a30878 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 21:46:23 +0200 Subject: [PATCH 04/12] more tests --- .../custom_io/med_model_part_io.cpp | 8 +- .../tests/med_files/tetrahedral_10N/mesh.med | Bin 0 -> 35564 bytes .../med_files/tetrahedral_4N/create_mesh.py | 80 ------------------ .../tests/med_files/tetrahedral_4N/mesh.med | Bin 15034 -> 26552 bytes .../tests/test_med_model_part_io.py | 40 +++++++-- 5 files changed, 41 insertions(+), 87 deletions(-) create mode 100644 applications/MedApplication/tests/med_files/tetrahedral_10N/mesh.med delete mode 100644 applications/MedApplication/tests/med_files/tetrahedral_4N/create_mesh.py diff --git a/applications/MedApplication/custom_io/med_model_part_io.cpp b/applications/MedApplication/custom_io/med_model_part_io.cpp index 7136fdda9028..16ebc67a40b8 100644 --- a/applications/MedApplication/custom_io/med_model_part_io.cpp +++ b/applications/MedApplication/custom_io/med_model_part_io.cpp @@ -34,7 +34,6 @@ static const std::map Krato { GeometryData::KratosGeometryType::Kratos_Line3D2, MED_SEG2 }, { GeometryData::KratosGeometryType::Kratos_Line2D3, MED_SEG3 }, { GeometryData::KratosGeometryType::Kratos_Line3D3, MED_SEG3 }, - { GeometryData::KratosGeometryType::Kratos_Line2D4, MED_SEG4 }, { GeometryData::KratosGeometryType::Kratos_Triangle2D3, MED_TRIA3 }, { GeometryData::KratosGeometryType::Kratos_Triangle3D3, MED_TRIA3 }, @@ -115,6 +114,12 @@ std::function&)> GetReorderFunction(const med_geometry_type std::swap(Connectivities[5], Connectivities[6]); }; + case MED_TETRA4: + return [](auto& rConnectivities){ + CheckConnectivitiesSize(4, rConnectivities); + std::swap(rConnectivities[2], rConnectivities[3]); + }; + case MED_TETRA10: return [](auto& rConnectivities){ CheckConnectivitiesSize(10, rConnectivities); @@ -165,7 +170,6 @@ std::function&)> GetReorderFunction(const med_geometry_type - MED_POINT1 - MED_SEG2 - MED_SEG3 - - MED_SEG4 */ }; } diff --git a/applications/MedApplication/tests/med_files/tetrahedral_10N/mesh.med b/applications/MedApplication/tests/med_files/tetrahedral_10N/mesh.med new file mode 100644 index 0000000000000000000000000000000000000000..1faa1fa700964732648cdab473868eb5d1375be4 GIT binary patch literal 35564 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 literal 0 HcmV?d00001 diff --git a/applications/MedApplication/tests/med_files/tetrahedral_4N/create_mesh.py b/applications/MedApplication/tests/med_files/tetrahedral_4N/create_mesh.py deleted file mode 100644 index 3859f7de0a30..000000000000 --- a/applications/MedApplication/tests/med_files/tetrahedral_4N/create_mesh.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python - -### -### This file is generated automatically by SALOME v9.6.0 with dump python functionality -### - -import salome - -salome.salome_init() -import salome_notebook -notebook = salome_notebook.NoteBook() - -### -### GEOM component -### - -import GEOM -from salome.geom import geomBuilder -import math -import SALOMEDS - - -geompy = geomBuilder.New() - -O = geompy.MakeVertex(0, 0, 0) -OX = geompy.MakeVectorDXDYDZ(1, 0, 0) -OY = geompy.MakeVectorDXDYDZ(0, 1, 0) -OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) -Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) -geompy.addToStudy( O, 'O' ) -geompy.addToStudy( OX, 'OX' ) -geompy.addToStudy( OY, 'OY' ) -geompy.addToStudy( OZ, 'OZ' ) -geompy.addToStudy( Box_1, 'Box_1' ) - -### -### SMESH component -### - -import SMESH, SALOMEDS -from salome.smesh import smeshBuilder - -smesh = smeshBuilder.New() -#smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations: - # multiples meshes built in parallel, complex and numerous mesh edition (performance) - -#hyp_16.SetLength( 34.641 ) ### not created Object -NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters', 'NETGENEngine', 34.641, 0 ) -Mesh_1 = smesh.Mesh(Box_1) -status = Mesh_1.AddHypothesis( Box_1, NETGEN_3D_Parameters_1 ) -NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) -NETGEN_3D_Parameters_1.SetMaxSize( 100 ) -NETGEN_3D_Parameters_1.SetMinSize( 0.34641 ) -NETGEN_3D_Parameters_1.SetSecondOrder( 0 ) -NETGEN_3D_Parameters_1.SetOptimize( 1 ) -NETGEN_3D_Parameters_1.SetFineness( 2 ) -NETGEN_3D_Parameters_1.SetChordalError( 17.3205 ) -NETGEN_3D_Parameters_1.SetChordalErrorEnabled( 1 ) -NETGEN_3D_Parameters_1.SetUseSurfaceCurvature( 1 ) -NETGEN_3D_Parameters_1.SetFuseEdges( 1 ) -NETGEN_3D_Parameters_1.SetCheckChartBoundary( 0 ) -NETGEN_3D_Parameters_1.SetQuadAllowed( 0 ) -NETGEN_3D_Parameters_1.SetCheckChartBoundary( 3 ) -isDone = Mesh_1.Compute() -smesh.SetName(Mesh_1, 'Mesh_1') -try: - Mesh_1.ExportMED(r'applications/MedApplication/tests/med_files/tetrahedral_4N/mesh.med',auto_groups=0,version=41,overwrite=1,meshPart=None,autoDimension=1) - pass -except: - print('ExportMED() failed. Invalid file name?') - - -## Set names of Mesh objects -smesh.SetName(NETGEN_1D_2D_3D.GetAlgorithm(), 'NETGEN 1D-2D-3D') -smesh.SetName(NETGEN_3D_Parameters_1, 'NETGEN 3D Parameters_1') -smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1') - - -if salome.sg.hasDesktop(): - salome.sg.updateObjBrowser() diff --git a/applications/MedApplication/tests/med_files/tetrahedral_4N/mesh.med b/applications/MedApplication/tests/med_files/tetrahedral_4N/mesh.med index baab49cf5552bf90213551ce0b35b3f37047cf64..f991181f7b2df1b7ca39df1552d4c84614763e24 100644 GIT binary patch literal 26552 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 R!vFr8qPAd*27Unz{0}9S!~*~T literal 15034 zcmeI3du$v>9mnU+jqNxtc0)=@O47Vz=TSSgNl2i?cfLLQoO`%;=a5(sN035;2#FK{ zmMWkWMJiNHct}zIiK<4eKtQP|5^+mK3i*Rdt(r^0Bm4I4ew>^~#89v9g7UOe}V< zrZ=tm9cHvC87rJ@c1DyfL4KED?Y8!&V3i)JrqcBb)ir)~+t(=7q$k?VWF|JEI<-$6 zw+yJLmZ^vB<|a&KeS~6#auMdOw2x32svn&H<;h?>s=M|&zWrvCBYutethvu<+O?_I*ER=@eU;sK=_;+5W6L`}d8I9x zA0D;0T~u|>sLwU^MTzoGHlr71$%2`sRe$N_aL@rVtxMw*TUd1Z#LIWai^B=6k(R9Y zo7&%XQdTTbNZIz$pY$aQno6M`mjDRAYt*Qk)H2L=Fzo@6bfeu<3S51E_fzp=I;rJ0 z8A_c*rl*xUdE59rwbcyhi`5Jit?#$1$IW6Hh#xt)OufHsVCyH&EPgfYH69+i}(NKMfKq_v8zVfFRFKyEqV6u8!oGTWdrwKIRDo0 z)QP=jsL^KSfve4ky)7cPJ{fWH#Y1Tv*`4j zkDL!y>3h+YnoP2=|6WHrX=~QHnSHHlxF=@EG8OM&YTJxf|MIV%*M9V;;Cs#8kxrci zf86G<T;wR25l#&yTd?k@WD#c&T{sy4#WT{UtX-BlyUY@!OsP0oR2kx9{` zn((^iJ4y$V{spRkTE~~WzEW?TaT}G(*Jjk%o8nr#ts!yd&krvVJvUn}nQg?9T{@`3M z3b+WX1}E-v$}Bs3bCqKIMiKf>r>jU$ zT)N0X59FaY`Yw?5=!YKYjXv1r)eC>1AO1j3Q~fja`-WMqlLP zU+l#W=&%F5@h5sCkM+bs+&X6g`|&US!d~KuKd|2$H})OzB2L7|yPxpC*YEfn|FX~J zmapXWrQSVfJ>F2prVMjH#A=uQeBIOV3{71BD+4&{rK(xA)CpOyM9x*!6s%i*Dyh%Z zFDuu(X+3+rN_9nkcGf?+_g86SLh$C4swNXlU6J&=a(>3SRQwO*javKO<5tUMLN=Eu zO4be*XE+>Q>~NTJVCJ!Wrb|Cdvm197>Hc|q0F{&Bo@j~T{TQ&>!KEf^lt zb9#T7_LTkqtTQqKJ=RpY=IR>L^mk5m*WWkCGcC9zsEazdW@|L(^96IC+u zM7Oh3NE_aCR*;MxoE%I#JG9o}FeO`V<~h^4bu#2hXR$l`kA|91%=djwQti3?lS{+4 z!>2?P7=Ec7TIMX-C*?q}g{~_gDE+O*##%E(ebZn1*mKW&>q_bz>Koh-Qr}dnTc{&J z>KYD{@TXp)o&@19xyU~98ZRN=i_}Bt3xDLH2MB-aC+tVQ7sKi}&I@f4O8i1yh#u69 z*yW|ePt<$x0~u#M{IDB6vCB(`pU@Y6AmgluA92DS^oEXjpeKC11@I&|i+nKKjuIk?ZAy9;`zi zh&}YNm;K7V0-*LF9Y=2t9hE5B#tLeHmvR^!NcJpVLPV_5%oC{10FHUU^Swi;om}Q2mMLKpxiviNAI?(ls|{$p4TfI-CO?T*EgS!$F@4_*&b($nEWE++OXYPrjoc+!Jy;vpg&$P@ za0YS_R?86eEq^|H>4k^izVz2CX{2W3JcN~>{(R%q9S6fMaa;?A$Mn$6&Ng^OcEj9^ z>8n3~p|AeF$@Tm%_~vxS!A%m}{~zFcz7LAYd`mPS{g_}}a8NKIXbC0-hXjWOQ-ULc zI|b8%8NsYzPH Date: Mon, 16 Oct 2023 21:48:45 +0200 Subject: [PATCH 05/12] mix mesh --- .../tests/med_files/tetrahedral_10N/mesh.med | Bin 35564 -> 35820 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/applications/MedApplication/tests/med_files/tetrahedral_10N/mesh.med b/applications/MedApplication/tests/med_files/tetrahedral_10N/mesh.med index 1faa1fa700964732648cdab473868eb5d1375be4..020550fe309856945f9cedc86591d9ee5a05d86f 100644 GIT binary patch delta 2359 zcmaJ?e@t6d6n?k7wPhJCXr&j*kG8Y|gN_oJoBU{LKwv;AG@#;G0Bsw{HViR~xEcZ? z!8zt8$7L*GGmDwl!3OhXk!F~w)E`l{gs5A_hQx@|jjFIr|1dN7Uf*j5&s&?ke0ja! zIp25AJ@>xgQAzNa=&FY0qjihyx z`z)N2TOk2;;5YudZzOTp99!TrvL~5i40MQ~dmzAzH6k{Po_R*H4beH@_L~5r`eOzJ zZ^Pi~~A9h;URIl4clKWuPwwCqV3kM7g7^Zz6Y3t{Z;T^(TT8>O_^ zajU|MWs?`ZlRt<07sqz`Xih47v&;0^&z0&Wqo zQotPe5v8jBr_Lt)%W?BlL_(_~6K1dzPnVVUg$N|qy$OCib?=UWm?7LsU!oCDy>}~t zNaAD^8YfPV%czYgGp+IC1@HCS#0+7XJ4r^o>~sD`Bylpe$xf`CUbID&*^uJLZMP?C zh#A5%*{MeS`u6!!B8ih3N_Ap+OK>`(Ou5#N9Wo#9B5#LC^P#00=JDn3x z&faK=D04vX$FJxT=ZG1?)l8%ran-`o86t_RCf?x0`_9>lNis~2fkrt0>I>u%8!?XS zI}`6VkwQ)GS5a&%MfGGru0zH2KH7#byrw7bFv{@KO?St8p(o>U(ZON@88o8jX2-^u znaqY*@oG*!YY-jo9wvE!oO}x$DENXd`+3U1=GMc$LX~>`Rbz5@aW;LGtW6DEEPPt- zp6`-7N-CQ4p&s zLQ0q|=%z0!gIO^6L>UxVyVAtINSRjbn_;zDCRvx|Wc^Fcq3V{3RbsO-HZR>-x=_Xp z+KM;8h}sNeYOV0dVMcAX`2?FE2zW-oQ31yUJS*Ti0mlWLU{>O;A^xTo-5`;>QCiMN zudPFIbMEp-T;sX@_|*j;R_gIT7HJ8o&rGnAoeJO9p**2|DyXS;iHrZF+9H`MAF>DV z-okI*A>{#%GFZ=2=&N=41EDTT9T8^a`g81zWFZ&qa->JM@&)8laH%L>e)CrIV{2wc z246WI5xZG(SWyFH)duLFUi`cx?3=OIS)<+^v>|xgX=bMCWt+rtvn^Kka~anfpdUK2 zL(N*$rIp$29}5OX=M66tE91g;b7AtYEnk+bHJ4q}V2^&D_rIUf46({{s0Y2-*Mu delta 2218 zcmb7_eN0nV7{>1@mwp)NkaX>l7Ab`S9aPFN!+}sb89Hbw6woqc8PE&J2vPTic7ehK zrvoy1OK_2m82({f6yYWt-3RJcrdhzGi-}=bmMocxL6*3=I5YoX_x2;|^>oRaG$-wO z-skt6_q`wM6QcET(Fe(yC#m4a6k4bi=I1Z$d&(Rl?bw)+dH97nvG$a!QLS`c&nN90 znR9SfYKASS8*5rLH%J=JV;ig>n?^ml_exNZ`VbI;H6YGK$2vs?hwOE=eQ4c~{>=6x@)^;`t-1 zcZi#F;uOfm1@ML_xFM z0L$2c529LaRBrzkA1>UHze;q7G-D=7kAI+KwL}q*k*gi}_1)zSoHk z5zLxKk3aLu;)o(1Q=RO<7jHUuM8(8z^^M_gpWq%ZB;{;cjjr7tnk4#~M-w$So{^6Gh+C zfsDOxao#$3bEiV}_`|};^zbofD!7O%x=ki;)-tMZGlr$Au9Xe!d)v%spwsT+y5+ zpLFVrQ4TBx4|uy&AmDMFod&yb?8)hkpZHsvF*;D69PQZ!K zGHh6v=q~4xso=rI_9&BGZRRGMjas3}o+*1ZG=w|~E*2}Lfu_LJBa@cERr}MzJh$y; zR0rABetLf7m^YG~wbhto!0RxvU)M|Ggf)R?Gxvtt+~TKKPuGlc@lw;uEw*pM@VF2E zOe3C(FYDyXr1qJS!AFDTRMp#LEurk$ZBzS#<$@P<_(D$a;Euahgk9WarqS|a+0KLt z7eWgqmQxg>Vz@->4BrMiaq#F`Fl1exslGL&x>B>*PYjvEm{AvWF@CzrpjwRd14i3~ zlN@U|BM+3e`|;hO<`k0GSbK@+w*g*4pZB7B{21l+Hfeh(!N9M|`)u8T)4G2F%|iCU From 03a7d4e3e37d4ec8dccc34895694981831f72dd9 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 21:53:32 +0200 Subject: [PATCH 06/12] WIP more tests --- .../tests/med_files/hexahedral_20N/mesh.med | Bin 0 -> 86108 bytes .../tests/med_files/hexahedral_27N/mesh.med | Bin 0 -> 117788 bytes .../med_files/hexahedral_8N/create_mesh.py | 68 ------------------ .../tests/med_files/hexahedral_8N/mesh.med | Bin 25631 -> 45660 bytes .../tests/test_med_model_part_io.py | 40 ++++++++++- 5 files changed, 39 insertions(+), 69 deletions(-) create mode 100644 applications/MedApplication/tests/med_files/hexahedral_20N/mesh.med create mode 100644 applications/MedApplication/tests/med_files/hexahedral_27N/mesh.med delete mode 100644 applications/MedApplication/tests/med_files/hexahedral_8N/create_mesh.py diff --git a/applications/MedApplication/tests/med_files/hexahedral_20N/mesh.med b/applications/MedApplication/tests/med_files/hexahedral_20N/mesh.med new file mode 100644 index 0000000000000000000000000000000000000000..aebd038ea4552925c871513cb1406f6bf49f7130 GIT binary patch literal 86108 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 literal 25631 zcmeI)2YggjzQFN234|5|LhqsX9*QC`NoGO<$xO&35D-X!geo;u5fP;-%|cNuC>E4r zK|yS|7Elx{SXg~eclG&J-|Aa@y8HC4F7NlBdk@K+nc)VQ$g<{sK40$4x%Zxa&pCHy z$eL7FO7*IZszz0=Y^d$DwKXp=L%LfBjwXD6%$w@Uii-cTSEs^~7DmO%IqE{SuNq}I z3?rtI!LCM{C&lZ_8|?PDvl7$YzE`YBW4O{`RC0TKc^Qd`OF3V*n9C$IIwjG!B*qLe z{3%$k&+Nv0-sp|cS-S6RS*janR0z&)YzxDP=0L0*%t#z!)TB;$$rf)!@vpoNJSoi+ zbdsDNa8i~#J>*H-hBSIHbl%TiowcNDVloPgCg=5tlWfVBZ0;`b-eHKNV$yYS%%!uhFIc?vid(hS+RM;s*ZT(f@)`8o&5#TsF-LB+1j(eX_UI^lh5bYPs&bpkt0&3Zy5#c zmsnR+GgK-E_BH$@#m8BO%Aa+kT5+n_B(Y3mA!$g{%Qn+Wsj>f^VW|C-qsJR3Wv8c* z?qB2(gT(36hH>|>Q5B6=a%l@QAltn+*4QIwSOG~z)0-K6O9b?tbSTTXO#-YqoS)5_ zXDliaP}Kd7G=LFLTkRD3_Yhzbkt-3 zTwK*Gu3BZ7IhG@9S_K{nm{mQw*+Kc0LTe|b*`Jg-yc98I4lhMa9#@!{x|j=#Ix-Yz za#F4MLH-%QFq}q0H6!6P?P!hr6#3Mlz(RPl>o zY=I46t-zAK-d$D$h3-TWL#23s1jZ_JSG;=5SZ^I+O%<>msrJi8Z*uC;(2EKyZI9Re zRTcBH#&hD9hwem%!%>IIb2uEUtr}GO=sJcYR7F>;Y&fE#qWrZ}nN?-9h0E8k74EX?C)?VO zwe|(pzO0WM7kT@&>Nz+abGk~_>e=N~;pX0F9ars>Z5>zPs=b2u=JgY->s5OeSl3TD zvo{+c__!G!9Ipzu%bz(EyPVc>OepUZ^{h05|uKok#H%nLiuRcx`A2DCq9oNsd ztA9N{{k`4wdV2bMyX*Dz^!Ikx>*<~Adp*6`@T3`^E~~1aJkL%RCu^_3!LVoUva-v`6%o953Cn;Kbff;#<{*% z`B(L#ms`abZf|$J%2&9(-Sy$pRpEBmhfBA#;VPYQd%JkTT{p#AXD2(&7*siaJL8uc zzs<&EXL%CS zOZR!F_MxaR=;Le$DP;Y$YrWk^yy}}_wU3T993{V`5B_Mkl6(`%mT!GiQsy7+W|`?l z_TQBoM-PmA-Aw9a=JL|68}FwJ4%&Z}kdyIf3$wHXniT#0EZ>Ig>uH`A^4k!fyXQgc zODXx@W0n7F=;Ciqw0<7u8<`qGePj2xAMceSgzlWyw;>scX@9f6scANNSNpRRp?kZt z6v5+lrMEVZhfYokHo1*?#%?RCRu=e*vrbzpNc%#k&9bk0+x5_e)}?B1fA=2gYF_dO z86em~=QyC+Jt4lBxspo*P73?QOqtxhchtV?*2oO7gWcYsv2$W+3#ZjU=u!C3*-7u( zwWCz0Y-(@cjt^UR(<$@9OSB!M^W&zMW~AA|L@L{Z{i_y)zD?K2O?H}}N6EI%+!@xd z<;-8cahrZ&jYM+pt9{Iqta>!gYpyQ7i`OPtX&RF{|9+QxUA`}`f$|zClNyluOP0~H z3YBM(iim;yPDp+VC_i(MpIKCc%&gVHKw!vPf!p8zySzB|vLu%uDbz(h@Y5sz61^dN ze#++mbzKwoP05Npb#=~PQqkN!BkAc)tHVMn2A}KjX5a7 zT+G9KEPyO$7U3E!##!8pV;OG1jaZHqScz3wjWxIlH)Acvp$e*^8e-uS*1SpvdXo3StX6%+7|gG_?FAfIy_}n<)!&3)v(Ru zGi;aO!*UYx<;G)6xb|eBU0vqN&B>15OI}P_3O5`nj{>+HL*p8cOO*Hnq2Js6Qo}SE#1FG#jd0 z%)XJ4ubV+B{|a@Jm*Cqjoj7#MT2H+Ewtc6}Dr_(3IZpWN@*MvU8;c13KN?Tv2V@Fn z3!R`mtDlewnoZU}vK2pe_sum!{L2*UC2P3Nxv$t3A=TaQ2U!5HJ@mvR zfhAkON#P2oofLY=EAE`Wk!BrCP1+#~b~afX%CscSDC;v>E6Ey4)1#fHy{E5h^>v=U#?#k#`r1xk*Xe6IS&Yae+8-zy1h(T~d*87P_ zf{gbr$ok(68RG^+I=9rJUQSupr(p<&A|0~c&wvMBWI~<;hCwD`AF?5Jn1kUM0lB%Q z9D3VGU5&&jT!qn)=YTO7i#+5*o(sldJSLz3@|;kJiI{}RkoMQxN1hX=U@E5JYRL1$ zbj-j^%z`{u%*GrPVJ@Vt=3zb-U?HR&l5feUSc>aWAIoq9 zZp3mlzzVFyDy&8{dP9aa8C3g$;WOx2SO%nZSdR_Z2!`XJXX5IFZNg@3!B$9HM6wS# zh)>dy^d(=C-$?f%xzF36E!v?yBHf214e7tqucg0B86w?>DiCKa#Gy9oAkuwE(vbcu z{aX6Flp)f6NZPy$x}qDpL+?{kPJLXGawj4Q$#6mH!HpECaY^b$?^AMbq@m=v)SCAh z@W6{qw8AiC!G~=dY_VUWF$(COHxjKT#|B+!+1Q?Gf>Q3rv5lW6rQdWIj zlKW{HN{&l%f33hutb&Y7a=-OJPxL|pq^{QBCftm*h{rmt#|CUfbKHVkaT{(&Gi*Z1 zaj7ZqrLLuJr7orJq^|0s9_ph3q<=@cuSwdHC&_C(Dk0K+tqO5gMK#32fk^kY7Q`ui zUG4$7H>4bq?rR;0vm?|T7{lvG_ciI$(%0o4kb6VQu?CUsYeZMRmDfPTYhVB|4#Xfh zk%%ND!v!}|Fc_&w!w?KbIx^sa7nvA_EclR(91O<@7XJXMH^ zn1spD#|M2Ln$0Lv1FSg@8+>af201x6JJdB-q1dn1Dc4H6r;xRmqC-5Zp;VC?g{WySU za1hVpIXsUS@FEW3CHxLA;}yJ$*Kim|@H*bWQM`$_a16)sHr~Ozcn=PALCN{CI`8%R zxQsBp&T0_04(qW28&MN_-OIc*8u=)I^ba@mI!+->uV?AcdR?ayrq_2h!mfh!&k2xz zmq+9E{EQpR}gj#$D!J^Kd)80p5XQSxDp@WLwtmjh;;i#6K8MqL0|Mkq}#U+aV~_6 z6|-Sc>aWAIoq9Zp3mlzzVFyDy&8Y^gvJaLITRiU30zk&ob^t(Iy?x z5uMN(k?sdwh_frYp*t#K6EVLdiL=JMuPgPU+O)*>GIT;7DR zJ8&nq;Vz`%Zrp==u^mHjAMVEvJb_j^Bxx6u9kKj@4!fs?>5BB0QJPr?@ zz?0aAr{KlY*pCBv2AR<3@7G9myiX$Px%OY4To_AuOk~HF$UvM zh=zCrNAV`!LJp4MINruP7>;-G9!}tWjKBx@5Fgts36XB!g~T}* zvv4(9Bhu}=fH;dV6VuQNk#67l#5o5uFcmEk>GqvRoU<_QtSm zy?xzu8vn0QH@iMv@z)fe&uyqbZR_A~$rk#XyU`bYR-~l5k_`1Hg#G0$IzDC9nZL*E z_GJeB*QaPsJ9C07E%*;u2Aq&RGB^fFM`G~*pI4XL=l@bkvJ@3?B*&8-e8m4}qJ3Gx zKiN~4`cKGm+obC8W(3FW&rgmgE%=B((r|zL@=RrTazp>QO37OJR$c?;HBepyUm#(*8e?`e2h=#gKzQQ_zOkN64yhri=z{DObrG~|mU2ci&-3aE$}R6=FQ-+`}+YKTR3T!tE` ziCTz5ZPYCfiG(&U5qXk-`6{x}qDpqX&AT w7vvYHz0n7K(GQp73iQX77=VEo1Sb-agk-qjMhXTa6=@iPp-4vtJn-WG0VUrz!T Date: Mon, 16 Oct 2023 22:12:42 +0200 Subject: [PATCH 07/12] more logging --- applications/MedApplication/med_application.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/applications/MedApplication/med_application.cpp b/applications/MedApplication/med_application.cpp index fcf5abdaa673..b9c3cb474eff 100644 --- a/applications/MedApplication/med_application.cpp +++ b/applications/MedApplication/med_application.cpp @@ -24,14 +24,24 @@ namespace Kratos { KratosMedApplication::KratosMedApplication(): KratosApplication("MedApplication") { - // check if the library that was used to compile is the same as the one that is loaded at runtime - // they must match, otherwise random errors can occur + // logging information about the used library for debugging purposes med_int v_med_major, v_med_minor, v_med_release; MEDlibraryNumVersion(&v_med_major, &v_med_minor, &v_med_release); + med_int v_hdf_major, v_hdf_minor, v_hdf_release; + MEDlibraryHdfNumVersion(&v_hdf_major, &v_hdf_minor, &v_hdf_release); + + // Note: the detail severity must be explicitly enabled, it is not shown by default + KRATOS_DETAIL("MedApplication") << "Version of MED-library used during compilation: " << MED_MAJOR_NUM << "." << MED_NUM_MINEUR << "." << MED_NUM_RELEASE << std::endl; + KRATOS_DETAIL("MedApplication") << "Version of MED-library loaded at runtime: " << v_med_major << "." << v_med_minor << "." << v_med_release << std::endl; + KRATOS_DETAIL("MedApplication") << "Version of HDF-library used during compilation: " << H5_VERS_MAJOR << "." << H5_VERS_MINOR << "." << H5_VERS_RELEASE << std::endl; + KRATOS_DETAIL("MedApplication") << "Version of HDF-library loaded at runtime: " << v_hdf_major << "." << v_hdf_minor << "." << v_hdf_release << std::endl; + + // check if the library that was used to compile is the same as the one that is loaded at runtime + // they must match, otherwise random errors can occur KRATOS_ERROR_IF(v_med_major != MED_MAJOR_NUM || v_med_minor != MED_NUM_MINEUR || - v_med_release != MED_NUM_RELEASE) << "The MED library that was used during compilation (v" << v_med_major << "." << v_med_minor << "." << v_med_release << ") is different from the one loaded at runtime (v" << MED_MAJOR_NUM << "." << MED_NUM_MINEUR << "." << MED_NUM_RELEASE << ")!\nThis causes problems with reading/writing MED files, please check your paths for loading the library (e.g. \"PATH\" or \"LD_LIBRARY_PATH\")" << std::endl; + v_med_release != MED_NUM_RELEASE) << "The MED library that was used during compilation (v" << MED_MAJOR_NUM << "." << MED_NUM_MINEUR << "." << MED_NUM_RELEASE << ") is different from the one loaded at runtime (v" << v_med_major << "." << v_med_minor << "." << v_med_release << ")!\nThis causes problems with reading/writing MED files, please check your paths for loading the library (e.g. \"PATH\" or \"LD_LIBRARY_PATH\")" << std::endl; } void KratosMedApplication::Register() From 12ac61c377c9a62acfafb9e00fdcd209c7fc89e7 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 22:23:03 +0200 Subject: [PATCH 08/12] improve tests --- .../tests/test_med_model_part_io.py | 103 +++++++++--------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/applications/MedApplication/tests/test_med_model_part_io.py b/applications/MedApplication/tests/test_med_model_part_io.py index 9a08029a841e..4445ed7ffd4c 100644 --- a/applications/MedApplication/tests/test_med_model_part_io.py +++ b/applications/MedApplication/tests/test_med_model_part_io.py @@ -24,6 +24,10 @@ def _execute_tests(self, med_path, check_fct, print_vtk=False): med_io_read_1 = KratosMed.MedModelPartIO(GetMedPath(med_path)) med_io_read_1.ReadModelPart(self.mp_read_1) + # check no elements or conditions are created + self.assertEqual(self.mp_read_1.NumberOfElements(), 0) + self.assertEqual(self.mp_read_1.NumberOfConditions(), 0) + if print_vtk: write_vtk(self.mp_read_1, med_path) @@ -116,51 +120,47 @@ def test_tetrahedra_4N_linear_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + for node in model_part.Nodes: + self.assertTrue(0.0 <= node.X <= 500.0) + self.assertTrue(0.0 <= node.X0 <= 500.0) - for coords, node in zip(exp_coords, model_part.Nodes): - self.assertAlmostEqual(node.X, coords[0]) - self.assertAlmostEqual(node.X0, coords[0]) - self.assertAlmostEqual(node.Y, coords[1]) - self.assertAlmostEqual(node.Y0, coords[1]) - self.assertAlmostEqual(node.Z, coords[2]) - self.assertAlmostEqual(node.Z0, coords[2]) + self.assertTrue(0.0 <= node.Y <= 100.0) + self.assertTrue(0.0 <= node.Y0 <= 100.0) + + self.assertTrue(0.0 <= node.Z <= 200.0) + self.assertTrue(0.0 <= node.Z0 <= 200.0) + + self._execute_tests("tetrahedral_4N", mp_check_fct, True) def test_tetrahedra_10N_quadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 168) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + for node in model_part.Nodes: + self.assertTrue(0.0 <= node.X <= 500.0) + self.assertTrue(0.0 <= node.X0 <= 500.0) - for coords, node in zip(exp_coords, model_part.Nodes): - self.assertAlmostEqual(node.X, coords[0]) - self.assertAlmostEqual(node.X0, coords[0]) - self.assertAlmostEqual(node.Y, coords[1]) - self.assertAlmostEqual(node.Y0, coords[1]) - self.assertAlmostEqual(node.Z, coords[2]) - self.assertAlmostEqual(node.Z0, coords[2]) + self.assertTrue(0.0 <= node.Y <= 100.0) + self.assertTrue(0.0 <= node.Y0 <= 100.0) + + self.assertTrue(0.0 <= node.Z <= 200.0) + self.assertTrue(0.0 <= node.Z0 <= 200.0) self._execute_tests("tetrahedral_10N", mp_check_fct, True) def test_hexahedra_8N_linear_mesh(self): def mp_check_fct(model_part): - self.assertEqual(model_part.NumberOfNodes(), 36) + self.assertEqual(model_part.NumberOfNodes(), 216) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + for node in model_part.Nodes: + self.assertTrue(0.0 <= node.X <= 500.0) + self.assertTrue(0.0 <= node.X0 <= 500.0) - for coords, node in zip(exp_coords, model_part.Nodes): - self.assertAlmostEqual(node.X, coords[0]) - self.assertAlmostEqual(node.X0, coords[0]) - self.assertAlmostEqual(node.Y, coords[1]) - self.assertAlmostEqual(node.Y0, coords[1]) - self.assertAlmostEqual(node.Z, coords[2]) - self.assertAlmostEqual(node.Z0, coords[2]) + self.assertTrue(0.0 <= node.Y <= 100.0) + self.assertTrue(0.0 <= node.Y0 <= 100.0) + + self.assertTrue(0.0 <= node.Z <= 200.0) + self.assertTrue(0.0 <= node.Z0 <= 200.0) self._execute_tests("hexahedral_8N", mp_check_fct, True) @@ -168,17 +168,15 @@ def test_hexahedra_20N_quadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + for node in model_part.Nodes: + self.assertTrue(0.0 <= node.X <= 500.0) + self.assertTrue(0.0 <= node.X0 <= 500.0) - for coords, node in zip(exp_coords, model_part.Nodes): - self.assertAlmostEqual(node.X, coords[0]) - self.assertAlmostEqual(node.X0, coords[0]) - self.assertAlmostEqual(node.Y, coords[1]) - self.assertAlmostEqual(node.Y0, coords[1]) - self.assertAlmostEqual(node.Z, coords[2]) - self.assertAlmostEqual(node.Z0, coords[2]) + self.assertTrue(0.0 <= node.Y <= 100.0) + self.assertTrue(0.0 <= node.Y0 <= 100.0) + + self.assertTrue(0.0 <= node.Z <= 200.0) + self.assertTrue(0.0 <= node.Z0 <= 200.0) self._execute_tests("hexahedral_20N", mp_check_fct, True) @@ -186,20 +184,19 @@ def test_hexahedra_27N_biquadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + for node in model_part.Nodes: + self.assertTrue(0.0 <= node.X <= 500.0) + self.assertTrue(0.0 <= node.X0 <= 500.0) - for coords, node in zip(exp_coords, model_part.Nodes): - self.assertAlmostEqual(node.X, coords[0]) - self.assertAlmostEqual(node.X0, coords[0]) - self.assertAlmostEqual(node.Y, coords[1]) - self.assertAlmostEqual(node.Y0, coords[1]) - self.assertAlmostEqual(node.Z, coords[2]) - self.assertAlmostEqual(node.Z0, coords[2]) + self.assertTrue(0.0 <= node.Y <= 100.0) + self.assertTrue(0.0 <= node.Y0 <= 100.0) + + self.assertTrue(0.0 <= node.Z <= 200.0) + self.assertTrue(0.0 <= node.Z0 <= 200.0) self._execute_tests("hexahedral_27N", mp_check_fct, True) + def write_vtk(model_part, name): # using the modeler to create elements for visualization, # until the vtk-output supports geometries directly @@ -221,6 +218,10 @@ def write_vtk(model_part, name): vtk_io = KM.VtkOutput(model_part, vtk_parameters) vtk_io.PrintOutput(name) + # remove elements again to avoid intereference with other checks + KM.VariableUtils().SetFlag(KM.TO_ERASE, True, model_part.Elements) + model_part.RemoveElementsFromAllLevels(KM.TO_ERASE) + if __name__ == '__main__': KratosUnittest.main() From 1c441ec9b00aba577c08991dc93514f0ec2203e1 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 22:31:43 +0200 Subject: [PATCH 09/12] add testing utilities --- .../MedApplication/tests/testing_utilities.py | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 applications/MedApplication/tests/testing_utilities.py diff --git a/applications/MedApplication/tests/testing_utilities.py b/applications/MedApplication/tests/testing_utilities.py new file mode 100644 index 000000000000..1fc3e5237064 --- /dev/null +++ b/applications/MedApplication/tests/testing_utilities.py @@ -0,0 +1,92 @@ +import KratosMultiphysics as KM +import KratosMultiphysics.KratosUnittest as KratosUnittest + +import KratosMultiphysics.MedApplication as KratosMed + +from pathlib import Path +from typing import Any, Dict, List, Set + + +def GetMedPath(med_path, med_name="mesh.med"): + return Path(__file__).absolute().parent / "med_files" / med_path / med_name + + +class MedModelPartIOTestCase(KratosUnittest.TestCase): + def _basic_checks(self, model_part): + # check no elements or conditions are created + self.assertEqual(model_part.NumberOfElements(), 0) + self.assertEqual(model_part.NumberOfConditions(), 0) + + self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 0.0) + self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 0.0) + self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 0.0) + self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 0.0) + + # check increasing node Ids + for i, node in enumerate(model_part.Nodes): + self.assertEqual(node.Id, i + 1) + + # check geometries have correct Ids + # Note: Geometries are not ordered, thus cannot check like nodes + self.assertEqual(set(get_geometry_ids(model_part)), set(range(1, model_part.NumberOfGeometries() + 1))) + + # check that the entities are unique in the ModelParts + self._check_unique_nodes(model_part) + self._check_unique_geometries(model_part) + + # check each ModelPart has (at least) the nodes of its geometries + self._check_nodes_geometries(model_part) + + def _check_unique_nodes(self, model_part): + node_ids: List[int] = get_node_ids(model_part) + node_ids_unique: Set[int] = set(node_ids) + self.assertEqual(len(node_ids), len(node_ids_unique), msg=f"Name of ModelPart: {model_part.FullName()}") + + for smp in model_part.SubModelParts: + self._check_unique_nodes(smp) + + def _check_unique_geometries(self, model_part): + geom_ids: List[int] = get_geometry_ids(model_part) + geom_ids_unique: Set[int] = set(geom_ids) + self.assertEqual(len(geom_ids), len(geom_ids_unique), msg=f"Name of ModelPart: {model_part.FullName()}") + + for smp in model_part.SubModelParts: + self._check_unique_geometries(smp) + + def _check_nodes_geometries(self, model_part): + geom_node_ids: List[int] = get_geom_node_ids(model_part) + geom_node_ids_unique: Set[int] = set(geom_node_ids) + + node_ids: List[int] = get_node_ids(model_part) + + # there can be nodes that do not belong to geometries, thus geom_node_ids is subset + self.assertTrue(geom_node_ids_unique.issubset(node_ids), msg=f"Name of ModelPart: {model_part.FullName()}") + + for smp in model_part.SubModelParts: + self._check_nodes_geometries(smp) + + +def get_num_geometries_by_type(model_part: KM.ModelPart) -> Dict[Any, int]: + geoms_by_type: Dict[Any, int] = {} + for geom in model_part.Geometries: + type_geom = type(geom) + if type_geom not in geoms_by_type: + geoms_by_type[type_geom] = 0 + geoms_by_type[type_geom] += 1 + return geoms_by_type + + +def get_node_ids(model_part: KM.ModelPart) -> List[int]: + return [node.Id for node in model_part.Nodes] + + +def get_geometry_ids(model_part: KM.ModelPart) -> List[int]: + return [geom.Id for geom in model_part.Geometries] + + +def get_geom_node_ids(model_part: KM.ModelPart) -> List[int]: + node_ids: List[int] = [] + for geom in model_part.Geometries: + for node in geom: + node_ids.append(node.Id) + return node_ids From c3cc1f3da416abf02a86ff2840d5c59fd0dfa0bc Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 22:43:21 +0200 Subject: [PATCH 10/12] lots more checks --- .../tests/test_med_model_part_io.py | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/applications/MedApplication/tests/test_med_model_part_io.py b/applications/MedApplication/tests/test_med_model_part_io.py index 4445ed7ffd4c..9f5095ba1060 100644 --- a/applications/MedApplication/tests/test_med_model_part_io.py +++ b/applications/MedApplication/tests/test_med_model_part_io.py @@ -4,16 +4,10 @@ import KratosMultiphysics.MedApplication as KratosMed from KratosMultiphysics.kratos_utilities import DeleteFileIfExisting +from testing_utilities import MedModelPartIOTestCase, GetMedPath, get_num_geometries_by_type -from pathlib import Path - - -def GetMedPath(med_path, med_name="mesh.med"): - return Path(__file__).absolute().parent / "med_files" / med_path / med_name - - -class TestMedModelPartIO(KratosUnittest.TestCase): +class TestMedModelPartIO(MedModelPartIOTestCase): def setUp(self): self.model = KM.Model() @@ -24,18 +18,11 @@ def _execute_tests(self, med_path, check_fct, print_vtk=False): med_io_read_1 = KratosMed.MedModelPartIO(GetMedPath(med_path)) med_io_read_1.ReadModelPart(self.mp_read_1) - # check no elements or conditions are created - self.assertEqual(self.mp_read_1.NumberOfElements(), 0) - self.assertEqual(self.mp_read_1.NumberOfConditions(), 0) + self._basic_checks(self.mp_read_1) if print_vtk: write_vtk(self.mp_read_1, med_path) - self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeLength(self.mp_read_1), 0.0) - self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeArea(self.mp_read_1), 0.0) - self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeVolume(self.mp_read_1), 0.0) - self.assertGreaterEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(self.mp_read_1), 0.0) - with self.subTest("check_model_part"): check_fct(self.mp_read_1) @@ -119,6 +106,17 @@ def test_quadrilateral_4N_linear_mesh(self): def test_tetrahedra_4N_linear_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) + self.assertEqual(model_part.NumberOfGeometries(), 167) + + # check how many geoms of each type + exp_geoms = {KM.Tetrahedra3D4: 65, KM.Triangle3D3: 64, KM.Line3D2: 32, KM.Geometry: 6} + self.assertEqual(sum(exp_geoms.values()), model_part.NumberOfGeometries()) + self.assertDictEqual(exp_geoms, get_num_geometries_by_type(model_part)) + + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 3200) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 340000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 10000000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 10343200) for node in model_part.Nodes: self.assertTrue(0.0 <= node.X <= 500.0) @@ -135,6 +133,17 @@ def mp_check_fct(model_part): def test_tetrahedra_10N_quadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 168) + self.assertEqual(model_part.NumberOfGeometries(), 176) + + # check how many geoms of each type + exp_geoms = {KM.Tetrahedra3D10: 65, KM.Triangle3D6: 64, KM.Line3D3: 32, KM.Geometry: 15} + self.assertEqual(sum(exp_geoms.values()), model_part.NumberOfGeometries()) + self.assertDictEqual(exp_geoms, get_num_geometries_by_type(model_part)) + + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 3200) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 340000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 10000000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 10343200) for node in model_part.Nodes: self.assertTrue(0.0 <= node.X <= 500.0) @@ -151,6 +160,17 @@ def mp_check_fct(model_part): def test_hexahedra_8N_linear_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 216) + self.assertEqual(model_part.NumberOfGeometries(), 371) + + # check how many geoms of each type + exp_geoms = {KM.Hexahedra3D8: 125, KM.Quadrilateral3D4: 150, KM.Line3D2: 60, KM.Geometry: 36} + self.assertEqual(sum(exp_geoms.values()), model_part.NumberOfGeometries()) + self.assertDictEqual(exp_geoms, get_num_geometries_by_type(model_part)) + + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 3200) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 340000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 10000000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 10343200) for node in model_part.Nodes: self.assertTrue(0.0 <= node.X <= 500.0) @@ -167,6 +187,17 @@ def mp_check_fct(model_part): def test_hexahedra_20N_quadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) + self.assertEqual(model_part.NumberOfGeometries(), 36) + + # check how many geoms of each type + exp_geoms = {KM.Hexahedra3D20: 125, KM.Quadrilateral3D8: 150, KM.Line3D3: 60, KM.Geometry: 96} + self.assertEqual(sum(exp_geoms.values()), model_part.NumberOfGeometries()) + self.assertDictEqual(exp_geoms, get_num_geometries_by_type(model_part)) + + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 3200) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 340000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 10000000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 10343200) for node in model_part.Nodes: self.assertTrue(0.0 <= node.X <= 500.0) @@ -183,6 +214,17 @@ def mp_check_fct(model_part): def test_hexahedra_27N_biquadratic_mesh(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) + self.assertEqual(model_part.NumberOfGeometries(), 36) + + # check how many geoms of each type + exp_geoms = {KM.Hexahedra3D27: 125, KM.Quadrilateral3D9: 150, KM.Line3D3: 60, KM.Geometry: 121} + self.assertEqual(sum(exp_geoms.values()), model_part.NumberOfGeometries()) + self.assertDictEqual(exp_geoms, get_num_geometries_by_type(model_part)) + + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeLength(model_part), 3200) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeArea(model_part), 340000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeVolume(model_part), 10000000) + self.assertAlmostEqual(KratosMed.MedTestingUtilities.ComputeDomainSize(model_part), 10343200) for node in model_part.Nodes: self.assertTrue(0.0 <= node.X <= 500.0) From e0879556660d333cf2a55fc62fe98ab6c8205a57 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 22:45:32 +0200 Subject: [PATCH 11/12] final cleanup --- .../custom_io/med_model_part_io.cpp | 4 +-- .../tests/test_med_model_part_io.py | 27 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/applications/MedApplication/custom_io/med_model_part_io.cpp b/applications/MedApplication/custom_io/med_model_part_io.cpp index 16ebc67a40b8..fb78fb3bd9fa 100644 --- a/applications/MedApplication/custom_io/med_model_part_io.cpp +++ b/applications/MedApplication/custom_io/med_model_part_io.cpp @@ -146,7 +146,7 @@ std::function&)> GetReorderFunction(const med_geometry_type case MED_HEXA27: KRATOS_ERROR << "MED_HEXA27 is not implemented!" << std::endl; return [](auto& rConnectivities){ - CheckConnectivitiesSize(20, rConnectivities); + CheckConnectivitiesSize(27, rConnectivities); std::swap(rConnectivities[1], rConnectivities[4]); std::swap(rConnectivities[2], rConnectivities[7]); }; @@ -496,7 +496,7 @@ void MedModelPartIO::ReadModelPart(ModelPart& rThisModelPart) KRATOS_ERROR_IF(std::numeric_limits::max() == num_geometries_total) << "number of geometries read (" << num_geometries_total << ") exceeds the capacity of the index type"; rThisModelPart.CreateNewGeometry(kratos_geo_name, - num_geometries_total++, + ++num_geometries_total, geom_node_ids); } diff --git a/applications/MedApplication/tests/test_med_model_part_io.py b/applications/MedApplication/tests/test_med_model_part_io.py index 9f5095ba1060..856c4d3828f5 100644 --- a/applications/MedApplication/tests/test_med_model_part_io.py +++ b/applications/MedApplication/tests/test_med_model_part_io.py @@ -8,7 +8,6 @@ class TestMedModelPartIO(MedModelPartIOTestCase): - def setUp(self): self.model = KM.Model() self.mp_read_1 = self.model.CreateModelPart("read_1") @@ -28,8 +27,8 @@ def _execute_tests(self, med_path, check_fct, print_vtk=False): with self.subTest("read_write_read"): med_temp_path = GetMedPath(med_path, "temp.med") - DeleteFileIfExisting(med_temp_path) # make sure there are no leftovers from previous tests - self.addCleanup(DeleteFileIfExisting, med_temp_path) # clean up after test + DeleteFileIfExisting(med_temp_path) # make sure there are no leftovers from previous tests + self.addCleanup(DeleteFileIfExisting, med_temp_path) # clean up after test med_io_write = KratosMed.MedModelPartIO(med_temp_path, KM.IO.WRITE) med_io_write.WriteModelPart(self.mp_read_1) @@ -49,9 +48,7 @@ def test_only_nodes(self): def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 4) - exp_coords = [ - (0,0,0), (0,0,1),(0,1,1),(1,1,1) - ] + exp_coords = [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)] for coords, node in zip(exp_coords, model_part.Nodes): self.assertAlmostEqual(node.X, coords[0]) @@ -185,6 +182,8 @@ def mp_check_fct(model_part): self._execute_tests("hexahedral_8N", mp_check_fct, True) def test_hexahedra_20N_quadratic_mesh(self): + self.skipTest("The connectivity conversion is not yet fully implemented") + def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) self.assertEqual(model_part.NumberOfGeometries(), 36) @@ -212,6 +211,8 @@ def mp_check_fct(model_part): self._execute_tests("hexahedral_20N", mp_check_fct, True) def test_hexahedra_27N_biquadratic_mesh(self): + self.skipTest("The connectivity conversion is not yet fully implemented") + def mp_check_fct(model_part): self.assertEqual(model_part.NumberOfNodes(), 36) self.assertEqual(model_part.NumberOfGeometries(), 36) @@ -242,20 +243,24 @@ def mp_check_fct(model_part): def write_vtk(model_part, name): # using the modeler to create elements for visualization, # until the vtk-output supports geometries directly - modeler_parameters = KM.Parameters("""{ + modeler_parameters = KM.Parameters( + """{ "elements_list" : [{ "model_part_name" : "read_1", "element_name" : "Element2D3N;Element2D4N;Element3D4N;Element3D8N;Element3D10N;Element3D20N;Element3D27N" }] - }""") + }""" + ) modeler = KM.CreateEntitiesFromGeometriesModeler(model_part.GetModel(), modeler_parameters) modeler.SetupModelPart() - vtk_parameters = KM.Parameters("""{ + vtk_parameters = KM.Parameters( + """{ "file_format" : "binary", "output_sub_model_parts" : false, "save_output_files_in_folder" : true - }""") + }""" + ) vtk_io = KM.VtkOutput(model_part, vtk_parameters) vtk_io.PrintOutput(name) @@ -265,5 +270,5 @@ def write_vtk(model_part, name): model_part.RemoveElementsFromAllLevels(KM.TO_ERASE) -if __name__ == '__main__': +if __name__ == "__main__": KratosUnittest.main() From 409fa1e6632d702807ae92c55c2f07fb971b7694 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 16 Oct 2023 22:48:23 +0200 Subject: [PATCH 12/12] disable vtk debug print --- .../MedApplication/tests/test_med_model_part_io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/applications/MedApplication/tests/test_med_model_part_io.py b/applications/MedApplication/tests/test_med_model_part_io.py index 856c4d3828f5..852963c17b4c 100644 --- a/applications/MedApplication/tests/test_med_model_part_io.py +++ b/applications/MedApplication/tests/test_med_model_part_io.py @@ -125,7 +125,7 @@ def mp_check_fct(model_part): self.assertTrue(0.0 <= node.Z <= 200.0) self.assertTrue(0.0 <= node.Z0 <= 200.0) - self._execute_tests("tetrahedral_4N", mp_check_fct, True) + self._execute_tests("tetrahedral_4N", mp_check_fct) def test_tetrahedra_10N_quadratic_mesh(self): def mp_check_fct(model_part): @@ -152,7 +152,7 @@ def mp_check_fct(model_part): self.assertTrue(0.0 <= node.Z <= 200.0) self.assertTrue(0.0 <= node.Z0 <= 200.0) - self._execute_tests("tetrahedral_10N", mp_check_fct, True) + self._execute_tests("tetrahedral_10N", mp_check_fct) def test_hexahedra_8N_linear_mesh(self): def mp_check_fct(model_part): @@ -179,7 +179,7 @@ def mp_check_fct(model_part): self.assertTrue(0.0 <= node.Z <= 200.0) self.assertTrue(0.0 <= node.Z0 <= 200.0) - self._execute_tests("hexahedral_8N", mp_check_fct, True) + self._execute_tests("hexahedral_8N", mp_check_fct) def test_hexahedra_20N_quadratic_mesh(self): self.skipTest("The connectivity conversion is not yet fully implemented") @@ -208,7 +208,7 @@ def mp_check_fct(model_part): self.assertTrue(0.0 <= node.Z <= 200.0) self.assertTrue(0.0 <= node.Z0 <= 200.0) - self._execute_tests("hexahedral_20N", mp_check_fct, True) + self._execute_tests("hexahedral_20N", mp_check_fct) def test_hexahedra_27N_biquadratic_mesh(self): self.skipTest("The connectivity conversion is not yet fully implemented") @@ -237,7 +237,7 @@ def mp_check_fct(model_part): self.assertTrue(0.0 <= node.Z <= 200.0) self.assertTrue(0.0 <= node.Z0 <= 200.0) - self._execute_tests("hexahedral_27N", mp_check_fct, True) + self._execute_tests("hexahedral_27N", mp_check_fct) def write_vtk(model_part, name):