Exemple #1
0
class TestCookMembrane(KratosUnittest.TestCase):
    def setUp(self):
        self.print_output = False
        self.print_results = False

    def test_cook_membrane_2d(self):
        results_filename = "cook_membrane_test/cook_membrane_results.json"
        parameters_filename = "cook_membrane_test/cook_membrane_parameters.json"
        with open(parameters_filename, 'r') as parameter_file:
            parameters = KratosMultiphysics.Parameters(parameter_file.read())

        model = KratosMultiphysics.Model()
        simulation = StructuralMechanicsAnalysis(model, parameters)
        simulation.Run()

        # self._check_results(model_part, A, b)
        if self.print_results:
            self.__print_results(model, results_filename)
        if self.print_output:
            self.__post_process(
                model.GetModelPart(parameters["solver_settings"]
                                   ["model_part_name"].GetString()))
        self.__check_results(model, results_filename)

    def test_cook_membrane_incompressible_2d(self):
        results_filename = "cook_membrane_test/cook_membrane_incompressible_results.json"
        parameters_filename = "cook_membrane_test/cook_membrane_parameters.json"
        with open(parameters_filename, 'r') as parameter_file:
            parameters = KratosMultiphysics.Parameters(parameter_file.read())
        parameters["solver_settings"]["material_import_settings"][
            "materials_filename"].SetString(
                "cook_membrane_test/cook_membrane_incompressible_materials.json"
            )

        model = KratosMultiphysics.Model()
        simulation = StructuralMechanicsAnalysis(model, parameters)
        simulation.Run()

        # self._check_results(model_part, A, b)
        if self.print_results:
            self.__print_results(model, results_filename)
        if self.print_output:
            self.__post_process(
                model.GetModelPart(parameters["solver_settings"]
                                   ["model_part_name"].GetString()))
        self.__check_results(model, results_filename)

    def __print_results(self, model, results_filename):
        json_output_settings = KratosMultiphysics.Parameters(r"""
        {
            "output_variables": ["DISPLACEMENT_X","DISPLACEMENT_Y","VOLUMETRIC_STRAIN"],
            "output_file_name": "",
            "time_frequency": 0.00,
            "model_part_name": "cook_membrane.Parts_ResultsCheck"
        }""")
        json_output_settings["output_file_name"].SetString(results_filename)
        self.json_output = JsonOutputProcess(model, json_output_settings)
        self.json_output.ExecuteInitialize()
        self.json_output.ExecuteBeforeSolutionLoop()
        self.json_output.ExecuteFinalizeSolutionStep()

    def __check_results(self, model, results_filename):
        from_json_check_result_settings = KratosMultiphysics.Parameters(r"""
        {
            "check_variables": ["DISPLACEMENT_X","DISPLACEMENT_Y","VOLUMETRIC_STRAIN"],
            "input_file_name": "",
            "model_part_name": "cook_membrane.Parts_ResultsCheck"
        }""")
        from_json_check_result_settings["input_file_name"].SetString(
            results_filename)
        self.from_json_check_result = FromJsonCheckResultProcess(
            model, from_json_check_result_settings)
        self.from_json_check_result.ExecuteInitialize()
        self.from_json_check_result.ExecuteFinalizeSolutionStep()

    def __post_process(self, main_model_part, post_type="gid"):
        if post_type == "gid":
            self.gid_output = GiDOutputProcess(
                main_model_part, main_model_part.Name,
                KratosMultiphysics.Parameters(r"""
                {
                    "result_file_configuration" : {
                    "gidpost_flags": {
                        "GiDPostMode": "GiD_PostBinary",
                        "WriteDeformedMeshFlag": "WriteUndeformed",
                        "WriteConditionsFlag": "WriteConditions",
                        "MultiFileFlag": "SingleFile"
                    },
                    "nodal_results"       : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                    "gauss_point_results" : []
                    }
                }"""))

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()

        elif post_type == "vtk":
            vtk_output_parameters = KratosMultiphysics.Parameters(r"""
            {
                "model_part_name": "",
                "extrapolate_gauss_points": false,
                "nodal_solution_step_data_variables" : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                "gauss_point_variables": []
            }""")
            vtk_output_parameters["model_part_name"].SetString(
                main_model_part.Name)
            self.vtk_output_process = VtkOutputProcess(
                main_model_part.GetModel(), vtk_output_parameters)

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()
class TestCheckNormals(KratosUnittest.TestCase):
    def setUp(self):
        pass

    def _normal_check_process_tests(self,
                                    input_filename,
                                    custom_submodel_part=""):
        KM.Logger.GetDefaultOutput().SetSeverity(KM.Logger.Severity.WARNING)

        self.model = KM.Model()
        self.main_model_part = self.model.CreateModelPart("Main", 2)

        self.main_model_part.AddNodalSolutionStepVariable(KM.NORMAL)

        self.main_model_part.CloneTimeStep(1.01)

        KM.ModelPartIO(input_filename).ReadModelPart(self.main_model_part)

        if custom_submodel_part == "":
            KM.VariableUtils().SetFlag(
                KM.INTERFACE, True,
                self.main_model_part.GetSubModelPart(
                    "CONTACT_Contact_slave_Auto1").Nodes)
            KM.VariableUtils().SetFlag(
                KM.INTERFACE, True,
                self.main_model_part.GetSubModelPart(
                    "CONTACT_Contact_master_Auto1").Nodes)
        else:
            KM.VariableUtils().SetFlag(
                KM.INTERFACE, True,
                self.main_model_part.GetSubModelPart(
                    custom_submodel_part).Nodes)

        ## DEBUG
        #KM.ComputeNodesMeanNormalModelPart(self.main_model_part, True)

        # Check normals
        check_process = CSMA.NormalCheckProcess(self.main_model_part)
        check_process.Execute()

        ## DEBUG
        #self.__post_process()

        check_parameters = KM.Parameters("""
        {
            "check_variables"      : ["NORMAL"],
            "input_file_name"      : "",
            "model_part_name"      : "Main",
            "check_for_flag"       : "INTERFACE",
            "historical_value"     : true,
            "time_frequency"       : 0.0
        }
        """)

        check_parameters["input_file_name"].SetString(input_filename +
                                                      "_check_normal.json")

        check = from_json_check_result_process.FromJsonCheckResultProcess(
            self.model, check_parameters)
        check.ExecuteInitialize()
        check.ExecuteBeforeSolutionLoop()
        check.ExecuteFinalizeSolutionStep()

        #out_parameters = KM.Parameters("""
        #{
        #"output_variables"     : ["NORMAL"],
        #"output_file_name"     : "",
        #"model_part_name"      : "Main",
        #"check_for_flag"       : "INTERFACE",
        #"historical_value"     : true,
        #"time_frequency"       : 0.0
        #}
        #""")

        #out_parameters["output_file_name"].SetString(input_filename + "_check_normal.json")

        #out = json_output_process.JsonOutputProcess(self.model, out_parameters)
        #out.ExecuteInitialize()
        #out.ExecuteBeforeSolutionLoop()
        #out.ExecuteFinalizeSolutionStep()

    def test_check_normals(self):
        input_filename = os.path.dirname(os.path.realpath(
            __file__)) + "/auxiliar_files_for_python_unittest/inverted_normals"

        self._normal_check_process_tests(input_filename)

    def test_check_normals_quads(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/inverted_normals_quads"

        self._normal_check_process_tests(input_filename)

    def test_check_normals_s_shape(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/inverted_normals_s_shape"

        self._normal_check_process_tests(input_filename,
                                         "GENERIC_Contact_Auto1")

    def __post_process(self, debug="GiD"):
        if debug == "GiD":
            self.gid_output = GiDOutputProcess(
                self.main_model_part, "gid_output",
                KM.Parameters("""
                                            {
                                                "result_file_configuration" : {
                                                    "gidpost_flags": {
                                                        "GiDPostMode": "GiD_PostBinary",
                                                        "WriteDeformedMeshFlag": "WriteUndeformed",
                                                        "MultiFileFlag": "SingleFile"
                                                    },
                                                    "nodal_results"       : ["NORMAL"],
                                                    "nodal_nonhistorical_results": [],
                                                    "nodal_flags_results": ["INTERFACE"]
                                                }
                                            }
                                            """))

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()
        elif debug == "VTK":
            self.vtk_output_process = VtkOutputProcess(
                self.model,
                KM.Parameters("""{
                                                "model_part_name"                    : "Main",
                                                "nodal_solution_step_data_variables" : ["NORMAL"],
                                                "nodal_data_value_variables": [],
                                                "nodal_flags" : ["INTERFACE"]
                                            }
                                            """))

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()
class TestPatchTestSmallDisplacementMixedVolumetricStrain(
        KratosUnittest.TestCase):
    def setUp(self):
        self.tolerance = 1.0e-6
        self.print_output = True

    def _add_variables(self, ModelPart):
        ModelPart.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.VOLUMETRIC_STRAIN)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.VOLUME_ACCELERATION)
        ModelPart.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.REACTION_FLUX)

    def _apply_BCs(self, ModelPart, A, b):
        for node in ModelPart.Nodes:
            node.Fix(KratosMultiphysics.DISPLACEMENT_X)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Y)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Z)

            x_vec = KratosMultiphysics.Vector(3)
            x_vec[0] = node.X0
            x_vec[1] = node.Y0
            x_vec[2] = node.Z0

            u = A * x_vec
            u += b

            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT, 0, u)

    def _apply_material_properties(self, ModelPart, Dimension):
        # Define material properties
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.YOUNG_MODULUS,
                                              200.0e9)
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.POISSON_RATIO,
                                              0.4)
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.DENSITY, 1.0)

        # Define body force
        g = [0, 0, 0]
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.VOLUME_ACCELERATION, g)

        # Define constitutive law
        if (Dimension == 2):
            cons_law = StructuralMechanicsApplication.LinearElasticPlaneStrain2DLaw(
            )
        else:
            cons_law = StructuralMechanicsApplication.LinearElastic3DLaw()
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.CONSTITUTIVE_LAW, cons_law)

    def _apply_user_provided_material_properties(self, ModelPart, Dimension):
        # Define body force
        g = [0, 0, 0]
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.VOLUME_ACCELERATION, g)

        # Define constitutive law
        if (Dimension == 2):
            cons_law = StructuralMechanicsApplication.UserProvidedLinearElastic2DLaw(
            )
        else:
            cons_law = StructuralMechanicsApplication.UserProvidedLinearElastic3DLaw(
            )
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.CONSTITUTIVE_LAW, cons_law)

    def _define_movement(self, Dimension):
        if (Dimension == 2):
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3, 3)
            A[0, 0] = 1.0e-10
            A[0, 1] = 2.0e-10
            A[0, 2] = 0.0
            A[1, 0] = 0.5e-10
            A[1, 1] = 0.7e-10
            A[1, 2] = 0.0
            A[2, 0] = 0.0
            A[2, 1] = 0.0
            A[2, 2] = 0.0

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.0
        else:
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3, 3)
            A[0, 0] = 1.0e-10
            A[0, 1] = 2.0e-10
            A[0, 2] = 0.0
            A[1, 0] = 0.5e-10
            A[1, 1] = 0.7e-10
            A[1, 2] = 0.1e-10
            A[2, 0] = -0.2e-10
            A[2, 1] = 0.0
            A[2, 2] = -0.3e-10

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.7e-10

        return A, b

    def _solve(self, ModelPart):
        # Define a linear strategy to solve the problem
        linear_solver = KratosMultiphysics.SkylineLUFactorizationSolver()
        builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(
            linear_solver)
        scheme = KratosMultiphysics.ResidualBasedIncrementalUpdateStaticScheme(
        )
        compute_reactions = True
        reform_step_dofs = True
        calculate_norm_dx = False
        move_mesh_flag = True

        strategy = KratosMultiphysics.ResidualBasedLinearStrategy(
            ModelPart, scheme, builder_and_solver, compute_reactions,
            reform_step_dofs, calculate_norm_dx, move_mesh_flag)
        strategy.SetEchoLevel(0)
        strategy.Check()

        # Solve the problem
        strategy.Solve()

    def _check_results(self, ModelPart, A, b):
        # Check that the results are exact on  the nodes
        for node in ModelPart.Nodes:
            x_vec = KratosMultiphysics.Vector(3)
            x_vec[0] = node.X0
            x_vec[1] = node.Y0
            x_vec[2] = node.Z0

            u = A * x_vec
            u += b

            coor_list = ["X", "Y", "Z"]

            d = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT)
            for i in range(3):
                if abs(u[i]) > 0.0:
                    error = (d[i] - u[i]) / u[i]
                    if error > self.tolerance:
                        print("NODE ", node.Id, ": Component ", coor_list[i],
                              ":\t", u[i], "\t", d[i], "\tError: ", error)
                    self.assertLess(error, self.tolerance)

    def _calculate_reference_strain(self, A, dim):
        # Given the matrix A, the analytic deformation gradient is F+I
        F = A
        for i in range(3):
            F[i, i] += 1.0

        # Here compute the Cauchy Green strain tensor
        cauchy_green_strain_tensor = KratosMultiphysics.Matrix(3, 3)

        for i in range(3):
            for j in range(3):
                cauchy_green_strain_tensor[i, j] = 0.0

        for i in range(3):
            for j in range(3):
                for k in range(3):
                    cauchy_green_strain_tensor[i, j] += F[k, i] * F[k, j]

        for i in range(3):
            cauchy_green_strain_tensor[i, i] -= 1.0

        for i in range(3):
            for j in range(3):
                cauchy_green_strain_tensor[
                    i, j] = 0.5 * cauchy_green_strain_tensor[i, j]

        # Cauchy Green strain tensor in Voigt notation
        if (dim == 2):
            reference_strain = KratosMultiphysics.Vector(3)
            reference_strain[0] = cauchy_green_strain_tensor[0, 0]
            reference_strain[1] = cauchy_green_strain_tensor[1, 1]
            reference_strain[2] = 2.0 * cauchy_green_strain_tensor[0, 1]
        else:
            reference_strain = KratosMultiphysics.Vector(6)
            reference_strain[0] = cauchy_green_strain_tensor[0, 0]
            reference_strain[1] = cauchy_green_strain_tensor[1, 1]
            reference_strain[2] = cauchy_green_strain_tensor[2, 2]
            reference_strain[3] = 2.0 * cauchy_green_strain_tensor[0, 1]
            reference_strain[4] = 2.0 * cauchy_green_strain_tensor[1, 2]
            reference_strain[5] = 2.0 * cauchy_green_strain_tensor[0, 2]

        return reference_strain

    def _check_stress(self, model_part, A, dim):
        # Calculate the reference strain
        reference_strain = self._calculate_reference_strain(A, dim)

        young = model_part.GetProperties()[1].GetValue(
            KratosMultiphysics.YOUNG_MODULUS)
        poisson = model_part.GetProperties()[1].GetValue(
            KratosMultiphysics.POISSON_RATIO)

        # Finally compute stress
        if (dim == 2):
            #here assume plane stress
            c1 = young / (1.00 - poisson * poisson)
            c2 = c1 * poisson
            c3 = 0.5 * young / (1 + poisson)
            reference_stress = KratosMultiphysics.Vector(3)
            reference_stress[0] = c1 * reference_strain[0] + c2 * (
                reference_strain[1])
            reference_stress[1] = c1 * reference_strain[1] + c2 * (
                reference_strain[0])
            reference_stress[2] = c3 * reference_strain[2]
        else:
            c1 = young / ((1.00 + poisson) * (1 - 2 * poisson))
            c2 = c1 * (1 - poisson)
            c3 = c1 * poisson
            c4 = c1 * 0.5 * (1 - 2 * poisson)
            reference_stress = KratosMultiphysics.Vector(6)
            reference_stress[0] = c2 * reference_strain[0] + c3 * (
                reference_strain[1] + reference_strain[2])
            reference_stress[1] = c2 * reference_strain[1] + c3 * (
                reference_strain[0] + reference_strain[2])
            reference_stress[2] = c2 * reference_strain[2] + c3 * (
                reference_strain[0] + reference_strain[1])
            reference_stress[3] = c4 * reference_strain[3]
            reference_stress[4] = c4 * reference_strain[4]
            reference_stress[5] = c4 * reference_strain[5]

        for elem in model_part.Elements:
            out = elem.CalculateOnIntegrationPoints(
                KratosMultiphysics.PK2_STRESS_VECTOR, model_part.ProcessInfo)
            for stress in out:
                for i in range(len(reference_stress)):
                    if abs(stress[i]) > 0.0:
                        self.assertLess(
                            (reference_stress[i] - stress[i]) / stress[i],
                            self.tolerance)

    def _check_stress_user_provided(self, model_part, A, dim):
        # Calculate the reference strain
        reference_strain = self._calculate_reference_strain(A, dim)

        # Finally compute stress
        elasticity_tensor = model_part.GetProperties()[1].GetValue(
            StructuralMechanicsApplication.ELASTICITY_TENSOR)
        reference_stress = elasticity_tensor * reference_strain

        for elem in model_part.Elements:
            out = elem.CalculateOnIntegrationPoints(
                KratosMultiphysics.PK2_STRESS_VECTOR, model_part.ProcessInfo)
            for stress in out:
                for i in range(len(reference_stress)):
                    if abs(stress[i]) > 0.0:
                        self.assertLess(
                            (reference_stress[i] - stress[i]) / stress[i],
                            self.tolerance)

    def testSmallDisplacementMixedVolumetricStrainElement2DTriangle(self):
        dimension = 2
        current_model = KratosMultiphysics.Model()
        model_part = current_model.CreateModelPart("MainModelPartTriangle")
        self._add_variables(model_part)
        self._apply_material_properties(model_part, dimension)

        # Create nodes
        model_part.CreateNewNode(1, 0.5, 0.5, 0.0)
        model_part.CreateNewNode(2, 0.7, 0.2, 0.0)
        model_part.CreateNewNode(3, 0.9, 0.8, 0.0)
        model_part.CreateNewNode(4, 0.3, 0.7, 0.0)
        model_part.CreateNewNode(5, 0.6, 0.6, 0.0)

        # Add DOFs
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.VOLUMETRIC_STRAIN,
            KratosMultiphysics.REACTION_FLUX, model_part)

        # Create a submodelpart for boundary conditions
        boundary_model_part = model_part.CreateSubModelPart(
            "BoundaryCondtions")
        boundary_model_part.AddNodes([1, 2, 3, 4])

        # Create elements
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 1, [1, 2, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 2, [2, 3, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 3, [3, 4, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 4, [4, 1, 5],
            model_part.GetProperties()[1])

        A, b = self._define_movement(dimension)

        self._apply_BCs(boundary_model_part, A, b)
        self._solve(model_part)
        self._check_results(model_part, A, b)
        self._check_stress(model_part, A, dimension)
        if self.print_output:
            self.__post_process(model_part)

    def testSmallDisplacementMixedVolumetricStrainElement3DTetrahedra(self):
        dimension = 3
        current_model = KratosMultiphysics.Model()
        model_part = current_model.CreateModelPart("MainModelPartTetrahedra")
        self._add_variables(model_part)
        self._apply_material_properties(model_part, dimension)

        #create nodes
        model_part.CreateNewNode(1, 0.0, 1.0, 0.0)
        model_part.CreateNewNode(2, 0.0, 1.0, 0.1)
        model_part.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405,
                                 0.05672979583333333)
        model_part.CreateNewNode(4, 0.0, 0.1, 0.0)
        model_part.CreateNewNode(5, 0.1, 0.1, 0.1)
        model_part.CreateNewNode(6, 1.0, 0.0, 0.0)
        model_part.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.VOLUMETRIC_STRAIN,
            KratosMultiphysics.REACTION_FLUX, model_part)

        #create a submodelpart for boundary conditions
        boundary_model_part = model_part.CreateSubModelPart(
            "BoundaryCondtions")
        boundary_model_part.AddNodes([1, 2, 4, 5, 6, 7])

        #create Element
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 1,
            [5, 3, 1, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 2,
            [3, 1, 2, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 3,
            [6, 4, 7, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 4,
            [5, 4, 1, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 5,
            [4, 1, 3, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 6,
            [5, 4, 3, 7],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 7,
            [3, 5, 7, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 8,
            [6, 7, 2, 3],
            model_part.GetProperties()[1])

        A, b = self._define_movement(dimension)

        self._apply_BCs(boundary_model_part, A, b)
        self._solve(model_part)
        self._check_results(model_part, A, b)
        self._check_stress(model_part, A, dimension)
        if self.print_output:
            self.__post_process(model_part)

    def testSmallDisplacementMixedVolumetricStrainElement3DTetrahedraAnisotropic(
            self):
        dimension = 3
        current_model = KratosMultiphysics.Model()
        model_part = current_model.CreateModelPart("MainModelPartTetrahedra")
        self._add_variables(model_part)
        self._apply_user_provided_material_properties(model_part, dimension)

        #set the user-provided anisotropic elasticity tensor
        elasticity_tensor = KratosMultiphysics.Matrix(6, 6)
        # for i in range(6):
        #     for j in range(6):
        #         elasticity_tensor[i,j] = 0.0
        # E = 2.0e11
        # NU = 0.3
        # c1 = E / (( 1.00 + NU ) * ( 1 - 2 * NU ) );
        # c2 = c1 * ( 1 - NU );
        # c3 = c1 * NU;
        # c4 = c1 * 0.5 * ( 1 - 2 * NU );
        # elasticity_tensor[0, 0] = c2;
        # elasticity_tensor[0, 1] = c3;
        # elasticity_tensor[0, 2] = c3;
        # elasticity_tensor[1, 0] = c3;
        # elasticity_tensor[1, 1] = c2;
        # elasticity_tensor[1, 2] = c3;
        # elasticity_tensor[2, 0] = c3;
        # elasticity_tensor[2, 1] = c3;
        # elasticity_tensor[2, 2] = c2;
        # elasticity_tensor[3, 3] = c4;
        # elasticity_tensor[4, 4] = c4;
        # elasticity_tensor[5, 5] = c4;
        aux_elasticity_tensor = [
            [5.99E+11, 5.57E+11, 5.34E+11, 0, 0, 4.44E+09],
            [5.57E+11, 5.71E+11, 5.34E+11, 0, 0, -3.00E+09],
            [5.34E+11, 5.34E+11, 5.37E+11, 0, 0, 9.90E+05],
            [0, 0, 0, 1.92E+09, 9.78E+06, 0], [0, 0, 0, 9.78E+06, 2.12E+09, 0],
            [4.44E+09, -3.00E+09, 9.90E+05, 0, 0, 2.56E+10]
        ]
        for i in range(6):
            for j in range(6):
                elasticity_tensor[i, j] = aux_elasticity_tensor[i][j]

        # T = KratosMultiphysics.Matrix(6,6)
        # T.fill(0.0)
        # aux_E = 0.0
        # aux_G = 0.0
        # for i in range(6):
        #     if i < 3:
        #         aux_E += elasticity_tensor[i,i]
        #     else:
        #         aux_G += elasticity_tensor[i,i]
        # aux_E /= 3.0
        # aux_G /= 3.0
        # for i in range(6):
        #     if i < 3:
        #         T[i,i] = math.sqrt(aux_E/elasticity_tensor[i,i])
        #     else:
        #         T[i,i] = math.sqrt(aux_G/elasticity_tensor[i,i])

        # elasticity_tensor = T * elasticity_tensor * T

        model_part.GetProperties()[1].SetValue(
            StructuralMechanicsApplication.ELASTICITY_TENSOR,
            elasticity_tensor)

        #create nodes
        model_part.CreateNewNode(1, 0.0, 1.0, 0.0)
        model_part.CreateNewNode(2, 0.0, 1.0, 0.1)
        model_part.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405,
                                 0.05672979583333333)
        model_part.CreateNewNode(4, 0.0, 0.1, 0.0)
        model_part.CreateNewNode(5, 0.1, 0.1, 0.1)
        model_part.CreateNewNode(6, 1.0, 0.0, 0.0)
        model_part.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.VOLUMETRIC_STRAIN,
            KratosMultiphysics.REACTION_FLUX, model_part)

        #create a submodelpart for boundary conditions
        boundary_model_part = model_part.CreateSubModelPart(
            "BoundaryCondtions")
        boundary_model_part.AddNodes([1, 2, 4, 5, 6, 7])

        #create Element
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 1,
            [5, 3, 1, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 2,
            [3, 1, 2, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 3,
            [6, 4, 7, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 4,
            [5, 4, 1, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 5,
            [4, 1, 3, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 6,
            [5, 4, 3, 7],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 7,
            [3, 5, 7, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 8,
            [6, 7, 2, 3],
            model_part.GetProperties()[1])

        A, b = self._define_movement(dimension)

        self._apply_BCs(boundary_model_part, A, b)
        self._solve(model_part)
        if self.print_output:
            self.__post_process(model_part)
        self._check_results(model_part, A, b)
        self._check_stress_user_provided(model_part, A, dimension)

    def __post_process(self, main_model_part, post_type="gid"):
        if post_type == "gid":
            self.gid_output = GiDOutputProcess(
                main_model_part, main_model_part.Name,
                KratosMultiphysics.Parameters(r"""
                {
                    "result_file_configuration" : {
                    "gidpost_flags": {
                        "GiDPostMode": "GiD_PostBinary",
                        "WriteDeformedMeshFlag": "WriteUndeformed",
                        "WriteConditionsFlag": "WriteConditions",
                        "MultiFileFlag": "SingleFile"
                    },
                    "nodal_results"       : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                    "gauss_point_results" : ["CAUCHY_STRESS_VECTOR"]
                    }
                }"""))

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()

        elif post_type == "vtk":
            vtk_output_parameters = KratosMultiphysics.Parameters(r"""
            {
                "model_part_name": "",
                "extrapolate_gauss_points": false,
                "nodal_solution_step_data_variables" : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                "gauss_point_variables": ["CAUCHY_STRESS_VECTOR"]
            }""")
            vtk_output_parameters["model_part_name"].SetString(
                main_model_part.Name)
            self.vtk_output_process = VtkOutputProcess(
                main_model_part.GetModel(), vtk_output_parameters)

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()
class TestPatchTestSmallStrain(KratosUnittest.TestCase):
    def setUp(self):
        pass

    def _add_variables(self,mp):
        mp.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT)
        mp.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION)
        mp.AddNodalSolutionStepVariable(KratosMultiphysics.VOLUME_ACCELERATION)


    def _apply_BCs(self,mp,A,b):
        for node in mp.Nodes:
            node.Fix(KratosMultiphysics.DISPLACEMENT_X)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Y)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Z)

        for node in mp.Nodes:
            xvec = KratosMultiphysics.Vector(3)
            xvec[0] = node.X0
            xvec[1] = node.Y0
            xvec[2] = node.Z0

            u = A*xvec
            u += b

            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,0,u)

    def _apply_material_properties(self,mp,dim):
        #define properties
        mp.GetProperties()[1].SetValue(KratosMultiphysics.YOUNG_MODULUS,210e9)
        mp.GetProperties()[1].SetValue(KratosMultiphysics.POISSON_RATIO,0.3)
        mp.GetProperties()[1].SetValue(KratosMultiphysics.THICKNESS,1.0)
        mp.GetProperties()[1].SetValue(KratosMultiphysics.DENSITY,1.0)
        #mp.GetProperties()[1].SetValue(StructuralMechanicsApplication.INTEGRATION_ORDER,5)

        g = [0,0,0]
        mp.GetProperties()[1].SetValue(KratosMultiphysics.VOLUME_ACCELERATION,g)

        if(dim == 2):
            cl = StructuralMechanicsApplication.LinearElasticPlaneStress2DLaw()
        else:
            cl = StructuralMechanicsApplication.LinearElastic3DLaw()
        mp.GetProperties()[1].SetValue(KratosMultiphysics.CONSTITUTIVE_LAW,cl)

    def _define_movement(self,dim):
        if(dim == 2):
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3,3)
            A[0,0] = 1.0e-10;  A[0,1] = 2.0e-10; A[0,2] = 0.0
            A[1,0] = 0.5e-10;  A[1,1] = 0.7e-10; A[1,2] = 0.0
            A[2,0] = 0.0;      A[2,1] = 0.0;     A[2,2] = 0.0

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.0

        else:
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3,3)
            A[0,0] = 1.0e-10;   A[0,1] = 2.0e-10; A[0,2] = 0.0
            A[1,0] = 0.5e-10;   A[1,1] = 0.7e-10; A[1,2] = 0.1e-10
            A[2,0] = -0.2e-10;  A[2,1] = 0.0;     A[2,2] = -0.3e-10

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.7e-10



        return A,b

    def _solve(self,mp):

        #define a minimal newton raphson solver
        linear_solver = KratosMultiphysics.SkylineLUFactorizationSolver()
        builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(linear_solver)
        scheme = KratosMultiphysics.ResidualBasedIncrementalUpdateStaticScheme()
        convergence_criterion = KratosMultiphysics.ResidualCriteria(1e-14,1e-20)

        max_iters = 20
        compute_reactions = True
        reform_step_dofs = True
        calculate_norm_dx = False
        move_mesh_flag = True
        strategy = KratosMultiphysics.ResidualBasedLinearStrategy(mp,
                                                                        scheme,
                                                                        linear_solver,
                                                                        builder_and_solver,
                                                                        compute_reactions,
                                                                        reform_step_dofs,
                                                                        calculate_norm_dx,
                                                                        move_mesh_flag)


        #strategy = KratosMultiphysics.ResidualBasedNewtonRaphsonStrategy(mp,
                                                                        #scheme,
                                                                        #linear_solver,
                                                                        #convergence_criterion,
                                                                        #builder_and_solver,
                                                                        #max_iters,
                                                                        #compute_reactions,
                                                                        #reform_step_dofs,
                                                                        #move_mesh_flag)
        strategy.SetEchoLevel(0)

        strategy.Initialize()
        strategy.Check()
        strategy.Solve()


    def _check_results(self,mp,A,b):

        ##check that the results are exact on the nodes
        for node in mp.Nodes:
            xvec = KratosMultiphysics.Vector(3)
            xvec[0] = node.X0
            xvec[1] = node.Y0
            xvec[2] = node.Z0

            u = A*xvec
            u += b

            coor_list = ["X","Y","Z"]

            d = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT)
            for i in range(3):
                if abs(u[i]) > 0.0:
                    error = (d[i] - u[i])/u[i]
                    if error > 1.0e-6:
                       print("NODE ", node.Id,": Component ", coor_list[i],":\t",u[i],"\t",d[i], "\tError: ", error)
                    self.assertLess(error, 1.0e-6)

    def _check_outputs(self,mp,A,dim):

        E = mp.GetProperties()[1].GetValue(KratosMultiphysics.YOUNG_MODULUS)
        NU =mp.GetProperties()[1].GetValue(KratosMultiphysics.POISSON_RATIO)

        # Given the matrix A, the analytic deformation gradient is F+I
        F = A
        for i in range(3):
            F[i,i] += 1.0

        # Here compute the Cauchy green strain tensor
        Etensor = KratosMultiphysics.Matrix(3,3)

        for i in range(3):
            for j in range(3):
                Etensor[i,j] = 0.0

        for i in range(3):
            for j in range(3):
                for k in range(3):
                    Etensor[i,j] += F[k,i]*F[k,j]

        for i in range(3):
            Etensor[i,i] -= 1.0

        for i in range(3):
            for j in range(3):
                Etensor[i,j] = 0.5*Etensor[i,j]

        # Verify strain
        if(dim == 2):
            reference_strain = KratosMultiphysics.Vector(3)
            reference_strain[0] = Etensor[0,0]
            reference_strain[1] = Etensor[1,1]
            reference_strain[2] = 2.0*Etensor[0,1]
        else:
            reference_strain = KratosMultiphysics.Vector(6)
            reference_strain[0] = Etensor[0,0]
            reference_strain[1] = Etensor[1,1]
            reference_strain[2] = Etensor[2,2]
            reference_strain[3] = 2.0*Etensor[0,1]
            reference_strain[4] = 2.0*Etensor[1,2]
            reference_strain[5] = 2.0*Etensor[0,2]

        for elem in mp.Elements:
            out = elem.CalculateOnIntegrationPoints(KratosMultiphysics.GREEN_LAGRANGE_STRAIN_VECTOR, mp.ProcessInfo)
            for strain in out:
                for i in range(len(reference_strain)):
                    if abs(strain[i]) > 0.0:
                        self.assertLess((reference_strain[i] - strain[i])/strain[i], 1.0e-6)

        # Finally compute stress
        if(dim == 2):
            #here assume plane stress
            c1 = E / (1.00 - NU*NU)
            c2 = c1 * NU
            c3 = 0.5* E / (1 + NU)
            reference_stress = KratosMultiphysics.Vector(3)
            reference_stress[0] = c1*reference_strain[0] + c2 * (reference_strain[1])
            reference_stress[1] = c1*reference_strain[1] + c2 * (reference_strain[0])
            reference_stress[2] = c3*reference_strain[2]
        else:
            c1 = E / (( 1.00 + NU ) * ( 1 - 2 * NU ) )
            c2 = c1 * ( 1 - NU )
            c3 = c1 * NU
            c4 = c1 * 0.5 * ( 1 - 2 * NU )
            reference_stress = KratosMultiphysics.Vector(6)
            reference_stress[0] = c2*reference_strain[0] + c3 * (reference_strain[1] + reference_strain[2])
            reference_stress[1] = c2*reference_strain[1] + c3 * (reference_strain[0] + reference_strain[2])
            reference_stress[2] = c2*reference_strain[2] + c3 * (reference_strain[0] + reference_strain[1])
            reference_stress[3] = c4*reference_strain[3]
            reference_stress[4] = c4*reference_strain[4]
            reference_stress[5] = c4*reference_strain[5]

        for elem in mp.Elements:
            out = elem.CalculateOnIntegrationPoints(KratosMultiphysics.PK2_STRESS_VECTOR, mp.ProcessInfo)
            for stress in out:
                for i in range(len(reference_stress)):
                    if abs(stress[i]) > 0.0:
                        self.assertLess((reference_stress[i] - stress[i])/stress[i], 1.0e-6)

    def test_SmallDisplacementElement_2D_triangle(self):
        dim = 2
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        #create nodes
        mp.CreateNewNode(1,0.5,0.5,0.0)
        mp.CreateNewNode(2,0.7,0.2,0.0)
        mp.CreateNewNode(3,0.9,0.8,0.0)
        mp.CreateNewNode(4,0.3,0.7,0.0)
        mp.CreateNewNode(5,0.6,0.6,0.0)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,2,3,4])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement2D3N", 1, [1,2,5], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D3N", 2, [2,3,5], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D3N", 3, [3,4,5], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D3N", 4, [4,1,5], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        # Checking consistent mass matrix
        M = KratosMultiphysics.Matrix(0,0)
        mp.Elements[1].CalculateMassMatrix(M,mp.ProcessInfo)
        Area = mp.Elements[1].GetGeometry().Area()
        for i in range(3):
            for j in range(3):
                for k in range(dim):
                    if(i==j):
                        coeff = Area/6.0
                    else:
                        coeff = Area/12.0
                    self.assertAlmostEqual(M[i*dim+k,j*dim+k],coeff)
        mp.Elements[1].SetValue(StructuralMechanicsApplication.MASS_FACTOR, 2.0)
        mp.Elements[1].CalculateMassMatrix(M,mp.ProcessInfo)
        for i in range(3):
            for j in range(3):
                for k in range(dim):
                    if(i==j):
                        coeff = Area/3.0
                    else:
                        coeff = Area/6.0
                    self.assertAlmostEqual(M[i*dim+k,j*dim+k],coeff)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_2D_quadrilateral(self):
        dim = 2
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        #create nodes
        mp.CreateNewNode(1,0.00,3.00,0.00)
        mp.CreateNewNode(2,1.00,2.25,0.00)
        mp.CreateNewNode(3,0.75,1.00,0.00)
        mp.CreateNewNode(4,2.25,2.00,0.00)
        mp.CreateNewNode(5,0.00,0.00,0.00)
        mp.CreateNewNode(6,3.00,3.00,0.00)
        mp.CreateNewNode(7,2.00,0.75,0.00)
        mp.CreateNewNode(8,3.00,0.00,0.00)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,5,6,8])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement2D4N", 1, [8,7,3,5], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D4N", 2, [6,4,7,8], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D4N", 3, [1,2,4,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D4N", 4, [4,2,3,7], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D4N", 5, [2,1,5,3], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_2D_quadratic_quadrilateral(self):
        dim = 2
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        # Create nodes
        mp.CreateNewNode(1, 2.0000000000, 1.0000000000, 0.0000000000)
        mp.CreateNewNode(2, 1.8333333333, 0.8333333333, 0.0000000000)
        mp.CreateNewNode(3, 1.7500000000, 0.9166666667, 0.0000000000)
        mp.CreateNewNode(4, 1.6501412600, 0.7903466431, 0.0000000000)
        mp.CreateNewNode(5, 1.6666666667, 0.6666666667, 0.0000000000)
        mp.CreateNewNode(6, 1.5000000000, 0.8333333333, 0.0000000000)
        mp.CreateNewNode(7, 1.5502825201, 0.6640266196, 0.0000000000)
        mp.CreateNewNode(8, 1.4669491867, 0.7473599529, 0.0000000000)
        mp.CreateNewNode(9, 1.4338983735, 0.6613865725, 0.0000000000)
        mp.CreateNewNode(10, 1.5000000000, 0.5000000000, 0.0000000000)
        mp.CreateNewNode(11, 1.3930628337, 0.5373333663, 0.0000000000)
        mp.CreateNewNode(12, 1.2500000000, 0.7500000000, 0.0000000000)
        mp.CreateNewNode(13, 1.2680628337, 0.6623333663, 0.0000000000)
        mp.CreateNewNode(14, 1.2861256675, 0.5746667326, 0.0000000000)
        mp.CreateNewNode(15, 1.3333333333, 0.3333333333, 0.0000000000)
        mp.CreateNewNode(16, 1.2358431474, 0.4106401130, 0.0000000000)
        mp.CreateNewNode(17, 1.1383529614, 0.4879468926, 0.0000000000)
        mp.CreateNewNode(18, 1.0691764807, 0.5773067797, 0.0000000000)
        mp.CreateNewNode(19, 1.0000000000, 0.6666666667, 0.0000000000)
        mp.CreateNewNode(20, 1.1666666667, 0.1666666667, 0.0000000000)
        mp.CreateNewNode(21, 1.0644666084, 0.2779203060, 0.0000000000)
        mp.CreateNewNode(22, 0.9622665502, 0.3891739453, 0.0000000000)
        mp.CreateNewNode(23, 0.8561332751, 0.4862536393, 0.0000000000)
        mp.CreateNewNode(24, 0.7500000000, 0.5833333333, 0.0000000000)
        mp.CreateNewNode(25, 0.8930900695, 0.1452004990, 0.0000000000)
        mp.CreateNewNode(26, 0.7861801389, 0.2904009980, 0.0000000000)
        mp.CreateNewNode(27, 1.0000000000, 0.0000000000, 0.0000000000)
        mp.CreateNewNode(28, 0.6430900695, 0.3952004990, 0.0000000000)
        mp.CreateNewNode(29, 0.6479361204, 0.2339226363, 0.0000000000)
        mp.CreateNewNode(30, 0.6989680602, 0.1169613182, 0.0000000000)
        mp.CreateNewNode(31, 0.5000000000, 0.5000000000, 0.0000000000)
        mp.CreateNewNode(32, 0.7500000000, 0.0000000000, 0.0000000000)
        mp.CreateNewNode(33, 0.5114680602, 0.3044613182, 0.0000000000)
        mp.CreateNewNode(34, 0.5096921019, 0.1774442747, 0.0000000000)
        mp.CreateNewNode(35, 0.3750000000, 0.3750000000, 0.0000000000)
        mp.CreateNewNode(36, 0.5048460509, 0.0887221373, 0.0000000000)
        mp.CreateNewNode(37, 0.3798460509, 0.2137221373, 0.0000000000)
        mp.CreateNewNode(38, 0.5000000000, 0.0000000000, 0.0000000000)
        mp.CreateNewNode(39, 0.2500000000, 0.2500000000, 0.0000000000)
        mp.CreateNewNode(40, 0.3149230255, 0.1068610687, 0.0000000000)
        mp.CreateNewNode(41, 0.2500000000, 0.0000000000, 0.0000000000)
        mp.CreateNewNode(42, 0.1250000000, 0.1250000000, 0.0000000000)
        mp.CreateNewNode(43, 0.0000000000, 0.0000000000, 0.0000000000)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1, 2, 3, 5, 6, 10, 12, 15, 19, 20, 24, 27, 31, 32, 35, 38, 39, 41, 42, 43])

        # Create Element
        mp.CreateNewElement("SmallDisplacementElement2D9N", 1, [ 39, 43, 38, 34, 42, 41, 36, 37, 40 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 2, [ 31, 39, 34, 26, 35, 37, 29, 28, 33 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 3, [ 34, 38, 27, 26, 36, 32, 25, 29, 30 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 4, [  5,  1,  6,  9,  2,  3,  8,  7,  4 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 5, [ 27, 15, 17, 26, 20, 16, 22, 25, 21 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 6, [ 31, 26, 17, 19, 28, 22, 18, 24, 23 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 7, [ 15,  5,  9, 17, 10,  7, 14, 16, 11 ], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement2D9N", 8, [ 19, 17,  9,  6, 18, 14,  8, 12, 13 ], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_3D_tetra(self):
        dim = 3
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        #create nodes
        mp.CreateNewNode(1,0.0, 1.0, 0.0)
        mp.CreateNewNode(2,0.0, 1.0, 0.1)
        mp.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405, 0.05672979583333333)
        mp.CreateNewNode(4, 0.0, 0.1, 0.0)
        mp.CreateNewNode(5, 0.1, 0.1, 0.1)
        mp.CreateNewNode(6, 1.0, 0.0, 0.0)
        mp.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,2,4,5,6,7])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement3D4N", 1,[5,3,1,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 2,[3,1,2,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 3,[6,4,7,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 4,[5,4,1,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 5,[4,1,3,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 6,[5,4,3,7], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 7,[3,5,7,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 8,[6,7,2,3], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_3D_tetra_user_provided_elasticity(self):
        dim = 3
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)

        #set the user-provided elasticity tensor
        E = 200e+9
        nu = 0.3
        c1 = E / ((1.00+nu) * (1-2*nu))
        c2 = c1 * (1-nu)
        c3 = c1 * nu
        c4 = c1 * 0.5 * (1-2*nu)
        elasticity_tensor = KratosMultiphysics.Matrix(6,6)
        for i in range(6):
            for j in range(6):
                elasticity_tensor[i,j] = 0.0
        elasticity_tensor[0, 0] = c2
        elasticity_tensor[0, 1] = c3
        elasticity_tensor[0, 2] = c3
        elasticity_tensor[1, 0] = c3
        elasticity_tensor[1, 1] = c2
        elasticity_tensor[1, 2] = c3
        elasticity_tensor[2, 0] = c3
        elasticity_tensor[2, 1] = c3
        elasticity_tensor[2, 2] = c2
        elasticity_tensor[3, 3] = c4
        elasticity_tensor[4, 4] = c4
        elasticity_tensor[5, 5] = c4

        #apply isotropic user-provided material properties
        claw = StructuralMechanicsApplication.UserProvidedLinearElastic3DLaw()
        mp.GetProperties()[1].SetValue(KratosMultiphysics.CONSTITUTIVE_LAW, claw)
        mp.GetProperties()[1].SetValue(StructuralMechanicsApplication.ELASTICITY_TENSOR, elasticity_tensor)

        #create nodes
        mp.CreateNewNode(1,0.0, 1.0, 0.0)
        mp.CreateNewNode(2,0.0, 1.0, 0.1)
        mp.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405, 0.05672979583333333)
        mp.CreateNewNode(4, 0.0, 0.1, 0.0)
        mp.CreateNewNode(5, 0.1, 0.1, 0.1)
        mp.CreateNewNode(6, 1.0, 0.0, 0.0)
        mp.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,2,4,5,6,7])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement3D4N", 1,[5,3,1,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 2,[3,1,2,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 3,[6,4,7,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 4,[5,4,1,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 5,[4,1,3,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 6,[5,4,3,7], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 7,[3,5,7,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 8,[6,7,2,3], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_3D_tetra_user_provided_elasticity_anisotropic(self):
        dim = 3
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)

        #set the user-provided anisotropic elasticity tensor
        elasticity_tensor = KratosMultiphysics.Matrix(6,6)
        aux_elasticity_tensor = [
            [5.99E+11,5.57E+11,5.34E+11,0,0,4.44E+09],
            [5.57E+11,5.71E+11,5.34E+11,0,0,-3.00E+09],
            [5.34E+11,5.34E+11,5.37E+11,0,0,9.90E+05],
            [0,0,0,1.92E+09,9.78E+06,0],
            [0,0,0,9.78E+06,2.12E+09,0],
            [4.44E+09,-3.00E+09,9.90E+05,0,0,2.56E+10]]
        for i in range(6):
            for j in range(6):
                elasticity_tensor[i,j] = aux_elasticity_tensor[i][j]

        #apply anisotropic user-provided material properties
        claw = StructuralMechanicsApplication.UserProvidedLinearElastic3DLaw()
        mp.GetProperties()[1].SetValue(KratosMultiphysics.CONSTITUTIVE_LAW, claw)
        mp.GetProperties()[1].SetValue(StructuralMechanicsApplication.ELASTICITY_TENSOR, elasticity_tensor)

        #create nodes
        mp.CreateNewNode(1,0.0, 1.0, 0.0)
        mp.CreateNewNode(2,0.0, 1.0, 0.1)
        mp.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405, 0.05672979583333333)
        mp.CreateNewNode(4, 0.0, 0.1, 0.0)
        mp.CreateNewNode(5, 0.1, 0.1, 0.1)
        mp.CreateNewNode(6, 1.0, 0.0, 0.0)
        mp.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,2,4,5,6,7])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement3D4N", 1,[5,3,1,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 2,[3,1,2,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 3,[6,4,7,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 4,[5,4,1,3], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 5,[4,1,3,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 6,[5,4,3,7], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 7,[3,5,7,2], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D4N", 8,[6,7,2,3], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_3D_prism(self):
        dim = 3
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        #create nodes
        mp.CreateNewNode(1,0.5,0.5,0.0)
        mp.CreateNewNode(2,0.7,0.2,0.0)
        mp.CreateNewNode(3,0.9,0.8,0.0)
        mp.CreateNewNode(4,0.3,0.7,0.0)
        mp.CreateNewNode(5,0.6,0.6,0.0)
        mp.CreateNewNode(6,0.5,0.5,0.1)
        mp.CreateNewNode(7,0.7,0.2,0.1)
        mp.CreateNewNode(8,0.9,0.8,0.1)
        mp.CreateNewNode(9,0.3,0.7,0.1)
        mp.CreateNewNode(10,0.6,0.6,0.1)
        mp.CreateNewNode(11,0.5,0.5,0.2)
        mp.CreateNewNode(12,0.7,0.2,0.2)
        mp.CreateNewNode(13,0.9,0.8,0.2)
        mp.CreateNewNode(14,0.3,0.7,0.2)
        mp.CreateNewNode(15,0.6,0.6,0.2)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,2,3,4,5,6,7,8,9,11,12,13,14,15])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement3D6N", 1, [1,2,5,6,7,10], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 2, [2,3,5,7,8,10], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 3, [3,4,5,8,9,10], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 4, [4,1,5,9,6,10], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 5, [6,7,10,11,12,15], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 6, [7,8,10,12,13,15], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 7, [8,9,10,13,14,15], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D6N", 8, [9,6,10,14,11,15], mp.GetProperties()[1])

        A,b = self._define_movement(dim)

        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

    def test_SmallDisplacementElement_3D_hexa(self):
        dim = 3
        current_model = KratosMultiphysics.Model()
        mp = current_model.CreateModelPart("solid_part")
        self._add_variables(mp)
        self._apply_material_properties(mp,dim)

        #create nodes
        mp.CreateNewNode(1, 0.00000,  1.00000,  1.00000)
        mp.CreateNewNode(2, 0.16500,  0.74500,  0.70200)
        mp.CreateNewNode(3, 0.27300,  0.75000,  0.23000)
        mp.CreateNewNode(4, 0.78800,  0.69300,  0.64400)
        mp.CreateNewNode(5, 0.32000,  0.18600,  0.64300)
        mp.CreateNewNode(6, 0.00000,  1.00000,  0.00000)
        mp.CreateNewNode(7, 0.00000,  0.00000,  1.00000)
        mp.CreateNewNode(8, 1.00000,  1.00000,  1.00000)
        mp.CreateNewNode(9, 0.67700,  0.30500,  0.68300)
        mp.CreateNewNode(10, 0.24900,  0.34200,  0.19200)
        mp.CreateNewNode(11, 0.85000,  0.64900,  0.26300)
        mp.CreateNewNode(12, 0.82600,  0.28800,  0.28800)
        mp.CreateNewNode(13, 0.00000,  0.00000,  0.00000)
        mp.CreateNewNode(14, 1.00000,  1.00000,  0.00000)
        mp.CreateNewNode(15, 1.00000,  0.00000,  1.00000)
        mp.CreateNewNode(16, 1.00000,  0.00000,  0.00000)

        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,mp)
        KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,mp)

        #create a submodelpart for boundary conditions
        bcs = mp.CreateSubModelPart("BoundaryCondtions")
        bcs.AddNodes([1,6,7,8,13,14,15,16])

        #create Element
        mp.CreateNewElement("SmallDisplacementElement3D8N", 1,[10,5,2,3,13,7,1,6], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 2,[12,9,5,10,16,15,7,13], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 3,[12,11,3,10,9,4,2,5], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 4,[9,4,2,5,15,8,1,7], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 5,[4,11,3,2,8,14,6,1], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 6,[11,4,9,12,14,8,15,16], mp.GetProperties()[1])
        mp.CreateNewElement("SmallDisplacementElement3D8N", 7,[11,12,10,3,14,16,13,6], mp.GetProperties()[1])

        A,b = self._define_movement(dim)
        self._apply_BCs(bcs,A,b)
        self._solve(mp)
        self._check_results(mp,A,b)
        self._check_outputs(mp,A,dim)

        #self.__post_process(mp)

        # Testing explicit utilities
        empty_param = KratosMultiphysics.Parameters("""{}""")
        max_delta_time = StructuralMechanicsApplication.CalculateDeltaTime(mp, empty_param)
        self.assertAlmostEqual(max_delta_time,4.1494033578614815e-07)

    def __post_process(self, main_model_part, post_type = "gid"):
        if post_type == "gid":
            self.gid_output = GiDOutputProcess(main_model_part,
                                        "gid_output",
                                        KratosMultiphysics.Parameters("""
                                            {
                                                "result_file_configuration" : {
                                                    "gidpost_flags": {
                                                        "GiDPostMode": "GiD_PostBinary",
                                                        "WriteDeformedMeshFlag": "WriteUndeformed",
                                                        "WriteConditionsFlag": "WriteConditions",
                                                        "MultiFileFlag": "SingleFile"
                                                    },
                                                    "nodal_results"       : ["DISPLACEMENT"],
                                                    "gauss_point_results" : ["GREEN_LAGRANGE_STRAIN_TENSOR","CAUCHY_STRESS_TENSOR","VON_MISES_STRESS"]
                                                }
                                            }
                                            """)
                                        )

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()
        elif post_type == "vtk":
            self.vtk_output_process = VtkOutputProcess(main_model_part.GetModel(),
                                        KratosMultiphysics.Parameters("""{
                                                "model_part_name"                    : "solid_part",
                                                "extrapolate_gauss_points"           : false,
                                                "nodal_solution_step_data_variables" : ["DISPLACEMENT"],
                                                "gauss_point_variables": ["VON_MISES_STRESS"]
                                            }
                                            """)
                                        )

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()
class TestPatchTestSmallDisplacementMixedVolumetricStrain(
        KratosUnittest.TestCase):
    def setUp(self):
        self.tolerance = 1.0e-6
        self.print_output = True

    def _add_variables(self, ModelPart):
        ModelPart.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.VOLUMETRIC_STRAIN)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.VOLUME_ACCELERATION)
        ModelPart.AddNodalSolutionStepVariable(KratosMultiphysics.REACTION)
        ModelPart.AddNodalSolutionStepVariable(
            KratosMultiphysics.REACTION_FLUX)

    def _apply_BCs(self, ModelPart, A, b):
        for node in ModelPart.Nodes:
            node.Fix(KratosMultiphysics.DISPLACEMENT_X)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Y)
            node.Fix(KratosMultiphysics.DISPLACEMENT_Z)

            x_vec = KratosMultiphysics.Vector(3)
            x_vec[0] = node.X0
            x_vec[1] = node.Y0
            x_vec[2] = node.Z0

            u = A * x_vec
            u += b

            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT, 0, u)

    def _apply_material_properties(self, ModelPart, Dimension):
        # Define material properties
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.YOUNG_MODULUS,
                                              200.0e9)
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.POISSON_RATIO,
                                              0.4)
        ModelPart.GetProperties()[1].SetValue(KratosMultiphysics.DENSITY, 1.0)

        # Define body force
        g = [0, 0, 0]
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.VOLUME_ACCELERATION, g)

        # Define constitutive law
        if (Dimension == 2):
            cons_law = StructuralMechanicsApplication.LinearElasticPlaneStrain2DLaw(
            )
        else:
            cons_law = StructuralMechanicsApplication.LinearElastic3DLaw()
        ModelPart.GetProperties()[1].SetValue(
            KratosMultiphysics.CONSTITUTIVE_LAW, cons_law)

    def _define_movement(self, Dimension):
        if (Dimension == 2):
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3, 3)
            A[0, 0] = 1.0e-10
            A[0, 1] = 2.0e-10
            A[0, 2] = 0.0
            A[1, 0] = 0.5e-10
            A[1, 1] = 0.7e-10
            A[1, 2] = 0.0
            A[2, 0] = 0.0
            A[2, 1] = 0.0
            A[2, 2] = 0.0

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.0
        else:
            #define the applied motion - the idea is that the displacement is defined as u = A*xnode + b
            #so that the displcement is linear and the exact F = I + A
            A = KratosMultiphysics.Matrix(3, 3)
            A[0, 0] = 1.0e-10
            A[0, 1] = 2.0e-10
            A[0, 2] = 0.0
            A[1, 0] = 0.5e-10
            A[1, 1] = 0.7e-10
            A[1, 2] = 0.1e-10
            A[2, 0] = -0.2e-10
            A[2, 1] = 0.0
            A[2, 2] = -0.3e-10

            b = KratosMultiphysics.Vector(3)
            b[0] = 0.5e-10
            b[1] = -0.2e-10
            b[2] = 0.7e-10

        return A, b

    def _solve(self, ModelPart):
        # Define a linear strategy to solve the problem
        linear_solver = KratosMultiphysics.SkylineLUFactorizationSolver()
        builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(
            linear_solver)
        scheme = KratosMultiphysics.ResidualBasedIncrementalUpdateStaticScheme(
        )
        compute_reactions = True
        reform_step_dofs = True
        calculate_norm_dx = False
        move_mesh_flag = True

        strategy = KratosMultiphysics.ResidualBasedLinearStrategy(
            ModelPart, scheme, linear_solver, builder_and_solver,
            compute_reactions, reform_step_dofs, calculate_norm_dx,
            move_mesh_flag)
        strategy.SetEchoLevel(0)
        strategy.Check()

        # Solve the problem
        strategy.Solve()

    def _check_results(self, ModelPart, A, b):
        # Check that the results are exact on  the nodes
        for node in ModelPart.Nodes:
            x_vec = KratosMultiphysics.Vector(3)
            x_vec[0] = node.X0
            x_vec[1] = node.Y0
            x_vec[2] = node.Z0

            u = A * x_vec
            u += b

            coor_list = ["X", "Y", "Z"]

            d = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT)
            for i in range(3):
                if abs(u[i]) > 0.0:
                    error = (d[i] - u[i]) / u[i]
                    if error > self.tolerance:
                        print("NODE ", node.Id, ": Component ", coor_list[i],
                              ":\t", u[i], "\t", d[i], "\tError: ", error)
                    self.assertLess(error, self.tolerance)

    def testSmallDisplacementMixedVolumetricStrainElement2DTriangle(self):
        dimension = 2
        current_model = KratosMultiphysics.Model()
        model_part = current_model.CreateModelPart("MainModelPartTriangle")
        self._add_variables(model_part)
        self._apply_material_properties(model_part, dimension)

        # Create nodes
        model_part.CreateNewNode(1, 0.5, 0.5, 0.0)
        model_part.CreateNewNode(2, 0.7, 0.2, 0.0)
        model_part.CreateNewNode(3, 0.9, 0.8, 0.0)
        model_part.CreateNewNode(4, 0.3, 0.7, 0.0)
        model_part.CreateNewNode(5, 0.6, 0.6, 0.0)

        # Add DOFs
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.VOLUMETRIC_STRAIN,
            KratosMultiphysics.REACTION_FLUX, model_part)

        # Create a submodelpart for boundary conditions
        boundary_model_part = model_part.CreateSubModelPart(
            "BoundaryCondtions")
        boundary_model_part.AddNodes([1, 2, 3, 4])

        # Create elements
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 1, [1, 2, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 2, [2, 3, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 3, [3, 4, 5],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement2D3N", 4, [4, 1, 5],
            model_part.GetProperties()[1])

        A, b = self._define_movement(dimension)

        self._apply_BCs(boundary_model_part, A, b)
        self._solve(model_part)
        self._check_results(model_part, A, b)
        if self.print_output:
            self.__post_process(model_part)

    def testSmallDisplacementMixedVolumetricStrainElement3DTetrahedra(self):
        dimension = 3
        current_model = KratosMultiphysics.Model()
        model_part = current_model.CreateModelPart("MainModelPartTetrahedra")
        self._add_variables(model_part)
        self._apply_material_properties(model_part, dimension)

        #create nodes
        model_part.CreateNewNode(1, 0.0, 1.0, 0.0)
        model_part.CreateNewNode(2, 0.0, 1.0, 0.1)
        model_part.CreateNewNode(3, 0.28739360416666665, 0.27808503701741405,
                                 0.05672979583333333)
        model_part.CreateNewNode(4, 0.0, 0.1, 0.0)
        model_part.CreateNewNode(5, 0.1, 0.1, 0.1)
        model_part.CreateNewNode(6, 1.0, 0.0, 0.0)
        model_part.CreateNewNode(7, 1.2, 0.0, 0.1)

        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_X, KratosMultiphysics.REACTION_X,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Y, KratosMultiphysics.REACTION_Y,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.DISPLACEMENT_Z, KratosMultiphysics.REACTION_Z,
            model_part)
        KratosMultiphysics.VariableUtils().AddDof(
            KratosMultiphysics.VOLUMETRIC_STRAIN,
            KratosMultiphysics.REACTION_FLUX, model_part)

        #create a submodelpart for boundary conditions
        boundary_model_part = model_part.CreateSubModelPart(
            "BoundaryCondtions")
        boundary_model_part.AddNodes([1, 2, 4, 5, 6, 7])

        #create Element
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 1,
            [5, 3, 1, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 2,
            [3, 1, 2, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 3,
            [6, 4, 7, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 4,
            [5, 4, 1, 3],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 5,
            [4, 1, 3, 6],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 6,
            [5, 4, 3, 7],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 7,
            [3, 5, 7, 2],
            model_part.GetProperties()[1])
        model_part.CreateNewElement(
            "SmallDisplacementMixedVolumetricStrainElement3D4N", 8,
            [6, 7, 2, 3],
            model_part.GetProperties()[1])

        A, b = self._define_movement(dimension)

        self._apply_BCs(boundary_model_part, A, b)
        self._solve(model_part)
        self._check_results(model_part, A, b)
        if self.print_output:
            self.__post_process(model_part)

    def __post_process(self, main_model_part, post_type="gid"):
        if post_type == "gid":
            self.gid_output = GiDOutputProcess(
                main_model_part, main_model_part.Name,
                KratosMultiphysics.Parameters(r"""
                {
                    "result_file_configuration" : {
                    "gidpost_flags": {
                        "GiDPostMode": "GiD_PostBinary",
                        "WriteDeformedMeshFlag": "WriteUndeformed",
                        "WriteConditionsFlag": "WriteConditions",
                        "MultiFileFlag": "SingleFile"
                    },
                    "nodal_results"       : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                    "gauss_point_results" : []
                    }
                }"""))

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()

        elif post_type == "vtk":
            vtk_output_parameters = KratosMultiphysics.Parameters(r"""
            {
                "model_part_name": "",
                "extrapolate_gauss_points": false,
                "nodal_solution_step_data_variables" : ["DISPLACEMENT","VOLUMETRIC_STRAIN"],
                "gauss_point_variables": []
            }""")
            vtk_output_parameters["model_part_name"].SetString(
                main_model_part.Name)
            self.vtk_output_process = VtkOutputProcess(
                main_model_part.GetModel(), vtk_output_parameters)

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()
Exemple #6
0
class TestMortarMapperCore(KratosUnittest.TestCase):
    def setUp(self):
        pass

    def __base_test_mapping(self, input_filename, num_nodes, master_num_nodes,
                            pure_implicit, inverted, discontinuous,
                            origin_are_conditions, destination_are_conditions):
        KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity(
            KratosMultiphysics.Logger.Severity.WARNING)
        self.model = KratosMultiphysics.Model()

        self.main_model_part = self.model.CreateModelPart("Main", 2)

        self.main_model_part.AddNodalSolutionStepVariable(
            KratosMultiphysics.DISPLACEMENT)
        self.main_model_part.AddNodalSolutionStepVariable(
            KratosMultiphysics.TEMPERATURE)
        self.main_model_part.AddNodalSolutionStepVariable(
            KratosMultiphysics.NORMAL)

        self.main_model_part.CloneTimeStep(1.01)

        KratosMultiphysics.ModelPartIO(input_filename).ReadModelPart(
            self.main_model_part)

        ## DEBUG Generate discontinous case
        #self.__generate_discontinous_case(inverted)

        if inverted:
            self.model_part_slave = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto2")
            self.model_part_master = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto1")
        else:
            self.model_part_slave = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto1")
            self.model_part_master = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto2")

        for node in self.model_part_master.Nodes:
            x = node.X
            y = node.Y
            z = node.Z
            node.SetSolutionStepValue(KratosMultiphysics.TEMPERATURE, z)
            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT_X, x)
            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT_Y, y)
            node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT_Z, z)
        del (node)

        map_parameters = KratosMultiphysics.Parameters("""
        {
            "echo_level"                       : 0,
            "absolute_convergence_tolerance"   : 1.0e-9,
            "relative_convergence_tolerance"   : 1.0e-4,
            "max_number_iterations"            : 10,
            "integration_order"                : 2,
            "origin_variable"                  : "TEMPERATURE",
            "discontinuous_interface"          : false,
            "origin_are_conditions"            : true,
            "destination_are_conditions"       : true
        }
        """)
        map_parameters["discontinuous_interface"].SetBool(discontinuous)
        map_parameters["origin_are_conditions"].SetBool(origin_are_conditions)
        map_parameters["destination_are_conditions"].SetBool(
            destination_are_conditions)

        if pure_implicit:
            #linear_solver = ExternalSolversApplication.SuperLUSolver()
            linear_solver = KratosMultiphysics.SkylineLUFactorizationSolver()
        else:
            linear_solver = None

        self.mortar_mapping_double = KratosMultiphysics.SimpleMortarMapperProcess(
            self.model_part_master, self.model_part_slave, map_parameters,
            linear_solver)
        map_parameters["origin_variable"].SetString("DISPLACEMENT")
        self.mortar_mapping_vector = KratosMultiphysics.SimpleMortarMapperProcess(
            self.model_part_master, self.model_part_slave, map_parameters,
            linear_solver)

    def _mapper_tests(self,
                      input_filename,
                      num_nodes,
                      master_num_nodes,
                      pure_implicit=False,
                      inverted=False,
                      discontinuous=False,
                      origin_are_conditions=True,
                      destination_are_conditions=True):

        self.__base_test_mapping(input_filename, num_nodes, master_num_nodes,
                                 pure_implicit, inverted, discontinuous,
                                 origin_are_conditions,
                                 destination_are_conditions)

        self.mortar_mapping_double.Execute()
        self.mortar_mapping_vector.Execute()

        # Debug postprocess file
        #self.__post_process()

        check_parameters = KratosMultiphysics.Parameters("""
        {
            "check_variables"      : ["TEMPERATURE","DISPLACEMENT"],
            "input_file_name"      : "",
            "model_part_name"      : "Main",
            "sub_model_part_name"  : "Parts_Parts_Auto1"
        }
        """)

        if inverted:
            check_parameters["input_file_name"].SetString(input_filename +
                                                          "_inverted.json")
        else:
            check_parameters["input_file_name"].SetString(input_filename +
                                                          ".json")

        check = from_json_check_result_process.FromJsonCheckResultProcess(
            self.model, check_parameters)
        check.ExecuteInitialize()
        check.ExecuteBeforeSolutionLoop()
        check.ExecuteFinalizeSolutionStep()

        ## The following is used to create the solution database
        #import json_output_process

        #out_parameters = KratosMultiphysics.Parameters("""
        #{
        #"output_variables"     : ["TEMPERATURE","DISPLACEMENT"],
        #"output_file_name"     : "",
        #"model_part_name"      : "Main",
        #"sub_model_part_name"  : "Parts_Parts_Auto1"
        #}
        #""")

        #if inverted:
        #out_parameters["output_file_name"].SetString(input_filename+"_inverted.json")
        #else:
        #out_parameters["output_file_name"].SetString(input_filename+".json")

        #out = json_output_process.JsonOutputProcess(self.model, out_parameters)
        #out.ExecuteInitialize()
        #out.ExecuteBeforeSolutionLoop()
        #out.ExecuteFinalizeSolutionStep()

    def test_less_basic_mortar_mapping_triangle_pure_implicit(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_integration_several_triangles"
        self._mapper_tests(input_filename, 3, 3, True)

    def test_less_basic_mortar_mapping_triangle(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_integration_several_triangles"
        self._mapper_tests(input_filename, 3, 3)

    def test_simple_curvature_mortar_mapping_triangle(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_simple_curvature"
        self._mapper_tests(input_filename, 3, 3)

    def test_mortar_mapping_triangle(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_double_curvature_integration_triangle"
        self._mapper_tests(input_filename, 3, 3)

    def test_mortar_mapping_triangle_discontinous_interface(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_double_curvature_integration_triangle_discontinous_interface"
        self._mapper_tests(input_filename, 3, 3, False, False, True)

    def test_mortar_mapping_quad(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_double_curvature_integration_quadrilateral"
        self._mapper_tests(input_filename, 4, 4)

    def test_mortar_mapping_quad_tri(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_double_curvature_integration_triangle_quadrilateral"
        self._mapper_tests(input_filename, 4, 3, False, False, False, False,
                           True)

    def test_mortar_mapping_tri_quad(self):
        input_filename = os.path.dirname(
            os.path.realpath(__file__)
        ) + "/auxiliar_files_for_python_unittest/mortar_mapper_python_tests/test_double_curvature_integration_triangle_quadrilateral"
        self._mapper_tests(input_filename, 3, 4, False, True, False, True,
                           False)

    def __post_process(self, debug="GiD"):

        if debug == "GiD":
            self.gid_output = GiDOutputProcess(
                self.main_model_part, "gid_output",
                KratosMultiphysics.Parameters("""
                                            {
                                                "result_file_configuration" : {
                                                    "gidpost_flags": {
                                                        "GiDPostMode": "GiD_PostBinary",
                                                        "WriteDeformedMeshFlag": "WriteUndeformed",
                                                        "WriteConditionsFlag": "WriteConditionsOnly",
                                                        "MultiFileFlag": "SingleFile"
                                                    },
                                                    "nodal_results"       : ["DISPLACEMENT","NORMAL","TEMPERATURE"],
                                                    "nodal_nonhistorical_results": ["NODAL_AREA","NODAL_MAUX","NODAL_VAUX"]
                                                }
                                            }
                                            """))

            self.gid_output.ExecuteInitialize()
            self.gid_output.ExecuteBeforeSolutionLoop()
            self.gid_output.ExecuteInitializeSolutionStep()
            self.gid_output.PrintOutput()
            self.gid_output.ExecuteFinalizeSolutionStep()
            self.gid_output.ExecuteFinalize()
        elif debug == "VTK":
            self.vtk_output_process = VtkOutputProcess(
                self.model,
                KratosMultiphysics.Parameters("""{
                                                "model_part_name"                    : "Main",
                                                "nodal_solution_step_data_variables" : ["DISPLACEMENT","NORMAL","TEMPERATURE"],
                                                "nodal_data_value_variables": ["NODAL_AREA","NODAL_MAUX","NODAL_VAUX"]
                                            }
                                            """))

            self.vtk_output_process.ExecuteInitialize()
            self.vtk_output_process.ExecuteBeforeSolutionLoop()
            self.vtk_output_process.ExecuteInitializeSolutionStep()
            self.vtk_output_process.PrintOutput()
            self.vtk_output_process.ExecuteFinalizeSolutionStep()
            self.vtk_output_process.ExecuteFinalize()

    def __generate_discontinous_case(self, inverted):
        counter_nodes = 0
        for node in self.main_model_part.Nodes:
            counter_nodes += 1

        counter_conditions = 0
        for cond in self.main_model_part.Conditions:
            counter_conditions += 1

        if inverted:
            self.model_part_slave = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto2")
            self.model_part_master = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto1")
        else:
            self.model_part_slave = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto1")
            self.model_part_master = self.main_model_part.GetSubModelPart(
                "Parts_Parts_Auto2")

        for cond in self.model_part_slave.Conditions:

            counter_conditions += 1
            length = cond.GetGeometry().Area() * 0.01
            list_nodes = []
            for node in cond.GetNodes():
                counter_nodes += 1
                list_nodes.append(counter_nodes)
                self.model_part_slave.CreateNewNode(counter_nodes,
                                                    node.X + length,
                                                    node.Y - length, node.Z)
                node.Set(KratosMultiphysics.TO_ERASE)
            cond.Set(KratosMultiphysics.TO_ERASE)

            self.model_part_slave.CreateNewCondition(
                "SurfaceCondition3D3N", counter_conditions, list_nodes,
                self.main_model_part.GetProperties()[1])

        self.main_model_part.RemoveNodesFromAllLevels(
            KratosMultiphysics.TO_ERASE)
        self.main_model_part.RemoveConditionsFromAllLevels(
            KratosMultiphysics.TO_ERASE)

        # Debug
        #self.__post_process()

        model_part_io = KratosMultiphysics.ModelPartIO(
            GetFilePath(
                "test_double_curvature_integration_triangle_discontinous_interface"
            ), KratosMultiphysics.IO.WRITE)
        model_part_io.WriteModelPart(self.main_model_part)

    def __sci_str(self, x):
        s = 10 * Decimal(str(x))
        s = ('{:.' + str(len(s.normalize().as_tuple().digits) - 1) +
             'E}').format(s)
        s = s.replace('E+', 'D0')
        s = s.replace('E-', 'D0-')
        s = s.replace('.', '')
        if s.startswith('-'):
            return '-.' + s[1:]
        else:
            return '.' + s