HYPRE_Real hypre_StructKrylovInnerProd( void *x, void *y ) { return ( hypre_StructInnerProd( (hypre_StructVector *) x, (hypre_StructVector *) y ) ); }
HYPRE_Int hypre_SStructPInnerProd( hypre_SStructPVector *px, hypre_SStructPVector *py, double *presult_ptr ) { HYPRE_Int nvars = hypre_SStructPVectorNVars(px); double presult; double sresult; HYPRE_Int var; presult = 0.0; for (var = 0; var < nvars; var++) { sresult = hypre_StructInnerProd(hypre_SStructPVectorSVector(px, var), hypre_SStructPVectorSVector(py, var)); presult += sresult; } *presult_ptr = presult; return hypre_error_flag; }
hypre_int main( hypre_int argc, char *argv[] ) { HYPRE_Int arg_index; HYPRE_Int print_usage; HYPRE_Int nx, ny, nz; HYPRE_Int P, Q, R; HYPRE_Int bx, by, bz; HYPRE_StructGrid from_grid, to_grid; HYPRE_StructVector from_vector, to_vector, check_vector; HYPRE_CommPkg comm_pkg; HYPRE_Int time_index; HYPRE_Int num_procs, myid; HYPRE_Int p, q, r; HYPRE_Int dim; HYPRE_Int nblocks ; HYPRE_Int **ilower, **iupper, **iupper2; HYPRE_Int istart[3]; HYPRE_Int i, ix, iy, iz, ib; HYPRE_Int print_system = 0; HYPRE_Real check; /*----------------------------------------------------------- * Initialize some stuff *-----------------------------------------------------------*/ /* Initialize MPI */ hypre_MPI_Init(&argc, &argv); hypre_MPI_Comm_size(hypre_MPI_COMM_WORLD, &num_procs ); hypre_MPI_Comm_rank(hypre_MPI_COMM_WORLD, &myid ); /*----------------------------------------------------------- * Set defaults *-----------------------------------------------------------*/ dim = 3; nx = 2; ny = 2; nz = 2; P = num_procs; Q = 1; R = 1; bx = 1; by = 1; bz = 1; istart[0] = 1; istart[1] = 1; istart[2] = 1; /*----------------------------------------------------------- * Parse command line *-----------------------------------------------------------*/ print_usage = 0; arg_index = 1; while (arg_index < argc) { if ( strcmp(argv[arg_index], "-n") == 0 ) { arg_index++; nx = atoi(argv[arg_index++]); ny = atoi(argv[arg_index++]); nz = atoi(argv[arg_index++]); } else if ( strcmp(argv[arg_index], "-istart") == 0 ) { arg_index++; istart[0] = atoi(argv[arg_index++]); istart[1] = atoi(argv[arg_index++]); istart[2] = atoi(argv[arg_index++]); } else if ( strcmp(argv[arg_index], "-P") == 0 ) { arg_index++; P = atoi(argv[arg_index++]); Q = atoi(argv[arg_index++]); R = atoi(argv[arg_index++]); } else if ( strcmp(argv[arg_index], "-b") == 0 ) { arg_index++; bx = atoi(argv[arg_index++]); by = atoi(argv[arg_index++]); bz = atoi(argv[arg_index++]); } else if ( strcmp(argv[arg_index], "-d") == 0 ) { arg_index++; dim = atoi(argv[arg_index++]); } else if ( strcmp(argv[arg_index], "-print") == 0 ) { arg_index++; print_system = 1; } else if ( strcmp(argv[arg_index], "-help") == 0 ) { print_usage = 1; break; } else { arg_index++; } } /*----------------------------------------------------------- * Print usage info *-----------------------------------------------------------*/ if ( (print_usage) && (myid == 0) ) { hypre_printf("\n"); hypre_printf("Usage: %s [<options>]\n", argv[0]); hypre_printf("\n"); hypre_printf(" -n <nx> <ny> <nz> : problem size per block\n"); hypre_printf(" -istart <ix> <iy> <iz> : start of box\n"); hypre_printf(" -P <Px> <Py> <Pz> : processor topology\n"); hypre_printf(" -b <bx> <by> <bz> : blocking per processor\n"); hypre_printf(" -d <dim> : problem dimension (2 or 3)\n"); hypre_printf(" -print : print vectors\n"); hypre_printf("\n"); } if ( print_usage ) { exit(1); } /*----------------------------------------------------------- * Check a few things *-----------------------------------------------------------*/ if ((P*Q*R) > num_procs) { if (myid == 0) { hypre_printf("Error: PxQxR is more than the number of processors\n"); } exit(1); } else if ((P*Q*R) < num_procs) { if (myid == 0) { hypre_printf("Warning: PxQxR is less than the number of processors\n"); } } /*----------------------------------------------------------- * Print driver parameters *-----------------------------------------------------------*/ if (myid == 0) { hypre_printf("Running with these driver parameters:\n"); hypre_printf(" (nx, ny, nz) = (%d, %d, %d)\n", nx, ny, nz); hypre_printf(" (ix, iy, iz) = (%d, %d, %d)\n", istart[0],istart[1],istart[2]); hypre_printf(" (Px, Py, Pz) = (%d, %d, %d)\n", P, Q, R); hypre_printf(" (bx, by, bz) = (%d, %d, %d)\n", bx, by, bz); hypre_printf(" dim = %d\n", dim); } /*----------------------------------------------------------- * Set up the stencil structure (7 points) when matrix is NOT read from file * Set up the grid structure used when NO files are read *-----------------------------------------------------------*/ switch (dim) { case 1: nblocks = bx; p = myid % P; break; case 2: nblocks = bx*by; p = myid % P; q = (( myid - p)/P) % Q; break; case 3: nblocks = bx*by*bz; p = myid % P; q = (( myid - p)/P) % Q; r = ( myid - p - P*q)/( P*Q ); break; } if (myid >= (P*Q*R)) { /* My processor has no data on it */ nblocks = bx = by = bz = 0; } /*----------------------------------------------------------- * prepare space for the extents *-----------------------------------------------------------*/ ilower = hypre_CTAlloc(HYPRE_Int*, nblocks); iupper = hypre_CTAlloc(HYPRE_Int*, nblocks); iupper2 = hypre_CTAlloc(HYPRE_Int*, nblocks); for (i = 0; i < nblocks; i++) { ilower[i] = hypre_CTAlloc(HYPRE_Int, dim); iupper[i] = hypre_CTAlloc(HYPRE_Int, dim); iupper2[i] = hypre_CTAlloc(HYPRE_Int, dim); } ib = 0; switch (dim) { case 1: for (ix = 0; ix < bx; ix++) { ilower[ib][0] = istart[0]+ nx*(bx*p+ix); iupper[ib][0] = istart[0]+ nx*(bx*p+ix+1) - 1; iupper2[ib][0] = iupper[ib][0]; if ( (ix == (bx-1)) && (p < (P-1)) ) iupper2[ib][0] = iupper[ib][0] + 1; ib++; } break; case 2: for (iy = 0; iy < by; iy++) for (ix = 0; ix < bx; ix++) { ilower[ib][0] = istart[0]+ nx*(bx*p+ix); iupper[ib][0] = istart[0]+ nx*(bx*p+ix+1) - 1; ilower[ib][1] = istart[1]+ ny*(by*q+iy); iupper[ib][1] = istart[1]+ ny*(by*q+iy+1) - 1; iupper2[ib][0] = iupper[ib][0]; iupper2[ib][1] = iupper[ib][1]; if ( (ix == (bx-1)) && (p < (P-1)) ) iupper2[ib][0] = iupper[ib][0] + 1; if ( (iy == (by-1)) && (q < (Q-1)) ) iupper2[ib][1] = iupper[ib][1] + 1; ib++; } break; case 3: for (iz = 0; iz < bz; iz++) for (iy = 0; iy < by; iy++) for (ix = 0; ix < bx; ix++) { ilower[ib][0] = istart[0]+ nx*(bx*p+ix); iupper[ib][0] = istart[0]+ nx*(bx*p+ix+1) - 1; ilower[ib][1] = istart[1]+ ny*(by*q+iy); iupper[ib][1] = istart[1]+ ny*(by*q+iy+1) - 1; ilower[ib][2] = istart[2]+ nz*(bz*r+iz); iupper[ib][2] = istart[2]+ nz*(bz*r+iz+1) - 1; iupper2[ib][0] = iupper[ib][0]; iupper2[ib][1] = iupper[ib][1]; iupper2[ib][2] = iupper[ib][2]; if ( (ix == (bx-1)) && (p < (P-1)) ) iupper2[ib][0] = iupper[ib][0] + 1; if ( (iy == (by-1)) && (q < (Q-1)) ) iupper2[ib][1] = iupper[ib][1] + 1; if ( (iz == (bz-1)) && (r < (R-1)) ) iupper2[ib][2] = iupper[ib][2] + 1; ib++; } break; } HYPRE_StructGridCreate(hypre_MPI_COMM_WORLD, dim, &from_grid); HYPRE_StructGridCreate(hypre_MPI_COMM_WORLD, dim, &to_grid); for (ib = 0; ib < nblocks; ib++) { HYPRE_StructGridSetExtents(from_grid, ilower[ib], iupper[ib]); HYPRE_StructGridSetExtents(to_grid, ilower[ib], iupper2[ib]); } HYPRE_StructGridAssemble(from_grid); HYPRE_StructGridAssemble(to_grid); /*----------------------------------------------------------- * Set up the vectors *-----------------------------------------------------------*/ HYPRE_StructVectorCreate(hypre_MPI_COMM_WORLD, from_grid, &from_vector); HYPRE_StructVectorInitialize(from_vector); AddValuesVector(from_grid, from_vector, 1.0); HYPRE_StructVectorAssemble(from_vector); HYPRE_StructVectorCreate(hypre_MPI_COMM_WORLD, to_grid, &to_vector); HYPRE_StructVectorInitialize(to_vector); AddValuesVector(to_grid, to_vector, 0.0); HYPRE_StructVectorAssemble(to_vector); /* Vector used to check the migration */ HYPRE_StructVectorCreate(hypre_MPI_COMM_WORLD, to_grid, &check_vector); HYPRE_StructVectorInitialize(check_vector); AddValuesVector(to_grid, check_vector, 1.0); HYPRE_StructVectorAssemble(check_vector); /*----------------------------------------------------------- * Migrate *-----------------------------------------------------------*/ time_index = hypre_InitializeTiming("Struct Migrate"); hypre_BeginTiming(time_index); HYPRE_StructVectorGetMigrateCommPkg(from_vector, to_vector, &comm_pkg); HYPRE_StructVectorMigrate(comm_pkg, from_vector, to_vector); HYPRE_CommPkgDestroy(comm_pkg); hypre_EndTiming(time_index); hypre_PrintTiming("Struct Migrate", hypre_MPI_COMM_WORLD); hypre_FinalizeTiming(time_index); /*----------------------------------------------------------- * Check the migration and print the result *-----------------------------------------------------------*/ hypre_StructAxpy(-1.0, to_vector, check_vector); check = hypre_StructInnerProd (check_vector, check_vector); if (myid == 0) { printf("\nCheck = %1.0f (success = 0)\n\n", check); } /*----------------------------------------------------------- * Print out the vectors *-----------------------------------------------------------*/ if (print_system) { HYPRE_StructVectorPrint("struct_migrate.out.xfr", from_vector, 0); HYPRE_StructVectorPrint("struct_migrate.out.xto", to_vector, 0); } /*----------------------------------------------------------- * Finalize things *-----------------------------------------------------------*/ HYPRE_StructGridDestroy(from_grid); HYPRE_StructGridDestroy(to_grid); for (i = 0; i < nblocks; i++) { hypre_TFree(ilower[i]); hypre_TFree(iupper[i]); hypre_TFree(iupper2[i]); } hypre_TFree(ilower); hypre_TFree(iupper); hypre_TFree(iupper2); HYPRE_StructVectorDestroy(from_vector); HYPRE_StructVectorDestroy(to_vector); HYPRE_StructVectorDestroy(check_vector); /* Finalize MPI */ hypre_MPI_Finalize(); return (0); }
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; }
HYPRE_Int hypre_SparseMSGSolve( void *smsg_vdata, hypre_StructMatrix *A, hypre_StructVector *b, hypre_StructVector *x ) { hypre_SparseMSGData *smsg_data = smsg_vdata; HYPRE_Real tol = (smsg_data -> tol); HYPRE_Int max_iter = (smsg_data -> max_iter); HYPRE_Int rel_change = (smsg_data -> rel_change); HYPRE_Int zero_guess = (smsg_data -> zero_guess); HYPRE_Int jump = (smsg_data -> jump); HYPRE_Int num_pre_relax = (smsg_data -> num_pre_relax); HYPRE_Int num_post_relax = (smsg_data -> num_post_relax); HYPRE_Int num_fine_relax = (smsg_data -> num_fine_relax); HYPRE_Int *num_grids = (smsg_data -> num_grids); HYPRE_Int num_all_grids = (smsg_data -> num_all_grids); HYPRE_Int num_levels = (smsg_data -> num_levels); hypre_StructMatrix **A_array = (smsg_data -> A_array); hypre_StructMatrix **Px_array = (smsg_data -> Px_array); hypre_StructMatrix **Py_array = (smsg_data -> Py_array); hypre_StructMatrix **Pz_array = (smsg_data -> Pz_array); hypre_StructMatrix **RTx_array = (smsg_data -> RTx_array); hypre_StructMatrix **RTy_array = (smsg_data -> RTy_array); hypre_StructMatrix **RTz_array = (smsg_data -> RTz_array); hypre_StructVector **b_array = (smsg_data -> b_array); hypre_StructVector **x_array = (smsg_data -> x_array); hypre_StructVector **t_array = (smsg_data -> t_array); hypre_StructVector **r_array = (smsg_data -> r_array); hypre_StructVector **e_array = (smsg_data -> e_array); hypre_StructVector **visitx_array = (smsg_data -> visitx_array); hypre_StructVector **visity_array = (smsg_data -> visity_array); hypre_StructVector **visitz_array = (smsg_data -> visitz_array); HYPRE_Int *grid_on = (smsg_data -> grid_on); void **relax_array = (smsg_data -> relax_array); void **matvec_array = (smsg_data -> matvec_array); void **restrictx_array = (smsg_data -> restrictx_array); void **restricty_array = (smsg_data -> restricty_array); void **restrictz_array = (smsg_data -> restrictz_array); void **interpx_array = (smsg_data -> interpx_array); void **interpy_array = (smsg_data -> interpy_array); void **interpz_array = (smsg_data -> interpz_array); HYPRE_Int logging = (smsg_data -> logging); HYPRE_Real *norms = (smsg_data -> norms); HYPRE_Real *rel_norms = (smsg_data -> rel_norms); HYPRE_Int *restrict_count; HYPRE_Real b_dot_b, r_dot_r, eps; HYPRE_Real e_dot_e, x_dot_x; HYPRE_Int i, l, lx, ly, lz; HYPRE_Int lymin, lymax, lzmin, lzmax; HYPRE_Int fi, ci; HYPRE_Int ierr = 0; #if DEBUG char filename[255]; #endif /*----------------------------------------------------- * Initialize some things and deal with special cases *-----------------------------------------------------*/ hypre_BeginTiming(smsg_data -> time_index); hypre_StructMatrixDestroy(A_array[0]); hypre_StructVectorDestroy(b_array[0]); hypre_StructVectorDestroy(x_array[0]); A_array[0] = hypre_StructMatrixRef(A); b_array[0] = hypre_StructVectorRef(b); x_array[0] = hypre_StructVectorRef(x); (smsg_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(smsg_data -> time_index); return ierr; } /* part of convergence check */ if (tol > 0.0) { /* eps = (tol^2) */ b_dot_b = hypre_StructInnerProd(b_array[0], b_array[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(smsg_data -> time_index); return ierr; } } restrict_count = hypre_TAlloc(HYPRE_Int, num_all_grids); /*----------------------------------------------------- * Do V-cycles: * For each index l, "fine" = l, "coarse" = (l+1) *-----------------------------------------------------*/ for (i = 0; i < max_iter; i++) { /*-------------------------------------------------- * Down cycle: * Note that r = b = x through the jump region *--------------------------------------------------*/ /* fine grid pre-relaxation */ hypre_PFMGRelaxSetPreRelax(relax_array[0]); hypre_PFMGRelaxSetMaxIter(relax_array[0], num_fine_relax); hypre_PFMGRelaxSetZeroGuess(relax_array[0], zero_guess); hypre_PFMGRelax(relax_array[0], A_array[0], b_array[0], x_array[0]); zero_guess = 0; /* compute fine grid residual (b - Ax) */ hypre_StructCopy(b_array[0], r_array[0]); hypre_StructMatvecCompute(matvec_array[0], -1.0, A_array[0], x_array[0], 1.0, r_array[0]); /* convergence check */ if (tol > 0.0) { r_dot_r = hypre_StructInnerProd(r_array[0], r_array[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; } /* RDF */ #if 0 hypre_printf("iter = %d, rel_norm = %e\n", i, rel_norms[i]); #endif /* 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) { /* initialize restrict_count */ for (fi = 0; fi < num_all_grids; fi++) { restrict_count[fi] = 0; } for (l = 0; l <= (num_levels - 2); l++) { lzmin = hypre_max((l - num_grids[1] - num_grids[0] + 2), 0); lzmax = hypre_min((l), (num_grids[2] - 1)); for (lz = lzmin; lz <= lzmax; lz++) { lymin = hypre_max((l - lz - num_grids[0] + 1), 0); lymax = hypre_min((l - lz), (num_grids[1] - 1)); for (ly = lymin; ly <= lymax; ly++) { lx = l - lz - ly; hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi); if (!grid_on[fi]) { break; } if (restrict_count[fi] > 1) { hypre_StructScale((1.0/restrict_count[fi]), b_array[fi]); } if (l > jump) { /* pre-relaxation */ hypre_PFMGRelaxSetPreRelax(relax_array[fi]); hypre_PFMGRelaxSetMaxIter(relax_array[fi], num_pre_relax); hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 1); hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi], x_array[fi]); /* compute residual (b - Ax) */ hypre_StructCopy(b_array[fi], r_array[fi]); hypre_StructMatvecCompute(matvec_array[fi], -1.0, A_array[fi], x_array[fi], 1.0, r_array[fi]); } if ((lx+1) < num_grids[0]) { /* restrict to ((lx+1), ly, lz) */ hypre_SparseMSGMapIndex((lx+1), ly, lz, num_grids, ci); if (grid_on[ci]) { if (restrict_count[ci]) { hypre_SparseMSGRestrict(restrictx_array[fi], RTx_array[lx], r_array[fi], t_array[ci]); hypre_StructAxpy(1.0, t_array[ci], b_array[ci]); } else { hypre_SparseMSGRestrict(restrictx_array[fi], RTx_array[lx], r_array[fi], b_array[ci]); } restrict_count[ci]++; } } if ((ly+1) < num_grids[1]) { /* restrict to (lx, (ly+1), lz) */ hypre_SparseMSGMapIndex(lx, (ly+1), lz, num_grids, ci); if (grid_on[ci]) { if (restrict_count[ci]) { hypre_SparseMSGRestrict(restricty_array[fi], RTy_array[ly], r_array[fi], t_array[ci]); hypre_StructAxpy(1.0, t_array[ci], b_array[ci]); } else { hypre_SparseMSGRestrict(restricty_array[fi], RTy_array[ly], r_array[fi], b_array[ci]); } restrict_count[ci]++; } } if ((lz+1) < num_grids[2]) { /* restrict to (lx, ly, (lz+1)) */ hypre_SparseMSGMapIndex(lx, ly, (lz+1), num_grids, ci); if (grid_on[ci]) { if (restrict_count[ci]) { hypre_SparseMSGRestrict(restrictz_array[fi], RTz_array[lz], r_array[fi], t_array[ci]); hypre_StructAxpy(1.0, t_array[ci], b_array[ci]); } else { hypre_SparseMSGRestrict(restrictz_array[fi], RTz_array[lz], r_array[fi], b_array[ci]); } restrict_count[ci]++; } } #if DEBUG hypre_sprintf(filename, "zoutSMSG_bdown.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, b_array[fi], 0); hypre_sprintf(filename, "zoutSMSG_xdown.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, x_array[fi], 0); hypre_sprintf(filename, "zoutSMSG_rdown.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, r_array[fi], 0); #endif } } } /*-------------------------------------------------- * Bottom *--------------------------------------------------*/ fi = num_all_grids - 1; if (restrict_count[fi] > 1) { hypre_StructScale((1.0/restrict_count[fi]), b_array[fi]); } hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 1); hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi], x_array[fi]); #if DEBUG hypre_sprintf(filename, "zoutSMSG_bbottom.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, b_array[fi], 0); hypre_sprintf(filename, "zoutSMSG_xbottom.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, x_array[fi], 0); #endif /*-------------------------------------------------- * Up cycle * Note that r = b = x through the jump region *--------------------------------------------------*/ for (l = (num_levels - 2); l >= 0; l--) { lzmin = hypre_max((l - num_grids[1] - num_grids[0] + 2), 0); lzmax = hypre_min((l), (num_grids[2] - 1)); for (lz = lzmax; lz >= lzmin; lz--) { lymin = hypre_max((l - lz - num_grids[0] + 1), 0); lymax = hypre_min((l - lz), (num_grids[1] - 1)); for (ly = lymax; ly >= lymin; ly--) { lx = l - lz - ly; hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi); if (!grid_on[fi]) { break; } if ((l >= 1) && (l <= jump)) { hypre_StructVectorSetConstantValues(x_array[fi], 0.0); } if ((lx+1) < num_grids[0]) { /* interpolate from ((lx+1), ly, lz) */ hypre_SparseMSGMapIndex((lx+1), ly, lz, num_grids, ci); if (grid_on[ci]) { hypre_SparseMSGInterp(interpx_array[fi], Px_array[lx], x_array[ci], e_array[fi]); hypre_SparseMSGFilter(visitx_array[fi], e_array[fi], lx, ly, lz, jump); hypre_StructAxpy(1.0, e_array[fi], x_array[fi]); } } if ((ly+1) < num_grids[1]) { /* interpolate from (lx, (ly+1), lz) */ hypre_SparseMSGMapIndex(lx, (ly+1), lz, num_grids, ci); if (grid_on[ci]) { hypre_SparseMSGInterp(interpy_array[fi], Py_array[ly], x_array[ci], e_array[fi]); hypre_SparseMSGFilter(visity_array[fi], e_array[fi], lx, ly, lz, jump); hypre_StructAxpy(1.0, e_array[fi], x_array[fi]); } } if ((lz+1) < num_grids[2]) { /* interpolate from (lx, ly, (lz+1)) */ hypre_SparseMSGMapIndex(lx, ly, (lz+1), num_grids, ci); if (grid_on[ci]) { hypre_SparseMSGInterp(interpz_array[fi], Pz_array[lz], x_array[ci], e_array[fi]); hypre_SparseMSGFilter(visitz_array[fi], e_array[fi], lx, ly, lz, jump); hypre_StructAxpy(1.0, e_array[fi], x_array[fi]); } } #if DEBUG hypre_sprintf(filename, "zoutSMSG_xup.%d.%d.%d", lx, ly, lz); hypre_StructVectorPrint(filename, x_array[fi], 0); #endif if (l > jump) { /* post-relaxation */ hypre_PFMGRelaxSetPostRelax(relax_array[fi]); hypre_PFMGRelaxSetMaxIter(relax_array[fi], num_post_relax); hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 0); hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi], x_array[fi]); } } } } } /* part of convergence check */ if ((tol > 0.0) && (rel_change)) { if (num_levels > 1) { e_dot_e = hypre_StructInnerProd(e_array[0], e_array[0]); x_dot_x = hypre_StructInnerProd(x_array[0], x_array[0]); } else { e_dot_e = 0.0; x_dot_x = 1.0; } } /* fine grid post-relaxation */ hypre_PFMGRelaxSetPostRelax(relax_array[0]); hypre_PFMGRelaxSetMaxIter(relax_array[0], num_fine_relax); hypre_PFMGRelaxSetZeroGuess(relax_array[0], 0); hypre_PFMGRelax(relax_array[0], A_array[0], b_array[0], x_array[0]); (smsg_data -> num_iterations) = (i + 1); } hypre_EndTiming(smsg_data -> time_index); return ierr; }