def IsConverged(self): new_data = self.interface_data.GetData() residual = new_data - self.prev_data res_norm = la.norm(residual) norm_new_data = la.norm(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 is_converged = abs_norm < self.abs_tolerance or rel_norm < self.rel_tolerance if self.echo_level > 1: info_msg = 'Convergence for "' + colors.bold( self.interface_data.variable.Name()) + '": ' if is_converged: info_msg += colors.green("ACHIEVED") else: info_msg += colors.red("NOT ACHIEVED") cs_tools.cs_print_info(self._Name(), info_msg) if self.echo_level > 2: info_msg = colors.bold("abs_norm") + " = " + str(abs_norm) + " | " info_msg += colors.bold("abs_tol") + " = " + str( self.abs_tolerance) + " || " info_msg += colors.bold("rel_norm") + " = " + str(rel_norm) + " | " info_msg += colors.bold("rel_tol") + " = " + str( self.rel_tolerance) cs_tools.cs_print_info(self._Name(), info_msg) return is_converged
def IsConverged(self, residual, current_data): abs_norm = la.norm(residual) / np.sqrt(residual.size) if self.initial_iteration: self.initial_iteration = False self.initial_norm = abs_norm rel_norm = abs_norm / self.initial_norm is_converged = abs_norm < self.abs_tolerance or rel_norm < self.rel_tolerance info_msg = "" if self.echo_level > 1: info_msg = 'Convergence ' if self.label != "": info_msg += 'for "{}": '.format(self.label) if is_converged: info_msg += colors.green("ACHIEVED") else: info_msg += colors.red("NOT ACHIEVED") if self.echo_level > 2: info_msg += '\n\t abs-norm = {:.2e} | abs-tol = {} || rel-norm = {:.2e} | rel-tol = {}'.format( abs_norm, self.abs_tolerance, rel_norm, self.rel_tolerance) if info_msg != "": cs_tools.cs_print_info(self._ClassName(), info_msg) return is_converged
def IsConverged(self): new_data = self.interface_data.GetData() residual = new_data - self.prev_data abs_norm = la.norm(residual) / np.sqrt(residual.size) if self.initial_iteration: self.initial_iteration = False self.initial_norm = abs_norm rel_norm = abs_norm / self.initial_norm is_converged = abs_norm < self.abs_tolerance or rel_norm < self.rel_tolerance if self.echo_level > 1: info_msg = 'Convergence for "' + colors.bold( self.interface_data.variable.Name()) + '": ' if is_converged: info_msg += colors.green("ACHIEVED") else: info_msg += colors.red("NOT ACHIEVED") cs_tools.cs_print_info(self._ClassName(), info_msg) if self.echo_level > 2: info_msg = colors.bold("abs_norm") + " = " + str(abs_norm) + " | " info_msg += colors.bold("abs_tol") + " = " + str( self.abs_tolerance) + " || " info_msg += colors.bold("rel_norm") + " = " + str(rel_norm) + " | " info_msg += colors.bold("rel_tol") + " = " + str( self.rel_tolerance) cs_tools.cs_print_info(self._ClassName(), info_msg) return is_converged
def IsConverged(self, residual, current_data): res_norm = la.norm(residual) norm_new_data = la.norm(current_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 is_converged = abs_norm < self.abs_tolerance or rel_norm < self.rel_tolerance info_msg = "" if self.echo_level > 1: info_msg = 'Convergence ' if self.label != "": info_msg += 'for "{}": '.format(self.label) if is_converged: info_msg += colors.green("ACHIEVED") else: info_msg += colors.red("NOT ACHIEVED") if self.echo_level > 2: info_msg += '\n\t abs-norm = {:.2e} | abs-tol = {} || rel-norm = {:.2e} | rel-tol = {}'.format( abs_norm, self.abs_tolerance, rel_norm, self.rel_tolerance) if info_msg != "": cs_tools.cs_print_info(self._ClassName(), info_msg) return is_converged
def SolveSolutionStep(self): for k in range(self.num_coupling_iterations): if self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.cyan("Coupling iteration:"), colors.bold( str(k + 1) + " / " + str(self.num_coupling_iterations))) for coupling_op in self.coupling_operations_dict.values(): coupling_op.InitializeCouplingIteration() for conv_acc in self.convergence_accelerators_list: conv_acc.InitializeNonLinearIteration() for conv_crit in self.convergence_criteria_list: conv_crit.InitializeNonLinearIteration() for solver_name, solver in self.solver_wrappers.items(): self._SynchronizeInputData(solver_name) solver.SolveSolutionStep() self._SynchronizeOutputData(solver_name) for coupling_op in self.coupling_operations_dict.values(): coupling_op.FinalizeCouplingIteration() for conv_acc in self.convergence_accelerators_list: conv_acc.FinalizeNonLinearIteration() for conv_crit in self.convergence_criteria_list: conv_crit.FinalizeNonLinearIteration() is_converged = all([ conv_crit.IsConverged() for conv_crit in self.convergence_criteria_list ]) if is_converged: if self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.green("### CONVERGENCE WAS ACHIEVED ###")) self.__CommunicateStateOfConvergence(True) return True if k + 1 >= self.num_coupling_iterations and self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.red("XXX CONVERGENCE WAS NOT ACHIEVED XXX")) self.__CommunicateStateOfConvergence( True ) # True because max number of iterations is achieved. Otherwise external solver is stuck in time return False # if it reaches here it means that the coupling has not converged and this was not the last coupling iteration self.__CommunicateStateOfConvergence(False) # do relaxation only if this iteration is not the last iteration of this timestep for conv_acc in self.convergence_accelerators_list: conv_acc.ComputeAndApplyUpdate()
def SolveSolutionStep(self): for k in range(self.num_coupling_iterations): if self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.cyan("Coupling iteration:"), colors.bold( str(k + 1) + " / " + str(self.num_coupling_iterations))) for coupling_op in self.coupling_operations_dict.values(): coupling_op.InitializeCouplingIteration() for conv_acc in self.convergence_accelerators_list: conv_acc.InitializeNonLinearIteration() for conv_crit in self.convergence_criteria_list: conv_crit.InitializeNonLinearIteration() for solver_name, solver in self.solver_wrappers.items(): self._SynchronizeInputData(solver_name) solver.SolveSolutionStep() self._SynchronizeOutputData(solver_name) for coupling_op in self.coupling_operations_dict.values(): coupling_op.FinalizeCouplingIteration() for conv_acc in self.convergence_accelerators_list: conv_acc.FinalizeNonLinearIteration() for conv_crit in self.convergence_criteria_list: conv_crit.FinalizeNonLinearIteration() is_converged = all([ conv_crit.IsConverged() for conv_crit in self.convergence_criteria_list ]) self.__CommunicateStateOfConvergence(is_converged) if is_converged: if self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.green("### CONVERGENCE WAS ACHIEVED ###")) return True else: # TODO I think this should not be done in the last iterations if the solution does not converge in this timestep for conv_acc in self.convergence_accelerators_list: conv_acc.ComputeAndApplyUpdate() if k + 1 >= self.num_coupling_iterations and self.echo_level > 0: cs_tools.cs_print_info( self._ClassName(), colors.red("XXX CONVERGENCE WAS NOT ACHIEVED XXX")) return False
def IsConverged(self): # Compute energy scalar on interface current_data = 0.0 for solver_index in range(0, len(self.interface_data)): #check length of data vectors are the same interface_energy = 0.0 data_1 = self.interface_data[solver_index][0].GetData() data_2 = self.interface_data[solver_index][1].GetData() if len(data_1) != len(data_2): self.__RaiseException( 'Data vector lengths for conjugate criteria composition must be identical, but they are different!' ) else: for i in range(0, len(data_1)): interface_energy += data_1[i] * data_2[i] if solver_index == 0: current_data = interface_energy else: current_data -= self.second_domain_data_sign * interface_energy #assumes domain_difference abs_norm = la.norm(current_data) if self.ignore_first_convergence and self.iteration == 1: is_converged = False else: is_converged = abs_norm < self.abs_tolerance self.iteration += 1 info_msg = "" if self.echo_level > 1: info_msg = 'Convergence ' if self.label != "": info_msg += 'for "{}": '.format(self.label) if is_converged: info_msg += colors.green("ACHIEVED") else: info_msg += colors.red("NOT ACHIEVED") if self.echo_level > 2: info_msg += '\n\t abs-norm = {:.2e} | abs-tol = {}'.format( abs_norm, self.abs_tolerance) if info_msg != "": cs_tools.cs_print_info(self._ClassName(), info_msg) return is_converged
def cs_print_warning(label, *args): KM.Logger.PrintWarning( colors.red("Warning: ") + colors.bold(label), " ".join(map(str, args)))
def UpdateSolution(self, r, x): self.R.appendleft(deepcopy(r)) self.X.appendleft(x + r) # r = x~ - x row = len(r) col = len(self.R) - 1 k = col num_old_matrices = len(self.v_old_matrices) if self.V_old == [] and self.W_old == []: # No previous vectors to reuse if k == 0: ## For the first iteration in the first time step, do relaxation only if self.echo_level > 3: cs_print_info( self._ClassName(), "Doing relaxation in the first iteration with factor = ", "{0:.1g}".format(self.alpha)) return self.alpha * r else: if self.echo_level > 3: cs_print_info(self._ClassName(), "Doing multi-vector extrapolation") cs_print_info(self._ClassName(), "Number of new modes: ", col) self.V_new = np.empty(shape=(col, row)) # will be transposed later for i in range(0, col): self.V_new[i] = self.R[i] - self.R[i + 1] self.V_new = self.V_new.T V = self.V_new ## Check the dimension of the newly constructed matrix if (V.shape[0] < V.shape[1]) and self.echo_level > 0: cs_print_warning( self._ClassName(), ": " + colors.red( "WARNING: column number larger than row number!")) ## Construct matrix W(differences of predictions) self.W_new = np.empty(shape=(col, row)) # will be transposed later for i in range(0, col): self.W_new[i] = self.X[i] - self.X[i + 1] self.W_new = self.W_new.T W = self.W_new ## Solve least-squares problem delta_r = -self.R[0] c = np.linalg.lstsq(V, delta_r)[0] ## Compute the update delta_x = np.dot(W, c) - delta_r return delta_x else: # previous vectors can be reused if k == 0: # first iteration if self.echo_level > 3: cs_print_info(self._ClassName(), "Using matrices from previous time steps") cs_print_info(self._ClassName(), "Number of previous matrices: ", num_old_matrices) V = self.V_old W = self.W_old ## Solve least-squares problem delta_r = -self.R[0] c = np.linalg.lstsq(V, delta_r)[0] ## Compute the update delta_x = np.dot(W, c) - delta_r return delta_x else: ## For other iterations, construct new V and W matrices and combine them with old ones if self.echo_level > 3: cs_print_info(self._ClassName(), "Doing multi-vector extrapolation") cs_print_info(self._ClassName(), "Number of new modes: ", col) cs_print_info(self._ClassName(), "Number of previous matrices: ", num_old_matrices) ## Construct matrix V (differences of residuals) self.V_new = np.empty(shape=(col, row)) # will be transposed later for i in range(0, col): self.V_new[i] = self.R[i] - self.R[i + 1] self.V_new = self.V_new.T V = np.hstack((self.V_new, self.V_old)) ## Check the dimension of the newly constructed matrix if (V.shape[0] < V.shape[1]) and self.echo_level > 0: cs_print_warning( self._ClassName(), ": " + colors.red( "WARNING: column number larger than row number!")) ## Construct matrix W(differences of predictions) self.W_new = np.empty(shape=(col, row)) # will be transposed later for i in range(0, col): self.W_new[i] = self.X[i] - self.X[i + 1] self.W_new = self.W_new.T W = np.hstack((self.W_new, self.W_old)) ## Solve least-squares problem delta_r = -self.R[0] c = np.linalg.lstsq(V, delta_r)[0] ## Compute the update delta_x = np.dot(W, c) - delta_r return delta_x