def IsConverged(self):
        convergence_list = []
        for i, data_entry in enumerate(self.settings["data_list"]):
            solver = self.solvers[data_entry["solver"]]
            data_name = data_entry["data_name"]
            cs_tools.ImportArrayFromSolver(solver, data_name, self.new_data)

            residual = self.new_data - self.old_data[i]
            res_norm = la.norm(residual)
            norm_new_data = la.norm(self.new_data)
            if norm_new_data < 1e-15:
                norm_new_data = 1.0 # to avoid division by zero
            abs_norm = res_norm / np.sqrt(residual.size)
            rel_norm = res_norm / norm_new_data
            convergence_list.append(abs_norm < self.abs_tolerances[i] or rel_norm < self.rel_tolerances[i])
            if self.echo_level > 1:
                info_msg  = 'Convergence for "'+bold(data_entry["data_name"])+'": '
                if convergence_list[i]:
                    info_msg += green("ACHIEVED")
                else:
                    info_msg += red("NOT ACHIEVED")
                classprint(self.lvl, self._Name(), info_msg)
            if self.echo_level > 2:
                info_msg  = bold("abs_norm")+" = " + str(abs_norm) + " | "
                info_msg += bold("abs_tol")+" = " + str(self.abs_tolerances[i])
                info_msg += " || "+bold("rel_norm")+" = " + str(rel_norm) + " | "
                info_msg += bold("rel_tol") +" = " + str(self.rel_tolerances[i])
                classprint(self.lvl, self._Name(), info_msg)

        return min(convergence_list) # return false if any of them did not converge!
    def SolveSolutionStep(self):
        for k in range(self.num_coupling_iterations):
            if self.echo_level > 0:
                couplingsolverprint(self.lvl, self._Name(),
                                    cyan("Coupling iteration:"), bold(str(k+1)+" / " + str(self.num_coupling_iterations)))

            self.convergence_accelerator.InitializeNonLinearIteration()
            self.convergence_criteria.InitializeNonLinearIteration()

            for solver_name in self.solver_names:
                solver = self.solvers[solver_name]
                self._SynchronizeInputData(solver, solver_name)
                solver.SolveSolutionStep()
                self._SynchronizeOutputData(solver, solver_name)

            self.convergence_accelerator.FinalizeNonLinearIteration()
            self.convergence_criteria.FinalizeNonLinearIteration()

            if self.convergence_criteria.IsConverged():
                if self.echo_level > 0:
                    couplingsolverprint(self.lvl, self._Name(), green("### CONVERGENCE WAS ACHIEVED ###"))
                break
            else:
                self.convergence_accelerator.ComputeUpdate()

            if k+1 >= self.num_coupling_iterations and self.echo_level > 0:
                couplingsolverprint(self.lvl, self._Name(), red("XXX CONVERGENCE WAS NOT ACHIEVED XXX"))
    def InitializeSolutionStep(self):
        csprint(
            0,
            bold("time={0:.12g}".format(self.time) + " | step=" +
                 str(self.step)))

        self._GetSolver().InitializeSolutionStep()
    def __GetMapper(self, from_client, to_client, data_settings):
        data_name = data_settings["data_name"]
        data_definition_from = from_client.GetDataDefinition(data_name)
        data_definition_to = to_client.GetDataDefinition(data_name)

        geometry_name_from = data_definition_from["geometry_name"]
        geometry_name_to = data_definition_to["geometry_name"]

        mapper = None
        is_inverse_mapper = False
        if geometry_name_from in self.mappers:  # a "Map"-Mapper exists
            if geometry_name_to in self.mappers[geometry_name_from]:
                mapper = self.mappers[geometry_name_from][geometry_name_to]

        if mapper == None and geometry_name_to in self.mappers:  # an "InverseMap"-Mapper exists
            if geometry_name_from in self.mappers[geometry_name_to]:
                mapper = self.mappers[geometry_name_to][geometry_name_from]
                is_inverse_mapper = True

        if mapper == None:  # no mapper for this geometry-pair exists, initializing a "Map"-Mapper
            if not geometry_name_from in self.mappers:
                self.mappers[geometry_name_from] = {}

            client_mesh_from = from_client.model[geometry_name_from]
            client_mesh_to = to_client.model[geometry_name_to]

            mapper_settings = KratosMultiphysics.Parameters("""{
                "mapper_type" : ""
            }""")
            mapper_settings["mapper_type"].SetString(
                data_settings["io_settings"]["mapper_type"])
            if from_client.IsDistributed() or to_client.IsDistributed():
                mapper = KratosMapping.MapperFactory.CreateMPIMapper(
                    client_mesh_from, client_mesh_to, mapper_settings)
            else:
                mapper = KratosMapping.MapperFactory.CreateMapper(
                    client_mesh_from, client_mesh_to, mapper_settings)

            self.mappers[geometry_name_from][geometry_name_to] = mapper

            # Printing information related to mapping
            if self.echo_level > 2:
                info_msg = bold(
                    "Mapper created"
                ) + ' for solver "' + self.solver_name + '": from "'
                info_msg += from_client._Name(
                ) + ':' + geometry_name_from + '" to "'
                info_msg += to_client._Name() + ':' + geometry_name_to + '"'
                csprint(self.lvl, info_msg)

        return mapper, is_inverse_mapper
    def AdvanceInTime(self, current_time):
        self.time = self.solvers[self.solver_names[0]].AdvanceInTime(
            current_time)
        for solver_name in self.solver_names[1:]:
            time_other_solver = self.solvers[solver_name].AdvanceInTime(
                current_time)
            if abs(self.time - time_other_solver) > 1e-12:
                raise Exception("Solver time mismatch")

        if not self.coupling_started and self.time > self.start_coupling_time:
            self.coupling_started = True
            if self.echo_level > 0:
                couplingsolverprint(self.lvl, self._Name(),
                                    bold("Starting Coupling"))

        # if a predictor is used then the delta_time is set
        # this is needed by some predictors
        if self.predictor is not None:
            delta_time = self.time - current_time
            self.predictor.SetDeltaTime(delta_time)

        return self.time
 def PrintInfo(self):
     '''Function to print Info abt the Object
     Can be overridden in derived classes to print more information
     '''
     cs_tools.classprint(self.lvl, "Convergence Accelerator",
                         cs_tools.bold(self._Name()))
 def PrintInfo(self):
     classprint(self.lvl, "Convergence Criteria", bold(self._Name()))
    def __Map(self, from_client, to_client, data_settings):
        mapper, is_inverse_mapper = self.__GetMapper(from_client, to_client,
                                                     data_settings)

        data_name = data_settings["data_name"]

        data_definition_from = from_client.GetDataDefinition(data_name)
        data_definition_to = to_client.GetDataDefinition(data_name)

        if is_inverse_mapper:
            var_origin = self.__GetKratosVariable(
                data_definition_to["data_identifier"])
            var_dest = self.__GetKratosVariable(
                data_definition_from["data_identifier"])
        else:
            var_origin = self.__GetKratosVariable(
                data_definition_from["data_identifier"])
            var_dest = self.__GetKratosVariable(
                data_definition_to["data_identifier"])

        var_origin_for_mapping = var_origin
        var_dest_for_mapping = var_dest

        mapper_flags = KratosMultiphysics.Flags()
        if "mapper_args" in data_settings["io_settings"]:
            for flag_name in data_settings["io_settings"]["mapper_args"]:
                mapper_flags |= self.mapper_flags[flag_name]

        if "type_of_quantity" in data_definition_from:
            if data_definition_from["type_of_quantity"] == "nodal_point":
                redistribution_tolerance = 1e-8
                redistribution_max_iters = 50
                geometry_name = data_definition_from["geometry_name"]
                # Convert the nodal point quantities to distributed quantities before mapping
                errr  #Talk to Philipp befoe using this => VAUX_EQ_TRACTION has to be added to the ModelPart!
                KratosMultiphysics.VariableRedistributionUtility.DistributePointValues(
                    from_client.model[geometry_name], var_origin,
                    KratosMultiphysics.VAUX_EQ_TRACTION,
                    redistribution_tolerance, redistribution_max_iters)
                var_origin_for_mapping = KratosMultiphysics.VAUX_EQ_TRACTION
                if self.echo_level > -1:
                    info_msg = bold("Distributing Point Values of ")
                    info_msg += bold("Variable: ") + var_origin.Name()
                    info_msg += bold(" On: ") + geometry_name
                    csprint(self.lvl, info_msg)

        distribute_on_dest = False
        if "type_of_quantity" in data_definition_to:
            if data_definition_to["type_of_quantity"] == "nodal_point":
                var_dest_for_mapping = KratosMultiphysics.VAUX_EQ_TRACTION
                distribute_on_dest = True

        if is_inverse_mapper:
            mapper.InverseMap(var_origin_for_mapping, var_dest_for_mapping,
                              mapper_flags)
        else:
            mapper.Map(var_origin_for_mapping, var_dest_for_mapping,
                       mapper_flags)

        if distribute_on_dest:
            geometry_name = data_definition_to["geometry_name"]
            # Convert the transferred traction loads to point loads
            KratosMultiphysics.VariableRedistributionUtility.ConvertDistributedValuesToPoint(
                to_client.model[geometry_name],
                KratosMultiphysics.VAUX_EQ_TRACTION, var_dest)
            if self.echo_level > -1:
                info_msg = bold(
                    "Converting Distributed-Values to Point-Values ")
                info_msg += bold("Variable: ") + var_dest.Name()
                info_msg += bold(" On: ") + geometry_name
                csprint(self.lvl, info_msg)

        if self.echo_level > 3:
            pre_string = ""
            if is_inverse_mapper:
                pre_string = "Inverse-"
            info_msg = bold(pre_string + "Mapping with: ")
            info_msg += bold("Origin_Variable: ") + var_origin.Name() + " | "
            info_msg += bold("Destination_Variable: ") + var_dest.Name()
            if "mapper_args" in data_settings["io_settings"]:
                info_msg += " | " + bold("Mapper-Flags: ") + ", ".join(
                    data_settings["io_settings"]["mapper_args"])
            csprint(self.lvl, info_msg)
 def PrintInfo(self):
     solverprint(self.lvl, "KratosSolver", bold(self._Name()))