Example #1
0
    def _GetAdjointParameters(self):

        adjoint_settings = self.response_settings[
            "adjoint_settings"].GetString()

        if adjoint_settings == "auto":
            Logger.PrintInfo(
                self._GetLabel(),
                "Automatic set up adjoint parameters for response:",
                self.identifier)

            if not self.primal_data_transfer_with_python:
                raise Exception(
                    "Auto setup of adjoint parameters does only support primal data transfer with python."
                )

            with open(self.response_settings["primal_settings"].GetString(),
                      'r') as parameter_file:
                primal_parameters = Parameters(parameter_file.read())

            # check that HDF5 process is not there
            if primal_parameters["processes"].Has("list_other_processes"):
                for i in range(
                        0, primal_parameters["processes"]
                    ["list_other_processes"].size()):
                    process = primal_parameters["processes"][
                        "list_other_processes"][i]
                    raise Exception(
                        "Auto setup of adjoint parameters does not support {} in list_other_processes"
                        .format(process["python_module"].GetString()))

            # clone primal settings as base for adjoint
            adjoint_parameters = primal_parameters.Clone()

            # analysis settings
            solver_settings = adjoint_parameters["solver_settings"]
            primal_solver_type = solver_settings["solver_type"].GetString()
            if primal_solver_type != "static":
                raise Exception(
                    "Auto setup of adjoint parameters does not support {} solver_type. Only available for 'static'"
                    .format(primal_solver_type))
            solver_settings["solver_type"].SetString("adjoint_" +
                                                     primal_solver_type)

            if not solver_settings.Has("compute_reactions"):
                solver_settings.AddEmptyValue("compute_reactions")
            solver_settings["compute_reactions"].SetBool(False)

            if not solver_settings.Has("move_mesh_flag"):
                solver_settings.AddEmptyValue("move_mesh_flag")
            solver_settings["move_mesh_flag"].SetBool(False)

            if solver_settings.Has("scheme_settings"):
                depr_msg = '\nDEPRECATION-WARNING: "scheme_settings" is deprecated, please remove it from your json parameters.\n'
                Logger.PrintWarning(__name__, depr_msg)
                solver_settings.RemoveValue("scheme_settings")

            if solver_settings["model_import_settings"][
                    "input_type"].GetString() == "use_input_model_part":
                solver_settings["model_import_settings"][
                    "input_type"].SetString("mdpa")
                if solver_settings["model_import_settings"].Has(
                        "input_filename"):
                    file_name = solver_settings["model_import_settings"][
                        "input_filename"].GetString()
                else:
                    Logger.PrintWarning(
                        self._GetLabel(),
                        "Automatic adjoint settings creator assumes the model_part_name as input_filename."
                    )
                    solver_settings["model_import_settings"].AddEmptyValue(
                        "input_filename")
                    file_name = solver_settings["model_part_name"].GetString()
                solver_settings["model_import_settings"][
                    "input_filename"].SetString(file_name)

            # Dirichlet conditions: change variables
            for i in range(
                    0, primal_parameters["processes"]
                ["constraints_process_list"].size()):
                process = adjoint_parameters["processes"][
                    "constraints_process_list"][i]
                variable_name = process["Parameters"][
                    "variable_name"].GetString()
                process["Parameters"]["variable_name"].SetString("ADJOINT_" +
                                                                 variable_name)

            # Neumann conditions - do not modify to read the same load values as in primal:

            # Output process:
            # TODO how to add the output process? How find out about the variables?
            if adjoint_parameters.Has("output_processes"):
                Logger.PrintInfo(
                    self._GetLabel(),
                    "Output process is removed for adjoint analysis. To enable it define adjoint_parameters yourself."
                )
                adjoint_parameters.RemoveValue("output_processes")

            # sensitivity settings
            adjoint_parameters["solver_settings"].AddValue(
                "sensitivity_settings",
                self.response_settings["sensitivity_settings"])

            # response settings
            adjoint_parameters["solver_settings"].AddValue(
                "response_function_settings", self.response_settings)

        else:  # adjoint parameters file is explicitely given - do not change it.
            with open(self.response_settings["adjoint_settings"].GetString(),
                      'r') as parameter_file:
                adjoint_parameters = Parameters(parameter_file.read())

        return adjoint_parameters
class TestParameters(KratosUnittest.TestCase):
    def setUp(self):
        self.kp = Parameters(json_string)
        self.compact_expected_output = """{"int_value":10,"double_value":2.0,"bool_value":true,"string_value":"hello","level1":{"list_value":[3,"hi",false],"tmp":5.0}}"""

        if (sys.version_info < (3, 2)):
            self.assertRaisesRegex = self.assertRaisesRegexp

    def test_kratos_parameters(self):
        self.assertEqual(self.kp.WriteJsonString(),
                         self.compact_expected_output)

        self.assertTrue(self.kp.Has("int_value"))
        self.assertFalse(self.kp.Has("unextisting_value"))

        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        self.assertEqual(self.kp["double_value"].GetDouble(), 2.0)
        self.assertEqual(self.kp["bool_value"].GetBool(), True)
        self.assertEqual(self.kp["string_value"].GetString(), "hello")

        self.assertEqual(self.kp.PrettyPrintJsonString(), pretty_out)

    def test_kratos_change_parameters(self):
        # now change one item in the sublist
        subparams = self.kp["level1"]

        my_list = subparams["list_value"]

        for i in range(my_list.size()):
            if my_list[i].IsBool():
                self.assertEqual(my_list[i].GetBool(), False)

        # my_list = subparams["list_value"]
        subparams["list_value"][0].SetString("changed")

        self.assertEqual(self.kp.PrettyPrintJsonString(),
                         pretty_out_after_change)

    def test_kratos_copy_parameters(self):
        # try to make a copy
        original_out = self.kp.PrettyPrintJsonString()
        other_copy = self.kp.Clone()

        self.assertEqual(other_copy.PrettyPrintJsonString(), original_out)

        other_copy["int_value"].SetInt(-1)
        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        # self.assertEqual(other_copy["int_value").GetString(),-1)

    def test_set_value(self):
        kp = Parameters(json_string)
        kp1 = Parameters(pretty_out_after_change)

        kp["bool_value"] = kp1["level1"]
        kp["bool_value"].PrettyPrintJsonString()
        self.assertEqual(kp["bool_value"].PrettyPrintJsonString(),
                         kp1["level1"].PrettyPrintJsonString())

    def test_kratos_wrong_parameters(self):
        # should check which errors are thrown!!
        with self.assertRaisesRegex(RuntimeError, "no_value"):
            self.kp["no_value"].GetInt()

    def test_validation_fails_due_to_wrong_type(self):
        kp = Parameters(wrong_type)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_fails_due_to_wrong_spelling(self):
        kp = Parameters(wrong_spelling)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_recursive_validation_fails_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.RecursivelyValidateAndAssignDefaults(defaults_params)

    def test_recursive_validation_4_levels(self):
        kp = Parameters(four_levels)
        kp_variation = Parameters(four_levels_variation)
        kp_wrong_wariation = Parameters(four_levels_wrong_variation)
        defaults_params = Parameters(four_levels_defaults)

        kp.RecursivelyValidateAndAssignDefaults(defaults_params)
        kp_variation.RecursivelyValidateAndAssignDefaults(defaults_params)

        self.assertTrue(kp.IsEquivalentTo(defaults_params))
        self.assertFalse(kp_variation.IsEquivalentTo(defaults_params))

        self.assertTrue(kp.HasSameKeysAndTypeOfValuesAs(defaults_params))
        self.assertTrue(
            kp_variation.HasSameKeysAndTypeOfValuesAs(defaults_params))
        self.assertFalse(
            kp_wrong_wariation.HasSameKeysAndTypeOfValuesAs(defaults_params))

    def test_validation_succeds_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # here no error shall be thrown since validation is only done on level0
        kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_succeeds(self):
        kp = Parameters(json_string)
        defaults_params = Parameters(defaults)
        defaults_params["level1"]["tmp"].SetDouble(
            2.0
        )  # this does not coincide with the value in kp, but is of the same type

        kp.ValidateAndAssignDefaults(defaults_params)
        self.assertEqual(kp.PrettyPrintJsonString(),
                         expected_validation_output)

        self.assertEqual(kp["level1"]["tmp"].GetDouble(),
                         5.0)  # not 2, since kp overwrites the defaults

    def test_add_value(self):
        kp = Parameters("{}")
        kp.AddEmptyValue("new_double").SetDouble(1.0)

        self.assertTrue(kp.Has("new_double"))
        self.assertEqual(kp["new_double"].GetDouble(), 1.0)

    def test_iterators(self):
        kp = Parameters(json_string)

        #iteration by range
        nitems = 0
        for iterator in kp:
            nitems = nitems + 1
        self.assertEqual(nitems, 5)

        #iteration by items
        for key, value in kp.items():
            #print(value.PrettyPrintJsonString())
            self.assertEqual(kp[key].PrettyPrintJsonString(),
                             value.PrettyPrintJsonString())
            #print(key,value)

        #testing values
        expected_values = [
            '10', '2.0', 'true', '"hello"',
            '{"list_value":[3,"hi",false],"tmp":5.0}'
        ]
        counter = 0

        for value in kp.values():
            self.assertEqual(value.WriteJsonString(), expected_values[counter])
            counter += 1

        #testing values
        expected_keys = [
            'int_value', 'double_value', 'bool_value', 'string_value', 'level1'
        ]
        counter = 0
        for key in kp.keys():
            self.assertEqual(key, expected_keys[counter])
            counter += 1

    def test_remove_value(self):
        kp = Parameters(json_string)
        self.assertTrue(kp.Has("int_value"))
        self.assertTrue(kp.Has("level1"))

        kp.RemoveValue("int_value")
        kp.RemoveValue("level1")

        self.assertFalse(kp.Has("int_value"))
        self.assertFalse(kp.Has("level1"))

    def test_is_methods(self):
        # This method checks all the "IsXXX" Methods
        tmp = Parameters(
            """{
            "int_value" : 10,   
            "double_value": 2.0,   
            "bool_value" : true,   
            "string_value" : "hello",
            "vector_value" : [5,3,4], 
            "matrix_value" : [[1,2],[3,6]]
        }"""
        )  # if you add more values to this, make sure to add the corresponding in the loop

        for key in tmp.keys():
            val_type = key[:-6]  # removing "_value"

            if val_type == "int":
                self.assertTrue(tmp[key].IsInt())
            else:
                self.assertFalse(tmp[key].IsInt())

            if val_type == "double":
                self.assertTrue(tmp[key].IsDouble())
            else:
                self.assertFalse(tmp[key].IsDouble())

            if val_type == "bool":
                self.assertTrue(tmp[key].IsBool())
            else:
                self.assertFalse(tmp[key].IsBool())

            if val_type == "string":
                self.assertTrue(tmp[key].IsString())
            else:
                self.assertFalse(tmp[key].IsString())

            if val_type == "vector":
                self.assertTrue(tmp[key].IsVector())
            else:
                self.assertFalse(tmp[key].IsVector())

            if val_type == "matrix":
                self.assertTrue(tmp[key].IsMatrix())
            else:
                self.assertFalse(tmp[key].IsMatrix())

    def test_get_methods(self):
        # This method checks all the "GetXXX" Methods if they throw an error
        tmp = Parameters(
            """{
            "int_value" : 10,   
            "double_value": 2.0,   
            "bool_value" : true,   
            "string_value" : "hello",
            "vector_value" : [5.2,-3.1,4.33], 
            "matrix_value" : [[1,2],[3,4],[5,6]]
        }"""
        )  # if you add more values to this, make sure to add the corresponding in the loop

        for key in tmp.keys():
            val_type = key[:-6]  # removing "_value"

            # Int and Double are checked tgth bcs both internally call "IsNumber"
            if val_type == "int" or val_type == "double":
                if val_type == "int":
                    self.assertEqual(tmp[key].GetInt(), 10)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetInt()

            if val_type == "double" or val_type == "int":
                if val_type == "double":
                    self.assertEqual(tmp[key].GetDouble(), 2.0)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetDouble()

            if val_type == "bool":
                self.assertEqual(tmp[key].GetBool(), True)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetBool()

            if val_type == "string":
                self.assertEqual(tmp[key].GetString(), "hello")
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetString()

            if val_type == "vector":
                V = tmp[key].GetVector()
                self.assertEqual(V[0], 5.2)
                self.assertEqual(V[1], -3.1)
                self.assertEqual(V[2], 4.33)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetVector()

            if val_type == "matrix":
                A = tmp[key].GetMatrix()
                self.assertEqual(A[0, 0], 1.0)
                self.assertEqual(A[0, 1], 2.0)
                self.assertEqual(A[1, 0], 3.0)
                self.assertEqual(A[1, 1], 4.0)
                self.assertEqual(A[2, 0], 5.0)
                self.assertEqual(A[2, 1], 6.0)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetMatrix()

    def test_vector_interface(self):
        # Read and check Vectors from a Parameters-Object
        tmp = Parameters("""{
            "valid_vectors" : [ []
            ],
            "false_vectors" : [ [[2,3],2],
                                [2,3,[2]],
                                [2,3,[]],
                                [{"key":3},2],
                                [2,3,{"key":3}],
                                [true,2],
                                [2,3,true],
                                [5,"string",2] 
            ]
        }""")

        # Check the IsVector Method
        for i in range(tmp["valid_vectors"].size()):
            valid_vector = tmp["valid_vectors"][i]
            self.assertTrue(valid_vector.IsVector())

        for i in range(tmp["false_vectors"].size()):
            false_vector = tmp["false_vectors"][i]
            self.assertFalse(false_vector.IsVector())

        # Check the GetVector Method also on the valid Matrices
        for i in range(tmp["valid_vectors"].size()):
            valid_vector = tmp["valid_vectors"][i]
            valid_vector.GetVector()

        # Check that the errors of the GetVector method are thrown correctly
        for i in range(tmp["false_vectors"].size()):
            false_vector = tmp["false_vectors"][i]
            with self.assertRaises(RuntimeError):
                false_vector.GetVector()

        # Manually assign and check a Vector
        vec = Vector(3)
        vec[0] = 1.32
        vec[1] = -2.22
        vec[2] = 5.5

        tmp.AddEmptyValue("vector_value")
        tmp["vector_value"].SetVector(vec)

        self.assertTrue(tmp["vector_value"].IsVector())

        V2 = tmp["vector_value"].GetVector()
        self.assertEqual(V2[0], 1.32)
        self.assertEqual(V2[1], -2.22)
        self.assertEqual(V2[2], 5.5)

    def test_matrix_interface(self):
        # Read and check Matrices from a Parameters-Object
        tmp = Parameters("""{
            "valid_matrices" : [ [[]],
                                 [[],[]],
                                 [[-9.81,8, 5.47]]
            ],
            "false_matrices" : [ [],
                                 [[[]]],
                                 [[3.3] , [1,2]],
                                 [[2,1.5,3.3] , [3,{"key":3},2]],
                                 [[2,1.5,3.3] , [5,false,2]],
                                 [[2,1.5,3.3] , [[2,3],1,2]],
                                 [[2,1.5,3.3] , ["string",2,9]] 
            ]
        }""")

        # Check the IsMatrix Method
        for i in range(tmp["valid_matrices"].size()):
            valid_matrix = tmp["valid_matrices"][i]
            self.assertTrue(valid_matrix.IsMatrix())

        for i in range(tmp["false_matrices"].size()):
            false_matrix = tmp["false_matrices"][i]
            self.assertFalse(false_matrix.IsMatrix())

        # Check the GetMatrix Method also on the valid Matrices
        for i in range(tmp["valid_matrices"].size()):
            valid_matrix = tmp["valid_matrices"][i]
            valid_matrix.GetMatrix()

        # Check that the errors of the GetMatrix method are thrown correctly
        for i in range(tmp["false_matrices"].size()):
            false_matrix = tmp["false_matrices"][i]
            with self.assertRaises(RuntimeError):
                false_matrix.GetMatrix()

        # Manually assign and check a Matrix
        mat = Matrix(3, 2)
        mat[0, 0] = 1.0
        mat[0, 1] = 2.0
        mat[1, 0] = 3.0
        mat[1, 1] = 4.0
        mat[2, 0] = 5.0
        mat[2, 1] = 6.0

        tmp.AddEmptyValue("matrix_value")
        tmp["matrix_value"].SetMatrix(mat)

        self.assertTrue(tmp["matrix_value"].IsMatrix())

        A2 = tmp["matrix_value"].GetMatrix()
        self.assertEqual(A2[0, 0], 1.0)
        self.assertEqual(A2[0, 1], 2.0)
        self.assertEqual(A2[1, 0], 3.0)
        self.assertEqual(A2[1, 1], 4.0)
        self.assertEqual(A2[2, 0], 5.0)
        self.assertEqual(A2[2, 1], 6.0)

    def test_null_vs_null_validation(self):

        # supplied settings
        null_custom = Parameters("""{
        "parameter": null
        }""")

        # default settings
        null_default = Parameters("""{
        "parameter": null
        }""")

        #this should NOT raise, hence making the test to pass
        null_custom.ValidateAndAssignDefaults(null_default)

    def test_double_vs_null_validation(self):

        # supplied settings
        double_custom = Parameters("""{
        "parameter": 0.0
        }""")

        # default settings
        null_default = Parameters("""{
        "parameter": null
        }""")

        with self.assertRaises(RuntimeError):
            double_custom.ValidateAndAssignDefaults(null_default)
class TestParameters(KratosUnittest.TestCase):
    def setUp(self):
        self.kp = Parameters(json_string)
        self.compact_expected_output = """{"int_value":10,"double_value":2.0,"bool_value":true,"string_value":"hello","level1":{"list_value":[3,"hi",false],"tmp":5.0}}"""

        if (sys.version_info < (3, 2)):
            self.assertRaisesRegex = self.assertRaisesRegexp

    def test_kratos_parameters(self):
        self.assertEqual(self.kp.WriteJsonString(),
                         self.compact_expected_output)

        self.assertTrue(self.kp.Has("int_value"))
        self.assertFalse(self.kp.Has("unextisting_value"))

        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        self.assertEqual(self.kp["double_value"].GetDouble(), 2.0)
        self.assertEqual(self.kp["bool_value"].GetBool(), True)
        self.assertEqual(self.kp["string_value"].GetString(), "hello")

        self.assertEqual(self.kp.PrettyPrintJsonString(), pretty_out)

    def test_kratos_change_parameters(self):
        # now change one item in the sublist
        subparams = self.kp["level1"]

        my_list = subparams["list_value"]

        for i in range(my_list.size()):
            if my_list[i].IsBool():
                self.assertEqual(my_list[i].GetBool(), False)

        # my_list = subparams["list_value"]
        subparams["list_value"][0].SetString("changed")

        self.assertEqual(self.kp.PrettyPrintJsonString(),
                         pretty_out_after_change)

    def test_kratos_copy_parameters(self):
        # try to make a copy
        original_out = self.kp.PrettyPrintJsonString()
        other_copy = self.kp.Clone()

        self.assertEqual(other_copy.PrettyPrintJsonString(), original_out)

        other_copy["int_value"].SetInt(-1)
        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        # self.assertEqual(other_copy["int_value").GetString(),-1)

    def test_set_value(self):
        kp = Parameters(json_string)
        kp1 = Parameters(pretty_out_after_change)

        kp["bool_value"] = kp1["level1"]
        kp["bool_value"].PrettyPrintJsonString()
        self.assertEqual(kp["bool_value"].PrettyPrintJsonString(),
                         kp1["level1"].PrettyPrintJsonString())

    def test_kratos_wrong_parameters(self):
        # should check which errors are thrown!!
        with self.assertRaisesRegex(RuntimeError, "no_value"):
            self.kp["no_value"].GetInt()

    def test_validation_fails_due_to_wrong_type(self):
        kp = Parameters(wrong_type)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_fails_due_to_wrong_spelling(self):
        kp = Parameters(wrong_spelling)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_recursive_validation_fails_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.RecursivelyValidateAndAssignDefaults(defaults_params)

    def test_validation_succeds_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # here no error shall be thrown since validation is only done on level0
        kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_succeeds(self):
        kp = Parameters(json_string)
        defaults_params = Parameters(defaults)
        defaults_params["level1"]["tmp"].SetDouble(
            2.0
        )  # this does not coincide with the value in kp, but is of the same type

        kp.ValidateAndAssignDefaults(defaults_params)
        self.assertEqual(kp.PrettyPrintJsonString(),
                         expected_validation_output)

        self.assertEqual(kp["level1"]["tmp"].GetDouble(),
                         5.0)  # not 2, since kp overwrites the defaults

    def test_add_value(self):
        kp = Parameters("{}")
        kp.AddEmptyValue("new_double").SetDouble(1.0)

        self.assertTrue(kp.Has("new_double"))
        self.assertEqual(kp["new_double"].GetDouble(), 1.0)

    def test_iterators(self):
        kp = Parameters(json_string)

        #iteration by range
        nitems = 0
        for iterator in kp:
            nitems = nitems + 1
        self.assertEqual(nitems, 5)

        #iteration by items
        for key, value in kp.items():
            #print(value.PrettyPrintJsonString())
            self.assertEqual(kp[key].PrettyPrintJsonString(),
                             value.PrettyPrintJsonString())
            #print(key,value)

        #testing values

        expected_values = [
            '10', '2.0', 'true', '"hello"',
            '{"list_value":[3,"hi",false],"tmp":5.0}'
        ]
        counter = 0

        for value in kp.values():
            self.assertEqual(value.WriteJsonString(), expected_values[counter])
            counter += 1

        #testing values
        expected_keys = [
            'int_value', 'double_value', 'bool_value', 'string_value', 'level1'
        ]
        counter = 0
        for key in kp.keys():
            self.assertEqual(key, expected_keys[counter])
            counter += 1

    def test_remove_value(self):
        kp = Parameters(json_string)
        self.assertTrue(kp.Has("int_value"))
        self.assertTrue(kp.Has("level1"))
        print(kp)

        kp.RemoveValue("int_value")
        kp.RemoveValue("level1")

        print(kp)
        self.assertFalse(kp.Has("int_value"))
        self.assertFalse(kp.Has("level1"))
class TestParameters(KratosUnittest.TestCase):

    def setUp(self):
        self.kp = Parameters(json_string)
        self.compact_expected_output = """{"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"}"""

    def test_kratos_parameters(self):
        self.assertEqual(
            self.kp.WriteJsonString(),
            self.compact_expected_output
        )

        self.assertTrue(self.kp.Has("int_value"))
        self.assertFalse(self.kp.Has("unextisting_value"))

        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        self.assertEqual(self.kp["double_value"].GetDouble(), 2.0)
        self.assertEqual(self.kp["bool_value"].GetBool(), True)
        self.assertEqual(self.kp["string_value"].GetString(), "hello")

        self.assertEqual(self.kp.PrettyPrintJsonString(), pretty_out)

    def test_kratos_change_parameters(self):
        # now change one item in the sublist
        subparams = self.kp["level1"]

        my_list = subparams["list_value"]

        for i in range(my_list.size()):
            if my_list[i].IsBool():
                self.assertEqual(my_list[i].GetBool(), False)

        # my_list = subparams["list_value"]
        subparams["list_value"][0].SetString("changed")

        self.assertEqual(
            self.kp.PrettyPrintJsonString(),
            pretty_out_after_change
        )

    def test_kratos_copy_parameters(self):
        # try to make a copy
        original_out = self.kp.PrettyPrintJsonString()
        other_copy = self.kp.Clone()

        self.assertEqual(
            other_copy.PrettyPrintJsonString(),
            original_out
        )

        other_copy["int_value"].SetInt(-1)
        self.assertEqual(self.kp["int_value"].GetInt(), 10)
        # self.assertEqual(other_copy["int_value").GetString(),-1)

    def test_set_value(self):
        kp = Parameters(json_string)
        kp1 = Parameters(pretty_out_after_change)

        kp["bool_value"] = kp1["level1"]
        kp["bool_value"].PrettyPrintJsonString()
        self.assertEqual(kp["bool_value"].PrettyPrintJsonString(), kp1["level1"].PrettyPrintJsonString())

    def test_kratos_wrong_parameters(self):
        # should check which errors are thrown!!
        with self.assertRaisesRegex(RuntimeError, "no_value"):
            self.kp["no_value"].GetInt()

    def test_validation_fails_due_to_wrong_type(self):
        kp = Parameters(wrong_type)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_fails_due_to_wrong_spelling(self):
        kp = Parameters(wrong_spelling)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.ValidateAndAssignDefaults(defaults_params)

    def test_recursive_validation_fails_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # should check which errors are thrown!!
        with self.assertRaises(RuntimeError):
            kp.RecursivelyValidateAndAssignDefaults(defaults_params)

    def test_recursive_validation_4_levels(self):
        kp = Parameters(four_levels)
        kp_variation = Parameters(four_levels_variation)
        kp_wrong_wariation = Parameters(four_levels_wrong_variation)
        defaults_params = Parameters(four_levels_defaults)

        kp.RecursivelyValidateAndAssignDefaults(defaults_params)
        kp_variation.RecursivelyValidateAndAssignDefaults(defaults_params)

        self.assertTrue( kp.IsEquivalentTo(defaults_params) )
        self.assertFalse( kp_variation.IsEquivalentTo(defaults_params) )

        self.assertTrue( kp.HasSameKeysAndTypeOfValuesAs(defaults_params) )
        self.assertTrue( kp_variation.HasSameKeysAndTypeOfValuesAs(defaults_params) )
        self.assertFalse( kp_wrong_wariation.HasSameKeysAndTypeOfValuesAs(defaults_params) )

    def test_validation_succeds_error_on_first_level(self):
        kp = Parameters(wrong_lev2)
        defaults_params = Parameters(defaults)

        # here no error shall be thrown since validation is only done on level0
        kp.ValidateAndAssignDefaults(defaults_params)

    def test_validation_succeeds(self):
        kp = Parameters(json_string)
        defaults_params = Parameters(defaults)
        defaults_params["level1"]["tmp"].SetDouble(2.0)  # this does not coincide with the value in kp, but is of the same type

        kp.ValidateAndAssignDefaults(defaults_params)
        self.assertEqual(kp.PrettyPrintJsonString(), expected_validation_output)

        self.assertEqual(kp["level1"]["tmp"].GetDouble(), 5.0)  # not 2, since kp overwrites the defaults

    def test_add_missing_parameters(self):
        # only missing parameters are added, no complaints if there already exist more than in the defaults
        kp = Parameters(json_string)
        tmp = Parameters(incomplete_with_extra_parameter)

        kp.AddMissingParameters(tmp)

        self.assertEqual(kp["new_default_obj"]["aaa"].GetString(), "string")
        self.assertEqual(kp["string_value"].GetString(), "hello")
        self.assertFalse(kp["level1"].Has("new_sublevel"))

    def test_recursively_add_missing_parameters(self):
        # only missing parameters are added, no complaints if there already exist more than in the defaults
        kp = Parameters(json_string)
        tmp = Parameters(incomplete_with_extra_parameter)

        kp.RecursivelyAddMissingParameters(tmp)

        self.assertTrue(kp["level1"].Has("new_sublevel"))
        self.assertEqual(kp["level1"]["new_sublevel"].GetString(), "this should only be assigned in recursive")

    def test_validate_defaults(self):
        # only parameters from defaults are validated, no new values are added
        kp = Parameters(incomplete_with_extra_parameter)
        tmp = Parameters(defaults)

        kp.ValidateDefaults(tmp)

        self.assertFalse(kp.Has("bool_value"))
        self.assertFalse(kp.Has("double_value"))
        self.assertTrue(kp.Has("level1"))

    def test_recursively_validate_defaults(self):
        # only parameters from defaults are validated, no new values are added
        kp = Parameters(incomplete)
        tmp = Parameters(defaults)

        kp.RecursivelyValidateDefaults(tmp)

        self.assertFalse(kp.Has("bool_value"))
        self.assertFalse(kp.Has("double_value"))
        self.assertTrue(kp.Has("level1"))


    def test_recursively_validate_defaults_fails(self):
        # only parameters from defaults are validated, no new values are added
        kp = Parameters(incomplete_with_extra_parameter)
        tmp = Parameters(defaults)

        with self.assertRaises(RuntimeError):
            kp.RecursivelyValidateDefaults(tmp)

        # sub_level
        self.assertFalse(kp["level1"].Has("tmp"))

    def test_add_value(self):
        kp = Parameters("{}")
        kp.AddEmptyValue("new_double").SetDouble(1.0)

        self.assertTrue(kp.Has("new_double"))
        self.assertEqual(kp["new_double"].GetDouble(), 1.0)

    def test_add_empty_array(self):
        kp = Parameters("{}")
        kp.AddEmptyArray("new_array")

        self.assertTrue(kp.Has("new_array"))
        self.assertEqual(kp["new_array"].size(), 0)

    def test_iterators(self):
        kp = Parameters(json_string)

        #iteration by range
        nitems = 0
        for iterator in kp:
            nitems = nitems + 1
        self.assertEqual(nitems, 5)

        #iteration by items
        for key,value in kp.items():
            #print(value.PrettyPrintJsonString())
            self.assertEqual(kp[key].PrettyPrintJsonString(), value.PrettyPrintJsonString())
            #print(key,value)

        #testing values
        expected_values = ['true', '2.0', '10', '{"list_value":[3,"hi",false],"tmp":5.0}','"hello"']
        counter = 0

        for value in kp.values():
            self.assertEqual(value.WriteJsonString(), expected_values[counter])
            counter += 1

        #testing values
        expected_keys = ['bool_value', 'double_value', 'int_value', 'level1', 'string_value']
        counter = 0
        for key in kp.keys():
            self.assertEqual(key, expected_keys[counter])
            counter += 1

    def test_remove_value(self):
        kp = Parameters(json_string)
        self.assertTrue(kp.Has("int_value"))
        self.assertTrue(kp.Has("level1"))

        kp.RemoveValue("int_value")
        kp.RemoveValue("level1")

        self.assertFalse(kp.Has("int_value"))
        self.assertFalse(kp.Has("level1"))

    def test_is_methods(self):
        # This method checks all the "IsXXX" Methods
        tmp = Parameters("""{
            "int_value" : 10,
            "double_value": 2.0,
            "bool_value" : true,
            "string_value" : "hello",
            "vector_value" : [5,3,4],
            "matrix_value" : [[1,2],[3,6]]
        }""") # if you add more values to this, make sure to add the corresponding in the loop

        for key in tmp.keys():
            val_type = key[:-6] # removing "_value"

            if val_type == "int":
                self.assertTrue(tmp[key].IsInt())
            else:
                self.assertFalse(tmp[key].IsInt())

            if val_type == "double":
                self.assertTrue(tmp[key].IsDouble())
            else:
                self.assertFalse(tmp[key].IsDouble())

            if val_type == "bool":
                self.assertTrue(tmp[key].IsBool())
            else:
                self.assertFalse(tmp[key].IsBool())

            if val_type == "string":
                self.assertTrue(tmp[key].IsString())
            else:
                self.assertFalse(tmp[key].IsString())

            if val_type == "vector":
                self.assertTrue(tmp[key].IsVector())
            else:
                self.assertFalse(tmp[key].IsVector())

            if val_type == "matrix":
                self.assertTrue(tmp[key].IsMatrix())
            else:
                self.assertFalse(tmp[key].IsMatrix())

    def test_get_methods(self):
        # This method checks all the "GetXXX" Methods if they throw an error
        tmp = Parameters("""{
            "int_value" : 10,
            "double_value": 2.0,
            "bool_value" : true,
            "string_value" : "hello",
            "vector_value" : [5.2,-3.1,4.33],
            "matrix_value" : [[1,2],[3,4],[5,6]]
        }""") # if you add more values to this, make sure to add the corresponding in the loop

        for key in tmp.keys():
            val_type = key[:-6] # removing "_value"

            # Int and Double are checked tgth bcs both internally call "IsNumber"
            if val_type == "int" or val_type == "double":
                if val_type == "int":
                    self.assertEqual(tmp[key].GetInt(),10)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetInt()

            if val_type == "double" or val_type == "int":
                if val_type == "double":
                    self.assertEqual(tmp[key].GetDouble(),2.0)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetDouble()

            if val_type == "bool":
                self.assertEqual(tmp[key].GetBool(),True)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetBool()

            if val_type == "string":
                self.assertEqual(tmp[key].GetString(),"hello")
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetString()

            if val_type == "vector":
                V = tmp[key].GetVector()
                self.assertEqual(V[0],5.2)
                self.assertEqual(V[1],-3.1)
                self.assertEqual(V[2],4.33)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetVector()

            if val_type == "matrix":
                A = tmp[key].GetMatrix()
                self.assertEqual(A[0,0],1.0)
                self.assertEqual(A[0,1],2.0)
                self.assertEqual(A[1,0],3.0)
                self.assertEqual(A[1,1],4.0)
                self.assertEqual(A[2,0],5.0)
                self.assertEqual(A[2,1],6.0)
            else:
                with self.assertRaises(RuntimeError):
                    tmp[key].GetMatrix()

    def test_vector_interface(self):
        # Read and check Vectors from a Parameters-Object
        tmp = Parameters("""{
            "valid_vectors" : [ []
            ],
            "false_vectors" : [ [[]],
                                [[2,3],2],
                                [2,3,[2]],
                                [2,3,[]],
                                [{"key":3},2],
                                [2,3,{"key":3}],
                                [true,2],
                                [2,3,true],
                                [5,"string",2]
            ]
        }""")

        # Check the IsVector Method
        for i in range(tmp["valid_vectors"].size()):
            valid_vector = tmp["valid_vectors"][i]
            self.assertTrue(valid_vector.IsVector())

        for i in range(tmp["false_vectors"].size()):
            false_vector = tmp["false_vectors"][i]
            self.assertFalse(false_vector.IsVector())

        # Check the GetVector Method also on the valid Matrices
        for i in range(tmp["valid_vectors"].size()):
            valid_vector = tmp["valid_vectors"][i]
            valid_vector.GetVector()

        # Check that the errors of the GetVector method are thrown correctly
        for i in range(tmp["false_vectors"].size()):
            false_vector = tmp["false_vectors"][i]
            with self.assertRaises(RuntimeError):
                false_vector.GetVector()

        # Manually assign and check a Vector
        vec = Vector(3)
        vec[0] = 1.32
        vec[1] = -2.22
        vec[2] = 5.5

        tmp.AddEmptyValue("vector_value")
        tmp["vector_value"].SetVector(vec)

        self.assertTrue(tmp["vector_value"].IsVector())

        V2 = tmp["vector_value"].GetVector()
        self.assertEqual(V2[0],1.32)
        self.assertEqual(V2[1],-2.22)
        self.assertEqual(V2[2],5.5)

    def test_matrix_interface(self):
        # Read and check Matrices from a Parameters-Object
        tmp = Parameters("""{
            "valid_matrices" : [ [[]],
                                 [[],[]],
                                 [[-9.81,8, 5.47]]
            ],
            "false_matrices" : [ [],
                                 [[[]]],
                                 [[3.3] , [1,2]],
                                 [[2,1.5,3.3] , [3,{"key":3},2]],
                                 [[2,1.5,3.3] , [5,false,2]],
                                 [[2,1.5,3.3] , [[2,3],1,2]],
                                 [[2,1.5,3.3] , ["string",2,9]]
            ]
        }""")

        # Check the IsMatrix Method
        for i in range(tmp["valid_matrices"].size()):
            valid_matrix = tmp["valid_matrices"][i]
            self.assertTrue(valid_matrix.IsMatrix())

        for i in range(tmp["false_matrices"].size()):
            false_matrix = tmp["false_matrices"][i]
            self.assertFalse(false_matrix.IsMatrix())

        # Check the GetMatrix Method also on the valid Matrices
        for i in range(tmp["valid_matrices"].size()):
            valid_matrix = tmp["valid_matrices"][i]
            valid_matrix.GetMatrix()

        # Check that the errors of the GetMatrix method are thrown correctly
        for i in range(tmp["false_matrices"].size()):
            false_matrix = tmp["false_matrices"][i]
            with self.assertRaises(RuntimeError):
                false_matrix.GetMatrix()

        # Manually assign and check a Matrix
        mat = Matrix(3,2)
        mat[0,0] = 1.0
        mat[0,1] = 2.0
        mat[1,0] = 3.0
        mat[1,1] = 4.0
        mat[2,0] = 5.0
        mat[2,1] = 6.0

        tmp.AddEmptyValue("matrix_value")
        tmp["matrix_value"].SetMatrix(mat)

        self.assertTrue(tmp["matrix_value"].IsMatrix())

        A2 = tmp["matrix_value"].GetMatrix()
        self.assertEqual(A2[0,0],1.0)
        self.assertEqual(A2[0,1],2.0)
        self.assertEqual(A2[1,0],3.0)
        self.assertEqual(A2[1,1],4.0)
        self.assertEqual(A2[2,0],5.0)
        self.assertEqual(A2[2,1],6.0)

    def test_null_vs_null_validation(self):

        # supplied settings
        null_custom = Parameters("""{
        "parameter": null
        }""")

        # default settings
        null_default = Parameters("""{
        "parameter": null
        }""")

        #this should NOT raise, hence making the test to pass
        null_custom.ValidateAndAssignDefaults(null_default)

    def test_double_vs_null_validation(self):
        # supplied settings
        double_custom = Parameters("""{
        "parameter": 0.0
        }""")

        # default settings
        null_default = Parameters("""{
        "parameter": null
        }""")

        with self.assertRaises(RuntimeError):
            double_custom.ValidateAndAssignDefaults(null_default)

    def test_file_serialization(self):
        tmp = Parameters(defaults)
        check = tmp.WriteJsonString()

        file_name = "parameter_serialization"

        serializer = FileSerializer(file_name, SerializerTraceType.SERIALIZER_NO_TRACE)
        serializer.Save("ParametersSerialization",tmp)
        del(tmp)
        del(serializer)


        #unpickle data - note that here i override "serialized_data"
        serializer = FileSerializer(file_name,SerializerTraceType.SERIALIZER_NO_TRACE)

        loaded_parameters = Parameters()
        serializer.Load("ParametersSerialization",loaded_parameters)

        self.assertEqual(check, loaded_parameters.WriteJsonString())
        kratos_utils.DeleteFileIfExisting(file_name + ".rest")

    def test_get_string_array_valid(self):
        tmp = Parameters("""{
            "parameter": ["foo", "bar"]
        } """)
        v = tmp["parameter"].GetStringArray()
        self.assertEqual(len(v), 2)
        self.assertEqual(v[0], "foo")
        self.assertEqual(v[1], "bar")

    def test_get_string_array_invalid(self):
        tmp = Parameters("""{
            "parameter": ["foo", true]
        } """)
        with self.assertRaisesRegex(RuntimeError, r'Error: Argument must be a string'):
            tmp["parameter"].GetStringArray()

    @KratosUnittest.skipUnless(have_pickle_module, "Pickle module error: : " + pickle_message)
    def test_stream_serialization(self):
        tmp = Parameters(defaults)
        check = tmp.WriteJsonString()

        serializer = StreamSerializer(SerializerTraceType.SERIALIZER_NO_TRACE)
        serializer.Save("ParametersSerialization",tmp)
        del(tmp)

        #pickle dataserialized_data
        pickled_data = pickle.dumps(serializer, protocol=2) # Second argument is the protocol and is NECESSARY (according to pybind11 docs)
        del(serializer)

        #unpickle data - note that here i override "serialized_data"
        serializer = pickle.loads(pickled_data)

        loaded_parameters = Parameters()
        serializer.Load("ParametersSerialization",loaded_parameters)

        self.assertEqual(check, loaded_parameters.WriteJsonString())