From 9e54d074181318ca98f0e6f098710bce5f8aca35 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:15:22 +0200 Subject: [PATCH 01/24] make a mesh, material and project parameters file for the oedometer test (unit convention = kN) --- .../test_oedometer/MaterialParameters.json | 29 ++++ .../test_oedometer/ProjectParameters.json | 148 ++++++++++++++++++ .../test_element_lab/test_oedometer/mesh.mdpa | 82 ++++++++++ 3 files changed, 259 insertions(+) create mode 100644 applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json create mode 100644 applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json create mode 100644 applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json new file mode 100644 index 000000000000..2049a3a1cf81 --- /dev/null +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json @@ -0,0 +1,29 @@ +{ + "properties": [{ + "model_part_name": "PorousDomain.Soil", + "properties_id": 1, + "Material": { + "constitutive_law": { + "name": "GeoLinearElasticPlaneStrain2DLaw" + }, + "Variables": { + "IGNORE_UNDRAINED": true, + "DENSITY_SOLID": 2.65, + "DENSITY_WATER": 1.0, + "POROSITY": 0.3, + "BULK_MODULUS_SOLID": 1.0e+09, + "BULK_MODULUS_FLUID": 2.0e-30, + "PERMEABILITY_XX": 4.5e-30, + "PERMEABILITY_YY": 4.5e-30, + "PERMEABILITY_XY": 0.0, + "DYNAMIC_VISCOSITY": 8.9e-07, + "THICKNESS": 1.0, + "BIOT_COEFFICIENT": 1.0, + "RETENTION_LAW": "SaturatedLaw", + "SATURATED_SATURATION": 0.0, + "YOUNG_MODULUS": 1.0e+04, + "POISSON_RATIO": 0.0 + } + } + }] +} \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json new file mode 100644 index 000000000000..f684e7bc6803 --- /dev/null +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json @@ -0,0 +1,148 @@ +{ + "problem_data": { + "problem_name": "oedometer", + "parallel_type": "OpenMP", + "echo_level": 1, + "start_time": 0.0, + "end_time": 1.0 + }, + "solver_settings": { + "time_stepping": { + "time_step": 1.0e-2, + "max_delta_time_factor": 1.0 + }, + "solver_type": "U_Pw", + "solution_type": "Quasi-Static", + "strategy_type": "line_search", + "scheme_type": "Backward_Euler", + "model_part_name": "PorousDomain", + "domain_size": 2, + "echo_level": 1, + "model_import_settings": { + "input_type": "mdpa", + "input_filename": "mesh" + }, + "material_import_settings": { + "materials_filename": "MaterialParameters.json" + }, + "buffer_size": 2, + "clear_storage": false, + "compute_reactions": true, + "move_mesh_flag": false, + "reform_dofs_at_each_step": false, + "block_builder": true, + "reset_displacements": true, + "convergence_criterion": "residual_criterion", + "residual_relative_tolerance": 1.0e-03, + "residual_absolute_tolerance": 1.0e-09, + "min_iterations": 6, + "max_iterations": 50, + "number_cycles": 1, + "reduction_factor": 0.5, + "increase_factor": 2.0, + "desired_iterations": 4, + "calculate_reactions": true, + "max_line_search_iterations": 5, + "first_alpha_value": 0.5, + "second_alpha_value": 1.0, + "min_alpha": 0.1, + "max_alpha": 2.0, + "line_search_tolerance": 0.5, + "rotation_dofs": false, + "problem_domain_sub_model_part_list": ["Soil"], + "body_domain_sub_model_part_list": ["Soil"], + "processes_sub_model_part_list": ["Soil", "Top_load", "Fixed_base", "Sides_L_R"], + "linear_solver_settings": { + "solver_type": "LinearSolversApplication.sparse_lu", + "scaling": true + } + }, + "processes": { + "constraints_process_list": [ + { + "python_module": "apply_vector_constraint_table_process", + "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", + "process_name": "ApplyVectorConstraintTableProcess", + "Parameters": { + "model_part_name": "PorousDomain.Fixed_base", + "variable_name": "DISPLACEMENT", + "active": [true, true, false], + "is_fixed": [true, true, false], + "value": [0.0, 0.0, 0.0], + "table": [0, 0, 0] + } + }, + { + "python_module": "apply_vector_constraint_table_process", + "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", + "process_name": "ApplyVectorConstraintTableProcess", + "Parameters": { + "model_part_name": "PorousDomain.Sides_L_R", + "variable_name": "DISPLACEMENT", + "active": [true, false, false], + "is_fixed": [true, false, false], + "value": [0.0, 0.0, 0.0], + "table": [0, 0, 0] + } + }, + { + "python_module": "apply_scalar_constraint_table_process", + "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", + "process_name": "ApplyScalarConstraintTableProcess", + "Parameters": { + "model_part_name": "PorousDomain.Fixed_base", + "variable_name": "WATER_PRESSURE", + "is_fixed": true, + "fluid_pressure_type": "Uniform", + "value": 0.0, + "table": 0 + } + } + ], + "loads_process_list": [ + { + "python_module": "apply_vector_constraint_table_process", + "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", + "process_name": "ApplyVectorConstraintTableProcess", + "Parameters": { + "model_part_name": "PorousDomain.Top_load", + "variable_name": "LINE_LOAD", + "active": [false, true, false], + "value": [0.0, 0.0, 0.0], + "table": [0, 1, 0] + } + } + ] + }, + "output_processes": { + "gid_output": [ + { + "python_module": "gid_output_process", + "kratos_module": "KratosMultiphysics", + "process_name": "GiDOutputProcess", + "Parameters": { + "model_part_name": "PorousDomain.porous_computational_model_part", + "output_name": "test_oedometer_output", + "postprocess_parameters": { + "result_file_configuration": { + "gidpost_flags": { + "WriteDeformedMeshFlag": "WriteDeformed", + "WriteConditionsFlag": "WriteElementsOnly", + "GiDPostMode": "GiD_PostAscii", + "MultiFileFlag": "SingleFile" + }, + "file_label": "step", + "output_control_type": "step", + "output_interval": 1, + "body_output": true, + "node_output": true, + "skin_output": false, + "nodal_results": ["DISPLACEMENT", "WATER_PRESSURE"], + "gauss_point_results": ["CAUCHY_STRESS_TENSOR", "ENGINEERING_STRAIN_TENSOR"] + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa new file mode 100644 index 000000000000..5187882c367e --- /dev/null +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa @@ -0,0 +1,82 @@ +Begin Table 1 TIME LINE_NORMAL_LOAD_Y + 0.0 0.0 + 1.0 -1000 +End Table + +Begin Properties 0 +End Properties + +Begin Properties 1 +End Properties + +Begin Nodes + 1 0.0000000000 0.0000000000 0.0000000000 + 2 0.5000000000 0.0000000000 0.0000000000 + 3 1.0000000000 0.0000000000 0.0000000000 + 4 0.0000000000 0.5000000000 0.0000000000 + 5 0.5000000000 0.5000000000 0.0000000000 + 6 1.0000000000 0.5000000000 0.0000000000 + 7 0.0000000000 1.0000000000 0.0000000000 + 8 0.5000000000 1.0000000000 0.0000000000 + 9 1.0000000000 1.0000000000 0.0000000000 +End Nodes + +Begin Elements SmallStrainUPwDiffOrderElement2D6N + 1 1 7 1 3 4 2 5 + 2 1 3 9 7 6 8 5 +End Elements + +Begin Conditions LineLoadDiffOrderCondition2D3N + 1 0 9 7 8 +End Conditions + +Begin SubModelPart Soil + Begin SubModelPartNodes + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + End SubModelPartNodes + Begin SubModelPartElements + 1 + 2 + End SubModelPartElements +End SubModelPart + +Begin SubModelPart Top_load + Begin SubModelPartTables + 1 + End SubModelPartTables + Begin SubModelPartNodes + 7 + 8 + 9 + End SubModelPartNodes + Begin SubModelPartConditions + 1 + End SubModelPartConditions +End SubModelPart + +Begin SubModelPart Fixed_base + Begin SubModelPartNodes + 1 + 2 + 3 + End SubModelPartNodes +End SubModelPart + +Begin SubModelPart Sides_L_R + Begin SubModelPartNodes + 3 + 6 + 9 + 1 + 4 + 7 + End SubModelPartNodes +End SubModelPart \ No newline at end of file From d5e715d43d655f2dff3a7dba581182a65bbb895e Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:17:46 +0200 Subject: [PATCH 02/24] insert assertion function and apply it in the triaxial test --- .../tests/test_element_lab.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index dabe5e08201b..c061ccc2c69f 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -9,6 +9,12 @@ class KratosGeoMechanicsLabElementTests(KratosUnittest.TestCase): """ This class contains some element tests, such as triaxial and oedometer tests """ + def _assert_integration_point_tensor_results(self, integration_point_tensors, expected_integration_point_tensor, places, result_name): + for idx, ip_tensor in enumerate(integration_point_tensors): + self.assertAlmostEqual(expected_integration_point_tensor[0], ip_tensor[0], places, msg = f"{result_name} component xx at integration point {idx}") + self.assertAlmostEqual(expected_integration_point_tensor[1], ip_tensor[1], places, msg = f"{result_name} component yy at integration point {idx}") + self.assertAlmostEqual(expected_integration_point_tensor[2], ip_tensor[2], places, msg = f"{result_name} component zz at integration point {idx}") + def test_triaxial(self): """ Regression test for the triaxial experiment. @@ -35,24 +41,18 @@ def test_triaxial(self): expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0]] for element in range(number_of_elements): stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1, result, [element+1], [0])[0] - for stress_vector in stress: - self.assertAlmostEqual(expected_stress[element][0], stress_vector[0], 4) # sigma_xx - self.assertAlmostEqual(expected_stress[element][1], stress_vector[1], 4) # sigma_yy - self.assertAlmostEqual(expected_stress[element][2], stress_vector[2], 4) # sigma_zz + self._assert_integration_point_tensor_results(stress, expected_stress[element], 4,"CAUCHY_STRESS_TENSOR") # Assert the engineering strain for both elements in the first integration point expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0]] for element in range(number_of_elements): strain = reader.element_integration_point_values_at_time("ENGINEERING_STRAIN_TENSOR", 1, result, [element+1], [0])[0] - for strain_component in strain: - self.assertAlmostEqual(expected_strain[element][0], strain_component[0], 4) # eps_xx - self.assertAlmostEqual(expected_strain[element][1], strain_component[1], 4) # eps_yy - self.assertAlmostEqual(expected_strain[element][2], strain_component[2], 4) # eps_zz + self._assert_integration_point_tensor_results(strain, expected_strain[element], 4,"ENGINEERING_STRAIN_TENSOR") def test_triaxial_comp_6n(self): """ Drained compression triaxial test on Mohr-Coulomb model with axisymmetric 2D6N elements - It consistes of two calculation phases: + It consists of two calculation phases: 1) apply confining stress of -100 kPa 2) apply deviatoric stress of -200 kPa """ @@ -90,7 +90,6 @@ def test_triaxial_comp_6n(self): self.assertAlmostEqual(-300.0, stress_vector[1], 2) # sigma_yy self.assertAlmostEqual(-100.0, stress_vector[2], 2) # sigma_zz - def test_oedometer_ULFEM(self): """ Oedometer test on a linear elastic model with 2D6N elements From db00ae70315cdbcbe496012897ceedb50149066f Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:39:09 +0200 Subject: [PATCH 03/24] add oedometer test with assertion function --- .../tests/test_element_lab.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index c061ccc2c69f..d5d883564ef1 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -49,6 +49,35 @@ def test_triaxial(self): strain = reader.element_integration_point_values_at_time("ENGINEERING_STRAIN_TENSOR", 1, result, [element+1], [0])[0] self._assert_integration_point_tensor_results(strain, expected_strain[element], 4,"ENGINEERING_STRAIN_TENSOR") + def test_oedometer(self): + """ + Oedometer test on a linear elastic model. + Application of additional load on the top leads to a vertical displacement and a change in stresses. + """ + test_name = 'test_oedometer' + file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) + simulation = test_helper.run_kratos(file_path) + + # read the output files from the simulation for comparison + reader = GiDOutputFileReader() + result = reader.read_output_from(os.path.join(file_path, 'test_oedometer_output.post.res')) + + number_of_elements = 2 + + # Assert the normal stresses of both elements (all integration points) + expected_stress = [0.0, -1000, 0.0] + stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1, result) + for element in range(number_of_elements): + self._assert_integration_point_tensor_results(stress[element], expected_stress, 6,"CAUCHY_STRESS_TENSOR") + + # Assert the displacement in all top nodes in all directions at 4 different timesteps + top_nodes = [7, 8, 9] + times = [0.25, 0.5, 0.75, 1.0] + for i in range(len(times)): + expected_disp = [0.0, -0.1*times[i], 0.0] + displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", times[i], result, node_ids=top_nodes) + self._assert_integration_point_tensor_results(displacements, expected_disp, 6, "DISPLACEMENT") + def test_triaxial_comp_6n(self): """ Drained compression triaxial test on Mohr-Coulomb model with axisymmetric 2D6N elements From a2db31460bdf14fa1f3c3cfbe8b97947cf1c08cf Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:52:11 +0200 Subject: [PATCH 04/24] apply assert function on displacement assertion triaxial test --- .../GeoMechanicsApplication/tests/test_element_lab.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index d5d883564ef1..5a50ab908ec2 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -33,9 +33,8 @@ def test_triaxial(self): # Assert the displacement in all nodes in all directions expected_disp = [[0.0, -0.2, 0.0], [0.0527776, -0.2, 0.0], [0.0, -0.100033, 0.0], [0.0524025, -0.0996931, 0.0], [0.0, 0.0, 0.0], [0.105197, -0.2, 0.0], [0.105114, -0.100049, 0.0], [0.0524406, 0.0, 0.0], [0.104632, 0.0, 0.0]] for node in range(number_of_nodes): - node_displacement = reader.nodal_values_at_time("DISPLACEMENT", 1, result, [node+1])[0] - for direction in range(3): - self.assertAlmostEqual(node_displacement[direction], expected_disp[node][direction], 4) + node_displacement = reader.nodal_values_at_time("DISPLACEMENT", 1, result, [node+1]) + self._assert_integration_point_tensor_results(node_displacement, expected_disp[node], 4, "DISPLACEMENT") # Assert the normal stress for both elements in the first integration point expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0]] From 94b658419f0db5131b499a72874def45b3d8c0f7 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:55:46 +0200 Subject: [PATCH 05/24] formatting of json files for the oedometer test --- .../test_oedometer/MaterialParameters.json | 56 ++++++++++--------- .../test_oedometer/ProjectParameters.json | 7 ++- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json index 2049a3a1cf81..55f723f88bb7 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json @@ -1,29 +1,31 @@ { - "properties": [{ - "model_part_name": "PorousDomain.Soil", - "properties_id": 1, - "Material": { - "constitutive_law": { - "name": "GeoLinearElasticPlaneStrain2DLaw" - }, - "Variables": { - "IGNORE_UNDRAINED": true, - "DENSITY_SOLID": 2.65, - "DENSITY_WATER": 1.0, - "POROSITY": 0.3, - "BULK_MODULUS_SOLID": 1.0e+09, - "BULK_MODULUS_FLUID": 2.0e-30, - "PERMEABILITY_XX": 4.5e-30, - "PERMEABILITY_YY": 4.5e-30, - "PERMEABILITY_XY": 0.0, - "DYNAMIC_VISCOSITY": 8.9e-07, - "THICKNESS": 1.0, - "BIOT_COEFFICIENT": 1.0, - "RETENTION_LAW": "SaturatedLaw", - "SATURATED_SATURATION": 0.0, - "YOUNG_MODULUS": 1.0e+04, - "POISSON_RATIO": 0.0 - } - } - }] + "properties": [ + { + "model_part_name": "PorousDomain.Soil", + "properties_id": 1, + "Material": { + "constitutive_law": { + "name": "GeoLinearElasticPlaneStrain2DLaw" + }, + "Variables": { + "IGNORE_UNDRAINED": true, + "DENSITY_SOLID": 2.65, + "DENSITY_WATER": 1.0, + "POROSITY": 0.3, + "BULK_MODULUS_SOLID": 1.0e+09, + "BULK_MODULUS_FLUID": 2.0e-30, + "PERMEABILITY_XX": 4.5e-30, + "PERMEABILITY_YY": 4.5e-30, + "PERMEABILITY_XY": 0.0, + "DYNAMIC_VISCOSITY": 8.9e-07, + "THICKNESS": 1.0, + "BIOT_COEFFICIENT": 1.0, + "RETENTION_LAW": "SaturatedLaw", + "SATURATED_SATURATION": 0.0, + "YOUNG_MODULUS": 1.0e+04, + "POISSON_RATIO": 0.0 + } + } + } + ] } \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json index f684e7bc6803..bd78c36a8b48 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json @@ -8,7 +8,7 @@ }, "solver_settings": { "time_stepping": { - "time_step": 1.0e-2, + "time_step": 1.0e-02, "max_delta_time_factor": 1.0 }, "solver_type": "U_Pw", @@ -138,7 +138,10 @@ "node_output": true, "skin_output": false, "nodal_results": ["DISPLACEMENT", "WATER_PRESSURE"], - "gauss_point_results": ["CAUCHY_STRESS_TENSOR", "ENGINEERING_STRAIN_TENSOR"] + "gauss_point_results": [ + "CAUCHY_STRESS_TENSOR", + "ENGINEERING_STRAIN_TENSOR" + ] } } } From ab632280675f23fe91971b4ef487a63178d7d48f Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 14:58:11 +0200 Subject: [PATCH 06/24] remove triaxial material parameters from the json format exception list --- .../GeoMechanicsApplication/exceptions_for_json_formatting.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/applications/GeoMechanicsApplication/exceptions_for_json_formatting.txt b/applications/GeoMechanicsApplication/exceptions_for_json_formatting.txt index a08472c9c1bf..d7687db1eb55 100644 --- a/applications/GeoMechanicsApplication/exceptions_for_json_formatting.txt +++ b/applications/GeoMechanicsApplication/exceptions_for_json_formatting.txt @@ -67,7 +67,6 @@ tests/test_constant_strip_load_2d/MaterialParameters_stage_1.json tests/test_constant_strip_load_2d/ProjectParameters.json tests/test_darcy_law.gid/MaterialParameters.json tests/test_darcy_law.gid/ProjectParameters.json -tests/test_element_lab/test_triaxial/MaterialParameters.json tests/test_inclinded_phreatic_line_smaller_line.gid/MaterialParameters.json tests/test_inclinded_phreatic_line_smaller_line.gid/ProjectParameters.json tests/test_inclinded_phreatic_surface.gid/MaterialParameters.json From b9e2305381df9c6755b92feffd991a5ba8e70bba Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 16:08:22 +0200 Subject: [PATCH 07/24] minor changes to triaxial test readme --- .../tests/test_element_lab/test_triaxial/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/README.md b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/README.md index 33ab6fd415c0..39f8c3fed24c 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/README.md +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/README.md @@ -12,9 +12,9 @@ A schematic overview of the model is displayed in the figure below: The test is performed with the following conditions: - Constraints: - - The displacement in the bottom nodes (5, 8, 9) is fixed in the Y direction. - - The displacement in the symmetry axis (i.e. the left nodes 1, 3, 5) is fixed in the X direction. - - The displacement of the top nodes (1, 2, 6) is prescribed and moves linearly from y = 0 at t = 0 to y = -0.2 at t = 1. + - The bottom nodes (5, 8, 9) are fixed in the Y direction. + - The symmetry axis (i.e. the left nodes 1, 3, 5) is fixed in the X direction. + - A displacement of -0.2 is prescribed for the top nodes (1, 2, 6). The nodes move linearly from y = 1 at t = 0 to y = 0.8 at t = 1. - Material: - The material is described by the Mohr-Coulomb model with the following parameters: - Poisson ratio = 0.25, From 5e2f2313afce376a6cc16d0d9c47866e0e2fff45 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 24 Apr 2026 16:08:56 +0200 Subject: [PATCH 08/24] add readme for the oedometer test incl schematic --- .../test_element_lab/test_oedometer/README.md | 26 + .../test_oedometer/drawing.svg | 902 ++++++++++++++++++ 2 files changed, 928 insertions(+) create mode 100644 applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md create mode 100644 applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md new file mode 100644 index 000000000000..4acb28abe173 --- /dev/null +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md @@ -0,0 +1,26 @@ +# Oedometer test + +This test is an oedometer test with a prescribed top load on a linear elastic model. It mimics a lab test, where soil properties such as the consolidation are determined. +In the lab this is performed on a cylindric volume of soil, where an increasing pressure is applied on the top of the cylinder. In the model test, the soil sample is emulated by two 2 differential order elements. + +A schematic overview of the model is displayed in the figure below. Here the nodes are displayed as black dots. The 2 elements are numbered in red and are seperated by the red line. + +![MeshStructure](drawing.svg) + +## Setup + +The test is performed with the following conditions: + +- Constraints: + - The bottom nodes (1, 2, 3) are fixed in the X and Y direction. + - The side nodes (1, 4, 7 and 3, 6, 9) are fixed in the X direction. +- Material: + - The material is described by the linear elastic model with the following parameters: + - Poisson ratio = 0.0, + - Young's modulus = 10000 $kN/m^2$ +- Conditions: + - A top load with a value of -1000 $kN/m^2$ is applied. + +## Assertions +For this test the normal stresses at $t$ = 1 are asserted. +On top of this, the displacement of the top nodes is asserted at 4 time steps: $t$ = 0.25, 0.5, 0.75 and 1. \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg new file mode 100644 index 000000000000..3d59e7f1bb6f --- /dev/null +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg @@ -0,0 +1,902 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + + + + + + + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + + + y + x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 m + 1.0 m + + + + + + + + + + + 1 + 2 + σ + + From 772c9a457786d388f1efa5fbfd5d95351248cceb Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Thu, 30 Apr 2026 11:41:07 +0200 Subject: [PATCH 09/24] changes in mesh, project and material files according to comments and changes in undrained branch --- .../test_oedometer/{ => common}/mesh.mdpa | 2 +- .../{ => drained}/MaterialParameters.json | 1 - .../{ => drained}/ProjectParameters.json | 9 +++------ .../test_triaxial/{ => common}/mesh.mdpa | 14 +++++++------- .../{ => drained}/MaterialParameters.json | 0 .../{ => drained}/ProjectParameters.json | 17 ++++------------- 6 files changed, 15 insertions(+), 28 deletions(-) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/{ => common}/mesh.mdpa (97%) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/{ => drained}/MaterialParameters.json (96%) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/{ => drained}/ProjectParameters.json (95%) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/{ => common}/mesh.mdpa (78%) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/{ => drained}/MaterialParameters.json (100%) rename applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/{ => drained}/ProjectParameters.json (93%) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa similarity index 97% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa index 5187882c367e..50700b4eece8 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa @@ -70,7 +70,7 @@ Begin SubModelPart Fixed_base End SubModelPartNodes End SubModelPart -Begin SubModelPart Sides_L_R +Begin SubModelPart Sides_rollers Begin SubModelPartNodes 3 6 diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json similarity index 96% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json index 55f723f88bb7..5329e2103fa5 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json @@ -18,7 +18,6 @@ "PERMEABILITY_YY": 4.5e-30, "PERMEABILITY_XY": 0.0, "DYNAMIC_VISCOSITY": 8.9e-07, - "THICKNESS": 1.0, "BIOT_COEFFICIENT": 1.0, "RETENTION_LAW": "SaturatedLaw", "SATURATED_SATURATION": 0.0, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json similarity index 95% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json index bd78c36a8b48..345cf3b30c13 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json @@ -20,7 +20,7 @@ "echo_level": 1, "model_import_settings": { "input_type": "mdpa", - "input_filename": "mesh" + "input_filename": "../common/mesh" }, "material_import_settings": { "materials_filename": "MaterialParameters.json" @@ -31,7 +31,7 @@ "move_mesh_flag": false, "reform_dofs_at_each_step": false, "block_builder": true, - "reset_displacements": true, + "reset_displacements": false, "convergence_criterion": "residual_criterion", "residual_relative_tolerance": 1.0e-03, "residual_absolute_tolerance": 1.0e-09, @@ -40,8 +40,6 @@ "number_cycles": 1, "reduction_factor": 0.5, "increase_factor": 2.0, - "desired_iterations": 4, - "calculate_reactions": true, "max_line_search_iterations": 5, "first_alpha_value": 0.5, "second_alpha_value": 1.0, @@ -51,7 +49,6 @@ "rotation_dofs": false, "problem_domain_sub_model_part_list": ["Soil"], "body_domain_sub_model_part_list": ["Soil"], - "processes_sub_model_part_list": ["Soil", "Top_load", "Fixed_base", "Sides_L_R"], "linear_solver_settings": { "solver_type": "LinearSolversApplication.sparse_lu", "scaling": true @@ -77,7 +74,7 @@ "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", "process_name": "ApplyVectorConstraintTableProcess", "Parameters": { - "model_part_name": "PorousDomain.Sides_L_R", + "model_part_name": "PorousDomain.Sides_rollers", "variable_name": "DISPLACEMENT", "active": [true, false, false], "is_fixed": [true, false, false], diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa similarity index 78% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/mesh.mdpa rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa index b1ccda9feb66..ed35deffa40b 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa @@ -25,16 +25,16 @@ Begin Nodes 9 1.0000000000 0.0000000000 0.0000000000 End Nodes -Begin Elements SmallStrainUPwDiffOrderAxisymmetricElement2D6N// GUI group identifier: Soil +Begin Elements SmallStrainUPwDiffOrderAxisymmetricElement2D6N 1 0 1 5 9 3 8 4 2 0 9 6 1 7 2 4 End Elements -Begin Conditions AxisymmetricLineNormalLoadDiffOrderCondition2D3N// GUI group identifier: Lateral_load +Begin Conditions AxisymmetricLineNormalLoadDiffOrderCondition2D3N 1 0 9 6 7 End Conditions -Begin SubModelPart Fixed_base // Group Fixed_base // Subtree DISPLACEMENT +Begin SubModelPart Vertically_fixed_base Begin SubModelPartNodes 5 8 @@ -42,7 +42,7 @@ Begin SubModelPart Fixed_base // Group Fixed_base // Subtree DISPLACEMENT End SubModelPartNodes End SubModelPart -Begin SubModelPart Fixed_side // Group Fixed_side // Subtree DISPLACEMENT +Begin SubModelPart Symmetry_line Begin SubModelPartNodes 1 3 @@ -50,7 +50,7 @@ Begin SubModelPart Fixed_side // Group Fixed_side // Subtree DISPLACEMENT End SubModelPartNodes End SubModelPart -Begin SubModelPart Soil // Group Soil // Subtree Parts_Soil +Begin SubModelPart Soil Begin SubModelPartNodes 1 2 @@ -68,7 +68,7 @@ Begin SubModelPart Soil // Group Soil // Subtree Parts_Soil End SubModelPartElements End SubModelPart -Begin SubModelPart Lateral_load // Group Lateral_load // Subtree Lateral_load +Begin SubModelPart Lateral_load Begin SubModelPartTables 1 End SubModelPartTables @@ -82,7 +82,7 @@ Begin SubModelPart Lateral_load // Group Lateral_load // Subtree Lateral_load End SubModelPartConditions End SubModelPart -Begin SubModelPart Top_displacement // Group Top_displacement // Subtree DISPLACEMENT +Begin SubModelPart Top_displacement Begin SubModelPartTables 2 End SubModelPartTables diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json similarity index 100% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/MaterialParameters.json rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/ProjectParameters.json similarity index 93% rename from applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/ProjectParameters.json rename to applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/ProjectParameters.json index c047bc5a3ff0..c6f609ebf547 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/ProjectParameters.json @@ -20,7 +20,7 @@ "echo_level": 1, "model_import_settings": { "input_type": "mdpa", - "input_filename": "mesh" + "input_filename": "../common/mesh" }, "material_import_settings": { "materials_filename": "MaterialParameters.json" @@ -31,7 +31,7 @@ "move_mesh_flag": false, "reform_dofs_at_each_step": false, "block_builder": true, - "reset_displacements": true, + "reset_displacements": false, "convergence_criterion": "residual_criterion", "residual_relative_tolerance": 1.0e-03, "residual_absolute_tolerance": 1.0e-09, @@ -40,8 +40,6 @@ "number_cycles": 1, "reduction_factor": 0.5, "increase_factor": 2.0, - "desired_iterations": 4, - "calculate_reactions": true, "max_line_search_iterations": 5, "first_alpha_value": 0.5, "second_alpha_value": 1.0, @@ -50,13 +48,6 @@ "line_search_tolerance": 0.5, "rotation_dofs": false, "problem_domain_sub_model_part_list": ["Soil"], - "processes_sub_model_part_list": [ - "Fixed_base", - "Fixed_side", - "Lateral_load", - "Top_displacement", - "Soil" - ], "body_domain_sub_model_part_list": ["Soil"], "linear_solver_settings": { "solver_type": "LinearSolversApplication.sparse_lu", @@ -70,7 +61,7 @@ "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", "process_name": "ApplyVectorConstraintTableProcess", "Parameters": { - "model_part_name": "PorousDomain.Fixed_base", + "model_part_name": "PorousDomain.Vertically_fixed_base", "variable_name": "DISPLACEMENT", "active": [false, true, false], "is_fixed": [false, true, false], @@ -83,7 +74,7 @@ "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", "process_name": "ApplyVectorConstraintTableProcess", "Parameters": { - "model_part_name": "PorousDomain.Fixed_side", + "model_part_name": "PorousDomain.Symmetry_line", "variable_name": "DISPLACEMENT", "active": [true, false, false], "is_fixed": [true, false, false], From 178f5a01e2c16bbed6a5b7ed996d3d0ad8082bdd Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Thu, 30 Apr 2026 13:43:17 +0200 Subject: [PATCH 10/24] add stage name drained and add functions in triaxial test --- .../tests/test_element_lab.py | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index 5a50ab908ec2..93bff0fe0b1a 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -15,49 +15,51 @@ def _assert_integration_point_tensor_results(self, integration_point_tensors, ex self.assertAlmostEqual(expected_integration_point_tensor[1], ip_tensor[1], places, msg = f"{result_name} component yy at integration point {idx}") self.assertAlmostEqual(expected_integration_point_tensor[2], ip_tensor[2], places, msg = f"{result_name} component zz at integration point {idx}") - def test_triaxial(self): + def _assert_first_ip_tensor(self, reader, result, variable_name, expected_values, precision_places, time): + for element_id, expected_tensor in enumerate(expected_values, start=1): + tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [0])[0] + self._assert_integration_point_tensor_results(tensor, expected_tensor, precision_places, variable_name) + + def test_triaxial_drained(self): """ Regression test for the triaxial experiment. """ test_name = 'test_triaxial' - file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) - simulation = test_helper.run_kratos(file_path) + stage_name = 'drained' + file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name, stage_name)) + test_helper.run_kratos(file_path) - # read the output files from the simulation for comparison + # Read the output files from the simulation for comparison reader = GiDOutputFileReader() result = reader.read_output_from(os.path.join(file_path, 'triaxial_test_output.post.res')) - number_of_elements = 2 - number_of_nodes = 9 + time = 1.0 # Assert the displacement in all nodes in all directions expected_disp = [[0.0, -0.2, 0.0], [0.0527776, -0.2, 0.0], [0.0, -0.100033, 0.0], [0.0524025, -0.0996931, 0.0], [0.0, 0.0, 0.0], [0.105197, -0.2, 0.0], [0.105114, -0.100049, 0.0], [0.0524406, 0.0, 0.0], [0.104632, 0.0, 0.0]] - for node in range(number_of_nodes): - node_displacement = reader.nodal_values_at_time("DISPLACEMENT", 1, result, [node+1]) - self._assert_integration_point_tensor_results(node_displacement, expected_disp[node], 4, "DISPLACEMENT") + for node_id, expected_node_displacement in enumerate(expected_disp, start=1): + node_displacement = reader.nodal_values_at_time("DISPLACEMENT", time, result, [node_id])[0] + self.assertVectorAlmostEqual(node_displacement, expected_node_displacement, 4, f"DISPLACEMENT at node {node_id}") # Assert the normal stress for both elements in the first integration point expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0]] - for element in range(number_of_elements): - stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1, result, [element+1], [0])[0] - self._assert_integration_point_tensor_results(stress, expected_stress[element], 4,"CAUCHY_STRESS_TENSOR") + self._assert_first_ip_tensor(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, 4, time) # Assert the engineering strain for both elements in the first integration point expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0]] - for element in range(number_of_elements): - strain = reader.element_integration_point_values_at_time("ENGINEERING_STRAIN_TENSOR", 1, result, [element+1], [0])[0] - self._assert_integration_point_tensor_results(strain, expected_strain[element], 4,"ENGINEERING_STRAIN_TENSOR") + self._assert_first_ip_tensor(reader, result, "ENGINEERING_STRAIN_TENSOR", expected_strain, 4, time) - def test_oedometer(self): + def test_oedometer_drained(self): """ Oedometer test on a linear elastic model. Application of additional load on the top leads to a vertical displacement and a change in stresses. """ test_name = 'test_oedometer' - file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) - simulation = test_helper.run_kratos(file_path) + stage_name = 'drained' + file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name, stage_name)) + test_helper.run_kratos(file_path) - # read the output files from the simulation for comparison + # Read the output files from the simulation for comparison reader = GiDOutputFileReader() result = reader.read_output_from(os.path.join(file_path, 'test_oedometer_output.post.res')) From d5019662caea826fa44ff01c3b1c40f64e9f93fa Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Thu, 30 Apr 2026 15:18:52 +0200 Subject: [PATCH 11/24] remove old code --- .../GeoMechanicsApplication/tests/test_element_lab.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index dd1642e15380..d02e9e237ba4 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -27,12 +27,6 @@ def test_triaxial_drained(self): expected_disp = [[0.0, -0.2, 0.0], [0.0527776, -0.2, 0.0], [0.0, -0.100033, 0.0], [0.0524025, -0.0996931, 0.0], [0.0, 0.0, 0.0], [0.105197, -0.2, 0.0], [0.105114, -0.100049, 0.0], [0.0524406, 0.0, 0.0], [0.104632, 0.0, 0.0]] expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0]] expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0]] - for element in range(number_of_elements): - strain = reader.element_integration_point_values_at_time("ENGINEERING_STRAIN_TENSOR", 1, result, [element+1], [0])[0] - for strain_component in strain: - self.assertAlmostEqual(expected_strain[element][0], strain_component[0], 4) # eps_xx - self.assertAlmostEqual(expected_strain[element][1], strain_component[1], 4) # eps_yy - self.assertAlmostEqual(expected_strain[element][2], strain_component[2], 4) # eps_zz self._run_triaxial_regression_test('drained', 'triaxial_test_output.post.res', expected_disp, expected_stress, expected_strain, 4) From a7dc6b8b7dae763f7b15744bf1eb0fd6ff60fe11 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 1 May 2026 09:35:52 +0200 Subject: [PATCH 12/24] change to geo drainage type --- .../test_oedometer/drained/MaterialParameters.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json index 5329e2103fa5..0b38d41110f4 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json @@ -8,7 +8,7 @@ "name": "GeoLinearElasticPlaneStrain2DLaw" }, "Variables": { - "IGNORE_UNDRAINED": true, + "GEO_DRAINAGE_TYPE": "CONSTANT_PW_FIELD", "DENSITY_SOLID": 2.65, "DENSITY_WATER": 1.0, "POROSITY": 0.3, From dba14b79ad62dbc369e5b0051035080ad358f061 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 1 May 2026 12:05:24 +0200 Subject: [PATCH 13/24] change nr of checked ip's in triaxial test Co-authored-by: Copilot --- .../tests/test_element_lab.py | 125 ++++++++---------- 1 file changed, 52 insertions(+), 73 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index d02e9e237ba4..9504ea8789bd 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -7,29 +7,17 @@ class KratosGeoMechanicsLabElementTests(KratosUnittest.TestCase): """ - This class contains some element tests, such as triaxial and oedometer tests + This class contains some element tests, such as triaxial and oedometer tests. """ - def _assert_integration_point_tensor_results(self, integration_point_tensors, expected_integration_point_tensor, places, result_name): - for idx, ip_tensor in enumerate(integration_point_tensors): - self.assertAlmostEqual(expected_integration_point_tensor[0], ip_tensor[0], places, msg = f"{result_name} component xx at integration point {idx}") - self.assertAlmostEqual(expected_integration_point_tensor[1], ip_tensor[1], places, msg = f"{result_name} component yy at integration point {idx}") - self.assertAlmostEqual(expected_integration_point_tensor[2], ip_tensor[2], places, msg = f"{result_name} component zz at integration point {idx}") - - def _assert_first_ip_tensor(self, reader, result, variable_name, expected_values, precision_places, time): - for element_id, expected_tensor in enumerate(expected_values, start=1): - tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [0])[0] - self._assert_integration_point_tensor_results(tensor, expected_tensor, precision_places, variable_name) - def test_triaxial_drained(self): """ - Regression test for the triaxial experiment. + Regression test for the triaxial experiment with a constant pore water pressure. """ expected_disp = [[0.0, -0.2, 0.0], [0.0527776, -0.2, 0.0], [0.0, -0.100033, 0.0], [0.0524025, -0.0996931, 0.0], [0.0, 0.0, 0.0], [0.105197, -0.2, 0.0], [0.105114, -0.100049, 0.0], [0.0524406, 0.0, 0.0], [0.104632, 0.0, 0.0]] - expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0]] - expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0]] - + expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.8828, -252.381, -99.8827, 0.0448209, 0, 0], [-100.045, -252.78, -100.045, 0.0314238, 0, 0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0], [-99.967, -252.589, -99.967, -0.0103576, 0, 0], [-100.064, -252.827, -100.064, 0.137162, 0, 0]] + expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.104939, -0.199861, 0.105022, 0.000100528, 0, 0], [0.10444, -0.199182, 0.104773, 6.24562e-05, 0, 0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0], [0.104915, -0.200106, 0.105298, -4.97694e-06, 0, 0], [0.105631, -0.200818, 0.105335, 0.000287088, 0, 0]] self._run_triaxial_regression_test('drained', 'triaxial_test_output.post.res', expected_disp, expected_stress, - expected_strain, 4) + expected_strain, 4, assert_all_integration_points=True) def test_triaxial_undrained(self): """ @@ -41,10 +29,10 @@ def test_triaxial_undrained(self): self._run_triaxial_regression_test('undrained', 'triaxial_undrained_test_output.post.res', expected_disp, expected_stress, expected_strain, 4) - def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_disp, expected_stress, - expected_strain, precision_places): - test_name = os.path.join('test_triaxial', stage_name) - file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) + def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_displacement, expected_stress, + expected_strain, precision_places, assert_all_integration_points=False): + test_name = 'test_triaxial' + file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name, stage_name)) test_helper.run_kratos(file_path) # Read the output files from the simulation for comparison. @@ -53,12 +41,33 @@ def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_d time = 1.0 # Assert the displacement in all nodes in all directions. - for node_id, expected_node_displacement in enumerate(expected_disp, start=1): + for node_id, expected_node_displacement in enumerate(expected_displacement, start=1): node_displacement = reader.nodal_values_at_time("DISPLACEMENT", time, result, [node_id])[0] self.assertVectorAlmostEqual(node_displacement, expected_node_displacement, precision_places) - self._assert_first_ip_tensor(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, precision_places, time) - self._assert_first_ip_tensor(reader, result, "ENGINEERING_STRAIN_TENSOR", expected_strain, precision_places, time) + if assert_all_integration_points: + self._assert_integration_point_tensors(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, + precision_places, time) + self._assert_integration_point_tensors(reader, result, "ENGINEERING_STRAIN_TENSOR", expected_strain, + precision_places, time) + else: + self._assert_first_ip_tensor(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, + precision_places, time) + self._assert_first_ip_tensor(reader, result, "ENGINEERING_STRAIN_TENSOR", expected_strain, + precision_places, time) + + def _assert_integration_point_tensors(self, reader, result, variable_name, expected_tensors, places, time): + """Assert tensor values for all integration points across both elements.""" + for flat_index, expected_tensor in enumerate(expected_tensors): + element_id, ip_index = self._get_element_id_and_ip_index(flat_index) + tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [ip_index])[0] + self._assert_integration_point_tensor_results(tensor, expected_tensor, places, variable_name) + + def _get_element_id_and_ip_index(self, flat_index): + """Map a flat integration-point index to the corresponding element and local integration point index.""" + if flat_index < 3: + return 1, flat_index + return 2, flat_index - 3 def _assert_first_ip_tensor(self, reader, result, variable_name, expected_values, precision_places, time=1.0): for element_id, expected_tensor in enumerate(expected_values, start=1): @@ -79,21 +88,20 @@ def test_oedometer_drained(self): reader = GiDOutputFileReader() result = reader.read_output_from(os.path.join(file_path, 'test_oedometer_output.post.res')) - number_of_elements = 2 - - # Assert the normal stresses of both elements (all integration points) - expected_stress = [0.0, -1000, 0.0] - stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1, result) - for element in range(number_of_elements): - self._assert_integration_point_tensor_results(stress[element], expected_stress, 6,"CAUCHY_STRESS_TENSOR") + # Assert the yy component of the normal stresses of both elements (first integration point) + expected_stress = [0.0, -1000, 0.0, 0.0, 0.0, 0.0] + stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1.0, result)[0] + self._assert_integration_point_tensor_results(stress, expected_stress, 6, "CAUCHY_STRESS_TENSOR") # Assert the displacement in all top nodes in all directions at 4 different timesteps top_nodes = [7, 8, 9] times = [0.25, 0.5, 0.75, 1.0] - for i in range(len(times)): - expected_disp = [0.0, -0.1*times[i], 0.0] - displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", times[i], result, node_ids=top_nodes) - self._assert_integration_point_tensor_results(displacements, expected_disp, 6, "DISPLACEMENT") + for step, time in enumerate(times): + expected_disp = [0.0, -0.1*time, 0.0] + displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", time, result, node_ids=top_nodes) + for node_index, displacement in enumerate(displacements): + self.assertVectorAlmostEqual(displacement, expected_disp, 6, + msg = f"DISPLACEMENT at node {top_nodes[node_index]} at time {time}") def test_triaxial_comp_6n(self): """ @@ -108,34 +116,10 @@ def test_triaxial_comp_6n(self): run_multiple_stages.run_stages(project_path, n_stages) reader = GiDOutputFileReader() - - # Assert - output_data = reader.read_output_from(os.path.join(project_path, "triaxial_comp_6n_stage1.post.res")) - time = 1.0 - stress_vectors_per_element = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", time, output_data) - number_of_elements = 2 - self.assertEqual(number_of_elements, len(stress_vectors_per_element)) - - number_of_integration_points_per_element = 3 - for element_stress_vectors in stress_vectors_per_element: - self.assertEqual(number_of_integration_points_per_element, len(element_stress_vectors)) - for stress_vector in element_stress_vectors: - self.assertAlmostEqual(-100.0, stress_vector[0], 3) # sigma_xx - self.assertAlmostEqual(-100.0, stress_vector[1], 3) # sigma_yy - self.assertAlmostEqual(-100.0, stress_vector[2], 3) # sigma_zz - - output_data = reader.read_output_from(os.path.join(project_path, "triaxial_comp_6n_stage2.post.res")) - time = 1.25 - stress_vectors_per_element = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", time, output_data) - self.assertEqual(number_of_elements, len(stress_vectors_per_element)) - - for element_stress_vectors in stress_vectors_per_element: - self.assertEqual(number_of_integration_points_per_element, len(element_stress_vectors)) - for stress_vector in element_stress_vectors: - self.assertAlmostEqual(-100.0, stress_vector[0], 2) # sigma_xx - self.assertAlmostEqual(-300.0, stress_vector[1], 2) # sigma_yy - self.assertAlmostEqual(-100.0, stress_vector[2], 2) # sigma_zz - + self._assert_triaxial_comp_6n_stage(reader, project_path, "triaxial_comp_6n_stage1.post.res", 1.0, + [-100.0, -100.0, -100.0, 0.0, 0.0, 0.0], 3) + self._assert_triaxial_comp_6n_stage(reader, project_path, "triaxial_comp_6n_stage2.post.res", 1.25, + [-100.0, -300.0, -100.0, 0.0, 0.0, 0.0], 2) def test_oedometer_ULFEM(self): """ @@ -176,15 +160,10 @@ def test_oedometer_ULFEM_diff_order(self): for top_node_nbr in top_node_nbrs: self.assertAlmostEqual(-1e-04, y_displacements[top_node_nbr], 6) - def _assert_triaxial_comp_6n_stage(self, reader, project_path, output_file_name, time, expected_stress_vector, - number_of_integration_points_per_element, places): - output_data = reader.read_output_from(os.path.join(project_path, output_file_name)) - stress_vectors_per_element = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", time, output_data) - self.assertEqual(2, len(stress_vectors_per_element)) - - for element_stress_vectors in stress_vectors_per_element: - self.assertEqual(number_of_integration_points_per_element, len(element_stress_vectors)) - self._assert_integration_point_tensor_results(element_stress_vectors, expected_stress_vector, places, "CAUCHY_STRESS_TENSOR") + def _assert_triaxial_comp_6n_stage(self, reader, project_path, output_file_name, time, expected_stress_vector, places): + result = reader.read_output_from(os.path.join(project_path, output_file_name)) + stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", time, result)[0] + self._assert_integration_point_tensor_results(stress, expected_stress_vector, places, "CAUCHY_STRESS_TENSOR") def _assert_oedometer_effective_stresses(self, effective_stresses, expected_yy, places_yy): for element in effective_stresses: @@ -199,7 +178,7 @@ def _assert_y_displacements(self, displacements, expected_y, places): def _assert_integration_point_tensor_results(self, integration_point_tensors, expected_integration_point_tensor, places, result_name): for idx, ip_tensor in enumerate(integration_point_tensors): - self.assertVectorAlmostEqual(expected_integration_point_tensor[:2], ip_tensor[:2], places, msg = f"{result_name} component xx, yy, zz at integration point {idx}") + self.assertVectorAlmostEqual(expected_integration_point_tensor, ip_tensor, places, msg = f"{result_name} components at integration point {idx}") if __name__ == '__main__': From 5c697888936175b4d59ea3be9556f43cab64f744 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 1 May 2026 14:59:41 +0200 Subject: [PATCH 14/24] make code use general helper functions Co-authored-by: Copilot --- .../tests/test_element_lab.py | 132 ++++++++---------- 1 file changed, 61 insertions(+), 71 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index 9504ea8789bd..292d468afc17 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -1,3 +1,4 @@ +from csv import reader import os import KratosMultiphysics.KratosUnittest as KratosUnittest @@ -10,9 +11,7 @@ class KratosGeoMechanicsLabElementTests(KratosUnittest.TestCase): This class contains some element tests, such as triaxial and oedometer tests. """ def test_triaxial_drained(self): - """ - Regression test for the triaxial experiment with a constant pore water pressure. - """ + """Regression test for the triaxial experiment on a mohr coulomb model with a constant pore water pressure.""" expected_disp = [[0.0, -0.2, 0.0], [0.0527776, -0.2, 0.0], [0.0, -0.100033, 0.0], [0.0524025, -0.0996931, 0.0], [0.0, 0.0, 0.0], [0.105197, -0.2, 0.0], [0.105114, -0.100049, 0.0], [0.0524406, 0.0, 0.0], [0.104632, 0.0, 0.0]] expected_stress = [[-99.9808, -252.622, -99.9806, 0.193199, 0.0, 0.0], [-99.8828, -252.381, -99.8827, 0.0448209, 0, 0], [-100.045, -252.78, -100.045, 0.0314238, 0, 0], [-99.9991, -252.668, -99.9991, 0.00846584, 0, 0], [-99.967, -252.589, -99.967, -0.0103576, 0, 0], [-100.064, -252.827, -100.064, 0.137162, 0, 0]] expected_strain = [[0.104863, -0.19973, 0.104946, 0.000440186, 0.0, 0.0], [0.104939, -0.199861, 0.105022, 0.000100528, 0, 0], [0.10444, -0.199182, 0.104773, 6.24562e-05, 0, 0], [0.1055, -0.200303, 0.104922, 3.84218e-05, 0, 0], [0.104915, -0.200106, 0.105298, -4.97694e-06, 0, 0], [0.105631, -0.200818, 0.105335, 0.000287088, 0, 0]] @@ -55,53 +54,32 @@ def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_d precision_places, time) self._assert_first_ip_tensor(reader, result, "ENGINEERING_STRAIN_TENSOR", expected_strain, precision_places, time) - - def _assert_integration_point_tensors(self, reader, result, variable_name, expected_tensors, places, time): - """Assert tensor values for all integration points across both elements.""" - for flat_index, expected_tensor in enumerate(expected_tensors): - element_id, ip_index = self._get_element_id_and_ip_index(flat_index) - tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [ip_index])[0] - self._assert_integration_point_tensor_results(tensor, expected_tensor, places, variable_name) - - def _get_element_id_and_ip_index(self, flat_index): - """Map a flat integration-point index to the corresponding element and local integration point index.""" - if flat_index < 3: - return 1, flat_index - return 2, flat_index - 3 - - def _assert_first_ip_tensor(self, reader, result, variable_name, expected_values, precision_places, time=1.0): - for element_id, expected_tensor in enumerate(expected_values, start=1): - tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [0])[0] - self._assert_integration_point_tensor_results(tensor, expected_tensor, precision_places, variable_name) - + def test_oedometer_drained(self): - """ - Oedometer test on a linear elastic model. - Application of additional load on the top leads to a vertical displacement and a change in stresses. - """ + """Regression test for the oedometer experiment on a linear elastic model with constant pore water pressure.""" + expected_stress_per_ip = [0.0, -1000.0, 0.0, 0.0, 0.0, 0.0] + expected_stress = [expected_stress_per_ip] * 6 + expected_y_displacements = [-0.025, -0.05, -0.075, -0.1] + displacement_times = [0.25, 0.5, 0.75, 1.0] + top_nodes = [7, 8, 9] + self._run_oedometer_regression_test('drained', 'test_oedometer_output.post.res', expected_stress, + expected_y_displacements, displacement_times, top_nodes, 6) + + def _run_oedometer_regression_test(self, stage_name, output_file_name, expected_stress, + expected_y_displacements, displacement_times, top_nodes, precision_places): + """Run the oedometer regression test and validate stress tensors and y-displacements in time.""" test_name = 'test_oedometer' - stage_name = 'drained' file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name, stage_name)) test_helper.run_kratos(file_path) - # Read the output files from the simulation for comparison reader = GiDOutputFileReader() - result = reader.read_output_from(os.path.join(file_path, 'test_oedometer_output.post.res')) + result = reader.read_output_from(os.path.join(file_path, output_file_name)) - # Assert the yy component of the normal stresses of both elements (first integration point) - expected_stress = [0.0, -1000, 0.0, 0.0, 0.0, 0.0] - stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", 1.0, result)[0] - self._assert_integration_point_tensor_results(stress, expected_stress, 6, "CAUCHY_STRESS_TENSOR") + self._assert_integration_point_tensors(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, + precision_places, time=1.0) - # Assert the displacement in all top nodes in all directions at 4 different timesteps - top_nodes = [7, 8, 9] - times = [0.25, 0.5, 0.75, 1.0] - for step, time in enumerate(times): - expected_disp = [0.0, -0.1*time, 0.0] - displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", time, result, node_ids=top_nodes) - for node_index, displacement in enumerate(displacements): - self.assertVectorAlmostEqual(displacement, expected_disp, 6, - msg = f"DISPLACEMENT at node {top_nodes[node_index]} at time {time}") + for time, expected_y in zip(displacement_times, expected_y_displacements): + self._assert_y_displacements_at_time(reader, result, top_nodes, expected_y, precision_places, time) def test_triaxial_comp_6n(self): """ @@ -110,39 +88,38 @@ def test_triaxial_comp_6n(self): 1) apply confining stress of -100 kPa 2) apply deviatoric stress of -200 kPa """ - project_path = test_helper.get_file_path(os.path.join('test_element_lab', 'triaxial_comp_6n')) - + test_name = 'triaxial_comp_6n' + project_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) n_stages = 2 run_multiple_stages.run_stages(project_path, n_stages) - reader = GiDOutputFileReader() - self._assert_triaxial_comp_6n_stage(reader, project_path, "triaxial_comp_6n_stage1.post.res", 1.0, - [-100.0, -100.0, -100.0, 0.0, 0.0, 0.0], 3) - self._assert_triaxial_comp_6n_stage(reader, project_path, "triaxial_comp_6n_stage2.post.res", 1.25, - [-100.0, -300.0, -100.0, 0.0, 0.0, 0.0], 2) + + result = reader.read_output_from(os.path.join(project_path, "triaxial_comp_6n_stage1.post.res")) + expected_stress = [[-100.0, -100.0, -100.0, 0.0, 0.0, 0.0]] * 6 + self._assert_integration_point_tensors(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, 3, time=1.0) + + result = reader.read_output_from(os.path.join(project_path, "triaxial_comp_6n_stage2.post.res")) + expected_stress = [[-100.0, -300.0, -100.0, 0.0, 0.0, 0.0]] * 6 + self._assert_integration_point_tensors(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, 2, time=1.25) def test_oedometer_ULFEM(self): """ Oedometer test on a linear elastic model with 2D6N elements """ test_name = 'oedometer_ULFEM' - project_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) - simulation = test_helper.run_kratos(project_path) + file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) + simulation = test_helper.run_kratos(file_path) effective_stresses = test_helper.get_cauchy_stress_tensor(simulation) self._assert_oedometer_effective_stresses(effective_stresses, -1000000.0, 2) top_node_nbrs = [1, 2] - output_file_path = os.path.join(project_path, test_name+'.post.res') - output_reader = GiDOutputFileReader() - output_data = output_reader.read_output_from(output_file_path) - displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", 0.1, output_data, node_ids=top_node_nbrs) - self._assert_y_displacements(displacements, -0.00990099, 6) - - displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", 0.7, output_data, node_ids=top_node_nbrs) - self._assert_y_displacements(displacements, -0.0654206, 6) + output_file = os.path.join(file_path, test_name+'.post.res') + reader = GiDOutputFileReader() + result = reader.read_output_from(output_file) - displacements = GiDOutputFileReader.nodal_values_at_time("DISPLACEMENT", 1.0, output_data, node_ids=top_node_nbrs) - self._assert_y_displacements(displacements, -0.0909090909516868, 6) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.00990099, 6, 0.1) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0654206, 6, 0.7) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0909090909516868, 6, 1.0) def test_oedometer_ULFEM_diff_order(self): """ @@ -152,18 +129,13 @@ def test_oedometer_ULFEM_diff_order(self): project_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) simulation = test_helper.run_kratos(project_path) effective_stresses = test_helper.get_cauchy_stress_tensor(simulation) - displacements = test_helper.get_displacement(simulation) self._assert_oedometer_effective_stresses(effective_stresses, -1000.0, 3) - y_displacements = [displacement[1] for displacement in displacements] + output_file = os.path.join(project_path, test_name + '.post.res') + reader = GiDOutputFileReader() + result = reader.read_output_from(output_file) top_node_nbrs = [1] - for top_node_nbr in top_node_nbrs: - self.assertAlmostEqual(-1e-04, y_displacements[top_node_nbr], 6) - - def _assert_triaxial_comp_6n_stage(self, reader, project_path, output_file_name, time, expected_stress_vector, places): - result = reader.read_output_from(os.path.join(project_path, output_file_name)) - stress = reader.element_integration_point_values_at_time("CAUCHY_STRESS_TENSOR", time, result)[0] - self._assert_integration_point_tensor_results(stress, expected_stress_vector, places, "CAUCHY_STRESS_TENSOR") + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -1e-4, 6, time=1.0) def _assert_oedometer_effective_stresses(self, effective_stresses, expected_yy, places_yy): for element in effective_stresses: @@ -172,7 +144,8 @@ def _assert_oedometer_effective_stresses(self, effective_stresses, expected_yy, self.assertAlmostEqual(expected_yy, integration_point[1,1], places_yy) self.assertAlmostEqual(0.0, integration_point[2,2], 3) - def _assert_y_displacements(self, displacements, expected_y, places): + def _assert_y_displacements_at_time(self, reader, result, node_ids, expected_y, places, time=1.0): + displacements = reader.nodal_values_at_time("DISPLACEMENT", time, result, node_ids=node_ids) for displacement in displacements: self.assertAlmostEqual(expected_y, displacement[1], places) @@ -180,6 +153,23 @@ def _assert_integration_point_tensor_results(self, integration_point_tensors, ex for idx, ip_tensor in enumerate(integration_point_tensors): self.assertVectorAlmostEqual(expected_integration_point_tensor, ip_tensor, places, msg = f"{result_name} components at integration point {idx}") + def _assert_integration_point_tensors(self, reader, result, variable_name, expected_tensors, places, time): + """Assert tensor values for all integration points across both elements.""" + for flat_index, expected_tensor in enumerate(expected_tensors): + element_id, ip_index = self._get_element_id_and_ip_index(flat_index) + tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [ip_index])[0] + self._assert_integration_point_tensor_results(tensor, expected_tensor, places, variable_name) + + def _get_element_id_and_ip_index(self, flat_index): + """Map a flat integration-point index to the corresponding element and local integration point index.""" + if flat_index < 3: + return 1, flat_index + return 2, flat_index - 3 + + def _assert_first_ip_tensor(self, reader, result, variable_name, expected_values, precision_places, time=1.0): + for element_id, expected_tensor in enumerate(expected_values, start=1): + tensor = reader.element_integration_point_values_at_time(variable_name, time, result, [element_id], [0])[0] + self._assert_integration_point_tensor_results(tensor, expected_tensor, precision_places, variable_name) if __name__ == '__main__': KratosUnittest.main() From 83fb795dc44184f588010ccb762ddff3a7e2a6c4 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 1 May 2026 15:00:01 +0200 Subject: [PATCH 15/24] change output file type --- .../oedometer_ULFEM_diff_order/ProjectParameters.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json index f57edf5de241..0234cb1b8ae3 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json @@ -79,7 +79,7 @@ "gidpost_flags": { "WriteDeformedMeshFlag": "WriteUndeformed", "WriteConditionsFlag": "WriteElementsOnly", - "GiDPostMode": "GiD_PostBinary", + "GiDPostMode": "GiD_PostAscii", "MultiFileFlag": "SingleFile" }, "file_label": "step", From 9cca8811cf09f58971ce609073122535c3fbaee5 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Fri, 1 May 2026 15:12:14 +0200 Subject: [PATCH 16/24] change the poisson ratio --- .../GeoMechanicsApplication/tests/test_element_lab.py | 4 ++-- .../test_oedometer/drained/MaterialParameters.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index 292d468afc17..ab62725cadb7 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -57,9 +57,9 @@ def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_d def test_oedometer_drained(self): """Regression test for the oedometer experiment on a linear elastic model with constant pore water pressure.""" - expected_stress_per_ip = [0.0, -1000.0, 0.0, 0.0, 0.0, 0.0] + expected_stress_per_ip = [-333.333, -1000.0, -333.333, 0.0, 0.0, 0.0] expected_stress = [expected_stress_per_ip] * 6 - expected_y_displacements = [-0.025, -0.05, -0.075, -0.1] + expected_y_displacements = [-0.0208333, -0.0416667, -0.0625, -0.0833333] displacement_times = [0.25, 0.5, 0.75, 1.0] top_nodes = [7, 8, 9] self._run_oedometer_regression_test('drained', 'test_oedometer_output.post.res', expected_stress, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json index 0b38d41110f4..b4cb09e2f26c 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json @@ -22,7 +22,7 @@ "RETENTION_LAW": "SaturatedLaw", "SATURATED_SATURATION": 0.0, "YOUNG_MODULUS": 1.0e+04, - "POISSON_RATIO": 0.0 + "POISSON_RATIO": 0.25 } } } From b4baf8b417ed9b00f7f15cc02f2a236e5c4b0459 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Mon, 4 May 2026 11:49:21 +0200 Subject: [PATCH 17/24] change output file name --- .../oedometer_ULFEM_diff_order/ProjectParameters.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json index 0234cb1b8ae3..dd8276590d19 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/ProjectParameters.json @@ -73,7 +73,7 @@ "process_name": "GiDOutputProcess", "Parameters": { "model_part_name": "PorousDomain.porous_computational_model_part", - "output_name": "Oedometer_ULFEM_diff_order", + "output_name": "oedometer_ULFEM_diff_order", "postprocess_parameters": { "result_file_configuration": { "gidpost_flags": { From 2cb498816afbad15b05fd7fcc2853b5571f035e8 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 09:38:54 +0200 Subject: [PATCH 18/24] remove value for the bulk modulus fluid --- .../oedometer_ULFEM_diff_order/MaterialParameters.json | 1 - .../test_oedometer/drained/MaterialParameters.json | 1 - .../test_triaxial/drained/MaterialParameters.json | 1 - .../test_element_lab/triaxial_comp_6n/MaterialParameters.json | 1 - 4 files changed, 4 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/MaterialParameters.json index 53ea187e7585..1489d2a454da 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/oedometer_ULFEM_diff_order/MaterialParameters.json @@ -14,7 +14,6 @@ "DENSITY_WATER" : 1.0e3, "POROSITY" : 0.3, "BULK_MODULUS_SOLID" : 1.0e12, - "BULK_MODULUS_FLUID" : 2.0e-30, "PERMEABILITY_XX" : 4.5e-30, "PERMEABILITY_YY" : 4.5e-30, "PERMEABILITY_XY" : 0.0, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json index b4cb09e2f26c..a8fbd945d748 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json @@ -13,7 +13,6 @@ "DENSITY_WATER": 1.0, "POROSITY": 0.3, "BULK_MODULUS_SOLID": 1.0e+09, - "BULK_MODULUS_FLUID": 2.0e-30, "PERMEABILITY_XX": 4.5e-30, "PERMEABILITY_YY": 4.5e-30, "PERMEABILITY_XY": 0.0, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json index abf8a102f5f2..8d8558f218f0 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/drained/MaterialParameters.json @@ -13,7 +13,6 @@ "DENSITY_WATER": 1.0, "POROSITY": 0.3, "BULK_MODULUS_SOLID": 1.0e+09, - "BULK_MODULUS_FLUID": 2.0e-30, "PERMEABILITY_XX": 4.5e-30, "PERMEABILITY_YY": 4.5e-30, "PERMEABILITY_XY": 0.0, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/triaxial_comp_6n/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/triaxial_comp_6n/MaterialParameters.json index 498ffb63aab1..e4291a94c1c4 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/triaxial_comp_6n/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/triaxial_comp_6n/MaterialParameters.json @@ -14,7 +14,6 @@ "DENSITY_WATER" : 1.0, "POROSITY" : 0.3, "BULK_MODULUS_SOLID" : 1.0e9, - "BULK_MODULUS_FLUID" : 2.0e-30, "PERMEABILITY_XX" : 4.5e-30, "PERMEABILITY_YY" : 4.5e-30, "PERMEABILITY_XY" : 0.0, From e4aa62dc27877112c0f9dbf0c4f8706c2666fe0f Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 10:34:15 +0200 Subject: [PATCH 19/24] apply stepwise loading + remove unused material parameters and set to si units (N instead of kN) --- .../test_oedometer/common/mesh.mdpa | 9 ++++++++- .../test_oedometer/drained/MaterialParameters.json | 13 +++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa index 50700b4eece8..c59fb27f35fa 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa @@ -1,6 +1,13 @@ Begin Table 1 TIME LINE_NORMAL_LOAD_Y 0.0 0.0 - 1.0 -1000 + 0.01 -250000 + 0.25 -250000 + 0.26 -500000 + 0.50 -500000 + 0.51 -750000 + 0.75 -750000 + 0.76 -1000000 + 1.0 -1000000 End Table Begin Properties 0 diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json index a8fbd945d748..0d17c8f4e782 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/MaterialParameters.json @@ -9,18 +9,11 @@ }, "Variables": { "GEO_DRAINAGE_TYPE": "CONSTANT_PW_FIELD", - "DENSITY_SOLID": 2.65, - "DENSITY_WATER": 1.0, + "DENSITY_SOLID": 2.65e+03, + "DENSITY_WATER": 1.0e+03, "POROSITY": 0.3, "BULK_MODULUS_SOLID": 1.0e+09, - "PERMEABILITY_XX": 4.5e-30, - "PERMEABILITY_YY": 4.5e-30, - "PERMEABILITY_XY": 0.0, - "DYNAMIC_VISCOSITY": 8.9e-07, - "BIOT_COEFFICIENT": 1.0, - "RETENTION_LAW": "SaturatedLaw", - "SATURATED_SATURATION": 0.0, - "YOUNG_MODULUS": 1.0e+04, + "YOUNG_MODULUS": 1.0e+07, "POISSON_RATIO": 0.25 } } From c537f2562ba6911e55a1c7f0326e5aeb5655e295 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 10:43:46 +0200 Subject: [PATCH 20/24] si units in assertion and stepwise loading --- .../tests/test_element_lab.py | 2 +- .../test_oedometer/common/mesh.mdpa | 34 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index ab62725cadb7..9d2989cafe1c 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -57,7 +57,7 @@ def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_d def test_oedometer_drained(self): """Regression test for the oedometer experiment on a linear elastic model with constant pore water pressure.""" - expected_stress_per_ip = [-333.333, -1000.0, -333.333, 0.0, 0.0, 0.0] + expected_stress_per_ip = [-333333, -1e+06, -333333, 0.0, 0.0, 0.0] expected_stress = [expected_stress_per_ip] * 6 expected_y_displacements = [-0.0208333, -0.0416667, -0.0625, -0.0833333] displacement_times = [0.25, 0.5, 0.75, 1.0] diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa index c59fb27f35fa..e3044d220e15 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa @@ -1,13 +1,13 @@ Begin Table 1 TIME LINE_NORMAL_LOAD_Y 0.0 0.0 - 0.01 -250000 - 0.25 -250000 - 0.26 -500000 - 0.50 -500000 - 0.51 -750000 - 0.75 -750000 - 0.76 -1000000 - 1.0 -1000000 + 0.01 -2.5e+05 + 0.25 -2.5e+05 + 0.26 -5e+05 + 0.50 -5e+05 + 0.51 -7.5e+05 + 0.75 -7.5e+05 + 0.76 -1e+06 + 1.0 -1e+06 End Table Begin Properties 0 @@ -17,15 +17,15 @@ Begin Properties 1 End Properties Begin Nodes - 1 0.0000000000 0.0000000000 0.0000000000 - 2 0.5000000000 0.0000000000 0.0000000000 - 3 1.0000000000 0.0000000000 0.0000000000 - 4 0.0000000000 0.5000000000 0.0000000000 - 5 0.5000000000 0.5000000000 0.0000000000 - 6 1.0000000000 0.5000000000 0.0000000000 - 7 0.0000000000 1.0000000000 0.0000000000 - 8 0.5000000000 1.0000000000 0.0000000000 - 9 1.0000000000 1.0000000000 0.0000000000 + 1 0.0 0.0 0.0 + 2 0.5 0.0 0.0 + 3 1.0 0.0 0.0 + 4 0.0 0.5 0.0 + 5 0.5 0.5 0.0 + 6 1.0 0.5 0.0 + 7 0.0 1.0 0.0 + 8 0.5 1.0 0.0 + 9 1.0 1.0 0.0 End Nodes Begin Elements SmallStrainUPwDiffOrderElement2D6N From 0ebbb37c5fc0a804ab4e69a03502f4c21f7a7b19 Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 11:00:07 +0200 Subject: [PATCH 21/24] fix fixed base constraint --- .../test_oedometer/drained/ProjectParameters.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json index 345cf3b30c13..f3153e626758 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json @@ -83,16 +83,16 @@ } }, { - "python_module": "apply_scalar_constraint_table_process", + "python_module": "apply_vector_constraint_table_process", "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", - "process_name": "ApplyScalarConstraintTableProcess", + "process_name": "ApplyVectorConstraintTableProcess", "Parameters": { "model_part_name": "PorousDomain.Fixed_base", - "variable_name": "WATER_PRESSURE", - "is_fixed": true, - "fluid_pressure_type": "Uniform", - "value": 0.0, - "table": 0 + "variable_name": "DISPLACEMENT", + "active": [true, true, false], + "is_fixed": [true, true, false], + "value": [0.0, 0.0, 0.0], + "table": [0, 0, 0] } } ], From f34cc3bc785122d708fd55f50c4b98cb88fa6c1a Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 11:34:38 +0200 Subject: [PATCH 22/24] use axisymmetric element type and loading --- .../test_oedometer/common/mesh.mdpa | 20 +++++++++---------- .../drained/ProjectParameters.json | 13 ++++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa index e3044d220e15..77839bd15598 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/common/mesh.mdpa @@ -1,13 +1,13 @@ Begin Table 1 TIME LINE_NORMAL_LOAD_Y 0.0 0.0 - 0.01 -2.5e+05 - 0.25 -2.5e+05 - 0.26 -5e+05 - 0.50 -5e+05 - 0.51 -7.5e+05 - 0.75 -7.5e+05 - 0.76 -1e+06 - 1.0 -1e+06 + 0.01 2.5e+05 + 0.25 2.5e+05 + 0.26 5e+05 + 0.50 5e+05 + 0.51 7.5e+05 + 0.75 7.5e+05 + 0.76 1e+06 + 1.0 1e+06 End Table Begin Properties 0 @@ -28,12 +28,12 @@ Begin Nodes 9 1.0 1.0 0.0 End Nodes -Begin Elements SmallStrainUPwDiffOrderElement2D6N +Begin Elements SmallStrainUPwDiffOrderAxisymmetricElement2D6N 1 1 7 1 3 4 2 5 2 1 3 9 7 6 8 5 End Elements -Begin Conditions LineLoadDiffOrderCondition2D3N +Begin Conditions AxisymmetricLineNormalLoadDiffOrderCondition2D3N 1 0 9 7 8 End Conditions diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json index f3153e626758..0a7e1d2d5bab 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json @@ -98,15 +98,16 @@ ], "loads_process_list": [ { - "python_module": "apply_vector_constraint_table_process", + "python_module": "apply_normal_load_table_process", "kratos_module": "KratosMultiphysics.GeoMechanicsApplication", - "process_name": "ApplyVectorConstraintTableProcess", + "process_name": "ApplyNormalLoadTableProcess", "Parameters": { "model_part_name": "PorousDomain.Top_load", - "variable_name": "LINE_LOAD", - "active": [false, true, false], - "value": [0.0, 0.0, 0.0], - "table": [0, 1, 0] + "variable_name": "NORMAL_CONTACT_STRESS", + "active": [true, false], + "value": [0.0, 0.0], + "table": [1, 0], + "fluid_pressure_type": "Uniform" } } ] From fa12b465158d3d92242e782821c6d3fae05612dd Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 11:57:02 +0200 Subject: [PATCH 23/24] Update readme Co-authored-by: Copilot --- .../test_element_lab/test_oedometer/README.md | 34 +++++----- .../test_oedometer/drawing.svg | 63 ++++++++++++++++++- 2 files changed, 79 insertions(+), 18 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md index 4acb28abe173..f12cbfe8d11c 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/README.md @@ -1,26 +1,30 @@ -# Oedometer test +# Oedometer Test -This test is an oedometer test with a prescribed top load on a linear elastic model. It mimics a lab test, where soil properties such as the consolidation are determined. -In the lab this is performed on a cylindric volume of soil, where an increasing pressure is applied on the top of the cylinder. In the model test, the soil sample is emulated by two 2 differential order elements. +This test simulates an oedometer test with a prescribed stepwise top loading process on a linear elastic soil model. It replicates a laboratory test used to determine soil properties, such as consolidation characteristics. +In the laboratory, this is performed on a cylindrical volume of soil, where an increasing pressure is applied on the top of the cylinder. In the model test, the soil sample is emulated by two axisymmetric differential order elements. -A schematic overview of the model is displayed in the figure below. Here the nodes are displayed as black dots. The 2 elements are numbered in red and are seperated by the red line. +A schematic overview of the model is displayed in the figure below. Here the nodes are displayed as black dots. The two elements are numbered in red and are separated by the red line. The symmetry axis is displayed as a red dashed line. ![MeshStructure](drawing.svg) ## Setup -The test is performed with the following conditions: +The test is performed under the following conditions: -- Constraints: - - The bottom nodes (1, 2, 3) are fixed in the X and Y direction. - - The side nodes (1, 4, 7 and 3, 6, 9) are fixed in the X direction. -- Material: +- **Constraints**: + - The bottom nodes (1, 2, 3) are fixed in the X and Y directions. + - The side nodes and the symmetry axis (3, 6, 9 and 1, 4, 7) are fixed in the X direction. +- **Material**: - The material is described by the linear elastic model with the following parameters: - - Poisson ratio = 0.0, - - Young's modulus = 10000 $kN/m^2$ -- Conditions: - - A top load with a value of -1000 $kN/m^2$ is applied. + - Poisson's ratio = 0.25 + - Young's modulus = 1e+07 Pa +- **Loading Conditions**: + - A top load is applied in 4 equal steps: + - t = 0.01 to 0.25: load = -2.5e+05 Pa + - t = 0.26 to 0.50: load = -5e+05 Pa + - t = 0.51 to 0.75: load = -7.5e+05 Pa + - t = 0.76 to 1.0: load = -1e+06 Pa ## Assertions -For this test the normal stresses at $t$ = 1 are asserted. -On top of this, the displacement of the top nodes is asserted at 4 time steps: $t$ = 0.25, 0.5, 0.75 and 1. \ No newline at end of file +For this test, the stresses at t = 1.0 are verified. +Additionally, the displacement in the Y-direction of the top nodes is verified at four time steps: t = 0.25, 0.5, 0.75, and 1.0. \ No newline at end of file diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg index 3d59e7f1bb6f..ee608c833068 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drawing.svg @@ -28,12 +28,44 @@ inkscape:cy="258.91089" inkscape:window-width="1920" inkscape:window-height="1009" - inkscape:window-x="-8" + inkscape:window-x="1912" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:current-layer="layer1" /> + + + σ + id="tspan11">σ + + + From 4dcf3c01605c902b0f261d12ddaccf2d5713e88f Mon Sep 17 00:00:00 2001 From: Sabine-van-Dijk Date: Tue, 5 May 2026 15:10:53 +0200 Subject: [PATCH 24/24] apply review comments --- .../tests/test_element_lab.py | 22 +++++++++---------- .../drained/ProjectParameters.json | 4 ++-- .../test_triaxial/common/mesh.mdpa | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab.py b/applications/GeoMechanicsApplication/tests/test_element_lab.py index 9d2989cafe1c..303b6e869600 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab.py +++ b/applications/GeoMechanicsApplication/tests/test_element_lab.py @@ -57,16 +57,16 @@ def _run_triaxial_regression_test(self, stage_name, output_file_name, expected_d def test_oedometer_drained(self): """Regression test for the oedometer experiment on a linear elastic model with constant pore water pressure.""" - expected_stress_per_ip = [-333333, -1e+06, -333333, 0.0, 0.0, 0.0] + expected_stress_per_ip = [-1e+06/3.0, -1e+06, -1e+06/3.0, 0.0, 0.0, 0.0] expected_stress = [expected_stress_per_ip] * 6 - expected_y_displacements = [-0.0208333, -0.0416667, -0.0625, -0.0833333] + expected_y_displacements = [-0.0208, -0.0417, -0.0625, -0.0833] displacement_times = [0.25, 0.5, 0.75, 1.0] top_nodes = [7, 8, 9] self._run_oedometer_regression_test('drained', 'test_oedometer_output.post.res', expected_stress, - expected_y_displacements, displacement_times, top_nodes, 6) + expected_y_displacements, displacement_times, top_nodes, 0, 4) def _run_oedometer_regression_test(self, stage_name, output_file_name, expected_stress, - expected_y_displacements, displacement_times, top_nodes, precision_places): + expected_y_displacements, displacement_times, top_nodes, precision_places_stress, precision_places_displacement=4): """Run the oedometer regression test and validate stress tensors and y-displacements in time.""" test_name = 'test_oedometer' file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name, stage_name)) @@ -76,10 +76,10 @@ def _run_oedometer_regression_test(self, stage_name, output_file_name, expected_ result = reader.read_output_from(os.path.join(file_path, output_file_name)) self._assert_integration_point_tensors(reader, result, "CAUCHY_STRESS_TENSOR", expected_stress, - precision_places, time=1.0) + precision_places_stress, time=1.0) for time, expected_y in zip(displacement_times, expected_y_displacements): - self._assert_y_displacements_at_time(reader, result, top_nodes, expected_y, precision_places, time) + self._assert_y_displacements_at_time(reader, result, top_nodes, expected_y, precision_places_displacement, time) def test_triaxial_comp_6n(self): """ @@ -110,16 +110,16 @@ def test_oedometer_ULFEM(self): file_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) simulation = test_helper.run_kratos(file_path) effective_stresses = test_helper.get_cauchy_stress_tensor(simulation) - self._assert_oedometer_effective_stresses(effective_stresses, -1000000.0, 2) + self._assert_oedometer_effective_stresses(effective_stresses, -1e+06, 2) top_node_nbrs = [1, 2] output_file = os.path.join(file_path, test_name+'.post.res') reader = GiDOutputFileReader() result = reader.read_output_from(output_file) - self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.00990099, 6, 0.1) - self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0654206, 6, 0.7) - self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0909090909516868, 6, 1.0) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0099, 4, 0.1) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0654, 4, 0.7) + self._assert_y_displacements_at_time(reader, result, top_node_nbrs, -0.0909, 4, 1.0) def test_oedometer_ULFEM_diff_order(self): """ @@ -129,7 +129,7 @@ def test_oedometer_ULFEM_diff_order(self): project_path = test_helper.get_file_path(os.path.join('test_element_lab', test_name)) simulation = test_helper.run_kratos(project_path) effective_stresses = test_helper.get_cauchy_stress_tensor(simulation) - self._assert_oedometer_effective_stresses(effective_stresses, -1000.0, 3) + self._assert_oedometer_effective_stresses(effective_stresses, -1e+03, 3) output_file = os.path.join(project_path, test_name + '.post.res') reader = GiDOutputFileReader() diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json index 0a7e1d2d5bab..f3aa59bfbd05 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_oedometer/drained/ProjectParameters.json @@ -38,8 +38,8 @@ "min_iterations": 6, "max_iterations": 50, "number_cycles": 1, - "reduction_factor": 0.5, - "increase_factor": 2.0, + "reduction_factor": 1.0, + "increase_factor": 1.0, "max_line_search_iterations": 5, "first_alpha_value": 0.5, "second_alpha_value": 1.0, diff --git a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa index fa2099426427..2315c73c9ded 100644 --- a/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa +++ b/applications/GeoMechanicsApplication/tests/test_element_lab/test_triaxial/common/mesh.mdpa @@ -29,8 +29,8 @@ Begin Nodes End Nodes Begin Elements SmallStrainUPwDiffOrderAxisymmetricElement2D6N - 1 0 1 5 9 3 8 4 - 2 0 9 6 1 7 2 4 + 1 1 1 5 9 3 8 4 + 2 1 9 6 1 7 2 4 End Elements Begin Conditions AxisymmetricLineNormalLoadDiffOrderCondition2D3N