void clear_data() { rk->clear_zero(); for(int i=0; i< KOLENTER; i++) gtk_entry_set_text(GTK_ENTRY(entry[i]),""); gtk_widget_grab_focus(entry[0]); }
bool Sol_MultigridPressure3DBase::solve(double &residual, double tolerance, int max_iter) { if (!check_float(tolerance)) { printf("[ERROR] Sol_MultigridPressure3DDevice::solve - garbage tolerance value %f\n", tolerance); return false; } if (tolerance < 0) { printf("[ERROR] Sol_MultigridPressure3DDevice::solve - negative tolerance value %f\n", tolerance); return false; } if (max_iter <= 0) { printf("[WARNING] Sol_MultigridPressure3DDevice::solve - non-positive max_iter %d\n", max_iter); return false; } double l2, linf; if (!do_fmg(tolerance, max_iter, l2, linf)) { // try again with initual solution vector set to 0. This can fix the problem // of certain error modes growing when resuing the previous solution as a // starting point. printf("[WARNING] Sol_MultigridPressure3DBase::solve - do_fmg did not converge, retrying with zeroed initial search vector\n"); clear_zero(0); if (!do_fmg(tolerance, max_iter, l2, linf)) { printf("[WARNING] Sol_MultigridPressure3DBase::solve - do_fmg failed\n"); residual = (convergence == CONVERGENCE_L2) ? l2 : linf; return false; } } residual = (convergence == CONVERGENCE_L2) ? l2 : linf; //printf("residual = %g\n", residual); return true; }
//Конструктор vprov_nbs_gr_data() { kl_shift=0; window=NULL; clear_zero(); }
bool Sol_MultigridPressure3DBase::do_vcycle(double tolerance, int max_iter, double &result_l2, double &result_linf) { clear_error(); int level; int coarse_level = _num_levels-1; apply_boundary_conditions(0); double orig_l2=0, orig_linf=0; restrict_residuals(0,0, (convergence & CONVERGENCE_CALC_L2) ? &orig_l2 : 0, (convergence & CONVERGENCE_CALC_LINF) ? &orig_linf : 0); //printf("Error Before: l2 = %f, linf = %f\n", orig_l2, orig_linf); double orig_error = (convergence & CONVERGENCE_CRITERIA_L2) ? orig_l2 : (convergence & CONVERGENCE_CRITERIA_LINF) ? orig_linf : 1e20; if (orig_error < tolerance) { if (convergence & CONVERGENCE_CALC_L2) result_l2 = orig_l2; if (convergence & CONVERGENCE_CALC_LINF) result_linf = orig_linf; return true; } for (int i_cyc = 0; i_cyc < max_iter; i_cyc++) { // going down for (level = 0; level < coarse_level; level++) { relax(level, nu1, RO_RED_BLACK); clear_zero(level+1); apply_boundary_conditions(level+1); if (level == 0) { restrict_residuals(0, 1, (convergence & CONVERGENCE_CALC_L2) ? &result_l2 : 0, (convergence & CONVERGENCE_CALC_LINF) ? &result_linf : 0); double residual = (convergence & CONVERGENCE_CRITERIA_L2) ? result_l2 : (convergence & CONVERGENCE_CRITERIA_LINF) ? result_linf : 1e20; //printf("%d: residual = %.12f\n", i_cyc, result_linf); // if we're below tolerance, or we're no longer converging, bail out if (residual < tolerance) { // last time through, we need to apply boundary condition to u[0], since we just relaxed (above), but haven't propagated changes to ghost cells. // in the case we are not finished, by the time we get back to level 0 (via coarsening & then prolongation), ghost cells would be filled in. // but since we are bailing here, we need to explicitly make ghost cells up-to-date with u. apply_boundary_conditions(0); //printf("[INFO] Sol_MultigridPressure3DBase::do_vcycle - error after %d iterations: L2 = %f (%fx), Linf = %f (%fx)\n", i_cyc, result_l2, orig_l2 / result_l2, result_linf, orig_linf / result_linf); return !any_error(); } } else restrict_residuals(level, level+1, 0, 0); } // these relaxation steps are essentially free, so do lots of them // (reference implementation uses nu1+nu2) - this is probably overkill, i need to revisit this // with a good heuristic. Inhomogeneous conditions require more iterations. int coarse_iters = max3(nx(coarse_level)*ny(coarse_level), ny(coarse_level)*nz(coarse_level), nx(coarse_level)*nz(coarse_level))/2; relax(coarse_level, coarse_iters, make_symmetric_operator ? RO_SYMMETRIC : RO_RED_BLACK); //relax(coarse_level, (nx(coarse_level)*ny(coarse_level)*nz(coarse_level))/2); // going up for (level = coarse_level-1; level >= 0; level--) { prolong(level+1, level); // don't need to relax finest grid since it will get relaxed at the beginning of the next v-cycle if (level > 0) relax(level, nu2, make_symmetric_operator ? RO_BLACK_RED : RO_RED_BLACK); } } if (!(convergence & CONVERGENCE_CRITERIA_NONE)) printf("[WARNING] Sol_MultigridPressure3DBase::do_vcycle - Failed to converge, error after: L2 = %f (%fx), Linf = %f (%fx)\n", result_l2, orig_l2 / result_l2, result_linf, orig_linf / result_linf); return false; }
bool Sol_MultigridPressure3DBase::do_fmg(double tolerance, int max_iter, double &result_l2, double &result_linf) { CPUTimer timer; timer.start(); clear_error(); int level_ncyc; int level; result_l2 = result_linf = 0; apply_boundary_conditions(0); double orig_l2=0, orig_linf=0; restrict_residuals(0,0, (convergence & CONVERGENCE_CALC_L2) ? &orig_l2 : 0, (convergence & CONVERGENCE_CALC_LINF) ? &orig_linf : 0); //printf("Error Before: l2 = %f, linf = %f\n", orig_l2, orig_linf); double orig_error = (convergence & CONVERGENCE_CRITERIA_L2) ? orig_l2 : (convergence & CONVERGENCE_CRITERIA_LINF) ? orig_linf : 1e20; if (orig_error < tolerance) { if (convergence & CONVERGENCE_CALC_L2) result_l2 = orig_l2; if (convergence & CONVERGENCE_CALC_LINF) result_linf = orig_linf; return true; } #if 0 // for testing relaxation only, enable this code block double iter_l2, iter_linf; for (int o=0; o < 100; o++) { relax(0, 10, RO_SYMMETRIC); restrict_residuals(0, 0, &iter_l2, &iter_linf); printf("error: l2 = %.12f, linf = %.12f\n", iter_l2, iter_linf); } printf("reduction: l2 = %f, linf = %f\n", orig_l2/iter_l2, orig_linf/iter_linf); result_l2 = iter_l2; result_linf = iter_linf; return true; #endif // initialize all the residuals. // we need this because in the FMG loop below, we don't necessarily start at level 0, but // rather 2 levels from the finest. Which means we first need to propagate the errors all the way down first before // beginning FMG. int coarse_level = _num_levels-1; int num_vcyc = 0; for (level = 0; level < _num_levels-1; level++) { // initialize U (solution) at next level to zero clear_zero(level+1); apply_boundary_conditions(level+1); // restrict residuals to the next level. restrict_residuals(level, level+1,0,0); } // do the full-multigrid loop for (int fine_level = _num_levels-1; fine_level >= 0 ; fine_level--) { //{ int fine_level = 0; // do a single v-cycle instead // we always do one extra v-cycle level_ncyc = (fine_level == 0) ? max_iter+1 : 1; // do ncyc v-cycle's for (int i_cyc = 0; i_cyc < level_ncyc; i_cyc++) { if (fine_level == 0) num_vcyc++; // going down for (level = fine_level; level < coarse_level; level++) { relax(level, nu1, RO_RED_BLACK); clear_zero(level+1); apply_boundary_conditions(level+1); if (level == 0) { restrict_residuals(0, 1, (convergence & CONVERGENCE_CALC_L2) ? &result_l2 : 0, (convergence & CONVERGENCE_CALC_LINF) ? &result_linf : 0); double residual = (convergence & CONVERGENCE_CRITERIA_L2) ? result_l2 : (convergence & CONVERGENCE_CRITERIA_LINF) ? result_linf : 1e20; if (ThreadManager::this_image() == 0) printf("%d: residual = %.12f,%.12f\n", i_cyc, result_linf, result_l2); // if we're below tolerance, or we're no longer converging, bail out if (residual < tolerance) { // last time through, we need to apply boundary condition to u[0], since we just relaxed (above), but haven't propagated changes to ghost cells. // in the case we are not finished, by the time we get back to level 0 (via coarsening & then prolongation), ghost cells would be filled in. // but since we are bailing here, we need to explicitly make ghost cells up-to-date with u. apply_boundary_conditions(0); timer.stop(); //printf("[ELAPSED] Sol_MultigridPressure3DBase::do_fmg - converged in %fms\n", timer.elapsed_ms()); printf("[INFO] Sol_MultigridPressure3DBase::do_fmg - error after %d iterations: L2 = %f (%fx), Linf = %f (%fx)\n", i_cyc, result_l2, orig_l2 / result_l2, result_linf, orig_linf / result_linf); global_counter_add("vcycles", num_vcyc); return !any_error(); } } else restrict_residuals(level, level+1, 0, 0); } // these relaxation steps are essentially free, so do lots of them // (reference implementation uses nu1+nu2) - this is probably overkill, i need to revisit this // with a good heuristic. Inhomogeneous conditions require more iterations. int coarse_iters = max3(nx(coarse_level)*ny(coarse_level), ny(coarse_level)*nz(coarse_level), nx(coarse_level)*nz(coarse_level))/2; relax(coarse_level, coarse_iters, make_symmetric_operator ? RO_SYMMETRIC : RO_RED_BLACK); //relax(coarse_level, (nx(coarse_level)*ny(coarse_level)*nz(coarse_level))/2); // going up for (level = coarse_level-1; level >= fine_level; level--) { prolong(level+1, level); // don't need to relax finest grid since it will get relaxed at the beginning of the next v-cycle if (level > 0) relax(level, nu2, make_symmetric_operator ? RO_BLACK_RED : RO_RED_BLACK); } } if (fine_level > 0) { // if not at finest level, need to prolong once more to next finer level for the next fine_level value prolong(fine_level, fine_level-1); } } timer.stop(); //printf("[ELAPSED] Sol_MultigridPressure3DBase::do_fmg - stopped iterations after %fms\n", timer.elapsed_ms()); if (!(convergence & CONVERGENCE_CRITERIA_NONE)) printf("[WARNING] Sol_MultigridPressure3DBase::do_fmg - Failed to converge, error after: L2 = %.12f (%fx), Linf = %.12f (%fx)\n", result_l2, orig_l2 / result_l2, result_linf, orig_linf / result_linf); return false; }