HYPRE_Int hypre_SMGSolve( void *smg_vdata, hypre_StructMatrix *A, hypre_StructVector *b, hypre_StructVector *x ) { hypre_SMGData *smg_data = smg_vdata; double tol = (smg_data -> tol); HYPRE_Int max_iter = (smg_data -> max_iter); HYPRE_Int rel_change = (smg_data -> rel_change); HYPRE_Int zero_guess = (smg_data -> zero_guess); HYPRE_Int num_levels = (smg_data -> num_levels); HYPRE_Int num_pre_relax = (smg_data -> num_pre_relax); HYPRE_Int num_post_relax = (smg_data -> num_post_relax); hypre_IndexRef base_index = (smg_data -> base_index); hypre_IndexRef base_stride = (smg_data -> base_stride); hypre_StructMatrix **A_l = (smg_data -> A_l); hypre_StructMatrix **PT_l = (smg_data -> PT_l); hypre_StructMatrix **R_l = (smg_data -> R_l); hypre_StructVector **b_l = (smg_data -> b_l); hypre_StructVector **x_l = (smg_data -> x_l); hypre_StructVector **r_l = (smg_data -> r_l); hypre_StructVector **e_l = (smg_data -> e_l); void **relax_data_l = (smg_data -> relax_data_l); void **residual_data_l = (smg_data -> residual_data_l); void **restrict_data_l = (smg_data -> restrict_data_l); void **interp_data_l = (smg_data -> interp_data_l); HYPRE_Int logging = (smg_data -> logging); double *norms = (smg_data -> norms); double *rel_norms = (smg_data -> rel_norms); double b_dot_b = 0, r_dot_r, eps = 0; double e_dot_e = 0, x_dot_x = 1; HYPRE_Int i, l; #if DEBUG char filename[255]; #endif /*----------------------------------------------------- * Initialize some things and deal with special cases *-----------------------------------------------------*/ hypre_BeginTiming(smg_data -> time_index); hypre_StructMatrixDestroy(A_l[0]); hypre_StructVectorDestroy(b_l[0]); hypre_StructVectorDestroy(x_l[0]); A_l[0] = hypre_StructMatrixRef(A); b_l[0] = hypre_StructVectorRef(b); x_l[0] = hypre_StructVectorRef(x); (smg_data -> num_iterations) = 0; /* if max_iter is zero, return */ if (max_iter == 0) { /* if using a zero initial guess, return zero */ if (zero_guess) { hypre_StructVectorSetConstantValues(x, 0.0); } hypre_EndTiming(smg_data -> time_index); return hypre_error_flag; } /* part of convergence check */ if (tol > 0.0) { /* eps = (tol^2) */ b_dot_b = hypre_StructInnerProd(b_l[0], b_l[0]); eps = tol*tol; /* if rhs is zero, return a zero solution */ if (b_dot_b == 0.0) { hypre_StructVectorSetConstantValues(x, 0.0); if (logging > 0) { norms[0] = 0.0; rel_norms[0] = 0.0; } hypre_EndTiming(smg_data -> time_index); return hypre_error_flag; } } /*----------------------------------------------------- * Do V-cycles: * For each index l, "fine" = l, "coarse" = (l+1) *-----------------------------------------------------*/ for (i = 0; i < max_iter; i++) { /*-------------------------------------------------- * Down cycle *--------------------------------------------------*/ /* fine grid pre-relaxation */ if (num_levels > 1) { hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 0, 0); hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 1, 1); } hypre_SMGRelaxSetMaxIter(relax_data_l[0], num_pre_relax); hypre_SMGRelaxSetZeroGuess(relax_data_l[0], zero_guess); hypre_SMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]); zero_guess = 0; /* compute fine grid residual (b - Ax) */ hypre_SMGResidual(residual_data_l[0], A_l[0], x_l[0], b_l[0], r_l[0]); /* convergence check */ if (tol > 0.0) { r_dot_r = hypre_StructInnerProd(r_l[0], r_l[0]); if (logging > 0) { norms[i] = sqrt(r_dot_r); if (b_dot_b > 0) rel_norms[i] = sqrt(r_dot_r/b_dot_b); else rel_norms[i] = 0.0; } /* always do at least 1 V-cycle */ if ((r_dot_r/b_dot_b < eps) && (i > 0)) { if (rel_change) { if ((e_dot_e/x_dot_x) < eps) break; } else { break; } } } if (num_levels > 1) { /* restrict fine grid residual */ hypre_SemiRestrict(restrict_data_l[0], R_l[0], r_l[0], b_l[1]); #if DEBUG if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3) { hypre_sprintf(filename, "zout_xdown.%02d", 0); hypre_StructVectorPrint(filename, x_l[0], 0); hypre_sprintf(filename, "zout_rdown.%02d", 0); hypre_StructVectorPrint(filename, r_l[0], 0); hypre_sprintf(filename, "zout_b.%02d", 1); hypre_StructVectorPrint(filename, b_l[1], 0); } #endif for (l = 1; l <= (num_levels - 2); l++) { /* pre-relaxation */ hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 0, 0); hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 1, 1); hypre_SMGRelaxSetMaxIter(relax_data_l[l], num_pre_relax); hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 1); hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); /* compute residual (b - Ax) */ hypre_SMGResidual(residual_data_l[l], A_l[l], x_l[l], b_l[l], r_l[l]); /* restrict residual */ hypre_SemiRestrict(restrict_data_l[l], R_l[l], r_l[l], b_l[l+1]); #if DEBUG if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3) { hypre_sprintf(filename, "zout_xdown.%02d", l); hypre_StructVectorPrint(filename, x_l[l], 0); hypre_sprintf(filename, "zout_rdown.%02d", l); hypre_StructVectorPrint(filename, r_l[l], 0); hypre_sprintf(filename, "zout_b.%02d", l+1); hypre_StructVectorPrint(filename, b_l[l+1], 0); } #endif } /*-------------------------------------------------- * Bottom *--------------------------------------------------*/ hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 1); hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); #if DEBUG if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3) { hypre_sprintf(filename, "zout_xbottom.%02d", l); hypre_StructVectorPrint(filename, x_l[l], 0); } #endif /*-------------------------------------------------- * Up cycle *--------------------------------------------------*/ for (l = (num_levels - 2); l >= 1; l--) { /* interpolate error and correct (x = x + Pe_c) */ hypre_SemiInterp(interp_data_l[l], PT_l[l], x_l[l+1], e_l[l]); hypre_StructAxpy(1.0, e_l[l], x_l[l]); #if DEBUG if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3) { hypre_sprintf(filename, "zout_eup.%02d", l); hypre_StructVectorPrint(filename, e_l[l], 0); hypre_sprintf(filename, "zout_xup.%02d", l); hypre_StructVectorPrint(filename, x_l[l], 0); } #endif /* post-relaxation */ hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 0, 1); hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 1, 0); hypre_SMGRelaxSetMaxIter(relax_data_l[l], num_post_relax); hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 0); hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]); } /* interpolate error and correct on fine grid (x = x + Pe_c) */ hypre_SemiInterp(interp_data_l[0], PT_l[0], x_l[1], e_l[0]); hypre_SMGAxpy(1.0, e_l[0], x_l[0], base_index, base_stride); #if DEBUG if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3) { hypre_sprintf(filename, "zout_eup.%02d", 0); hypre_StructVectorPrint(filename, e_l[0], 0); hypre_sprintf(filename, "zout_xup.%02d", 0); hypre_StructVectorPrint(filename, x_l[0], 0); } #endif } /* part of convergence check */ if ((tol > 0.0) && (rel_change)) { if (num_levels > 1) { e_dot_e = hypre_StructInnerProd(e_l[0], e_l[0]); x_dot_x = hypre_StructInnerProd(x_l[0], x_l[0]); } else { e_dot_e = 0.0; x_dot_x = 1.0; } } /* fine grid post-relaxation */ if (num_levels > 1) { hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 0, 1); hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 1, 0); } hypre_SMGRelaxSetMaxIter(relax_data_l[0], num_post_relax); hypre_SMGRelaxSetZeroGuess(relax_data_l[0], 0); hypre_SMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]); (smg_data -> num_iterations) = (i + 1); } hypre_EndTiming(smg_data -> time_index); return hypre_error_flag; }
int hypre_SMGRelax( void *relax_vdata, hypre_StructMatrix *A, hypre_StructVector *b, hypre_StructVector *x ) { hypre_SMGRelaxData *relax_data = relax_vdata; int zero_guess; int stencil_dim; hypre_StructVector *temp_vec; hypre_StructMatrix *A_sol; hypre_StructMatrix *A_rem; void **residual_data; void **solve_data; hypre_IndexRef base_stride; hypre_BoxArray *base_box_a; double zero = 0.0; int max_iter; int num_spaces; int *space_ranks; int i, j, k, is; int ierr = 0; /*---------------------------------------------------------- * Note: The zero_guess stuff is not handled correctly * for general relaxation parameters. It is correct when * the spaces are independent sets in the direction of * relaxation. *----------------------------------------------------------*/ hypre_BeginTiming(relax_data -> time_index); /*---------------------------------------------------------- * Set up the solver *----------------------------------------------------------*/ /* insure that the solver memory gets fully set up */ if ((relax_data -> setup_a_sol) > 0) { (relax_data -> setup_a_sol) = 2; } hypre_SMGRelaxSetup(relax_vdata, A, b, x); zero_guess = (relax_data -> zero_guess); stencil_dim = (relax_data -> stencil_dim); temp_vec = (relax_data -> temp_vec); A_sol = (relax_data -> A_sol); A_rem = (relax_data -> A_rem); residual_data = (relax_data -> residual_data); solve_data = (relax_data -> solve_data); /*---------------------------------------------------------- * Set zero values *----------------------------------------------------------*/ if (zero_guess) { base_stride = (relax_data -> base_stride); base_box_a = (relax_data -> base_box_array); ierr = hypre_SMGSetStructVectorConstantValues(x, zero, base_box_a, base_stride); } /*---------------------------------------------------------- * Iterate *----------------------------------------------------------*/ for (k = 0; k < 2; k++) { switch(k) { /* Do pre-relaxation iterations */ case 0: max_iter = 1; num_spaces = (relax_data -> num_pre_spaces); space_ranks = (relax_data -> pre_space_ranks); break; /* Do regular relaxation iterations */ case 1: max_iter = (relax_data -> max_iter); num_spaces = (relax_data -> num_reg_spaces); space_ranks = (relax_data -> reg_space_ranks); break; } for (i = 0; i < max_iter; i++) { for (j = 0; j < num_spaces; j++) { is = space_ranks[j]; hypre_SMGResidual(residual_data[is], A_rem, x, b, temp_vec); if (stencil_dim > 2) hypre_SMGSolve(solve_data[is], A_sol, temp_vec, x); else hypre_CyclicReduction(solve_data[is], A_sol, temp_vec, x); } (relax_data -> num_iterations) = (i + 1); } } /*---------------------------------------------------------- * Free up memory according to memory_use parameter *----------------------------------------------------------*/ if ((stencil_dim - 1) <= (relax_data -> memory_use)) { hypre_SMGRelaxDestroyASol(relax_vdata); } hypre_EndTiming(relax_data -> time_index); return ierr; }