38 0, 0, -1, 0, 0, 1], [3, max_stencil_size])
71 subroutine coarse_solver_initialize(tree, mg)
72 type(
af_t),
intent(inout) :: tree
73 type(
mg_t),
intent(inout) :: mg
74 integer :: nx(ndim), ierr
76 nx = tree%coarse_grid_size(1:ndim)
78 if (.not. tree%ready) error stop
"coarse_solver_initialize: tree not ready"
80 error stop
"coarse_solver_initialize: coarse_grid_size not set"
82 call hypre_initialize(ierr)
85 call hypre_create_grid(mg%csolver%grid, nx, tree%periodic)
86 call hypre_create_vector(mg%csolver%grid, nx, mg%csolver%phi)
87 call hypre_create_vector(mg%csolver%grid, nx, mg%csolver%rhs)
88 call hypre_set_matrix(tree, mg)
90 if (mg%csolver%solver_type <= 0)
then
93 mg%csolver%solver_type = coarse_solver_hypre_cycred
95 mg%csolver%solver_type = coarse_solver_hypre_pfmg
99 call hypre_prepare_solve(mg%csolver)
104 subroutine hypre_set_matrix(tree, mg)
105 type(
af_t),
intent(inout) :: tree
106 type(
mg_t),
intent(inout) :: mg
107 integer :: n, n_boxes, nc, id, IJK
108 integer :: cnt, stencil_size, ierr
109 integer :: ilo(NDIM), ihi(NDIM)
110 real(dp),
allocatable :: coeffs(:, :)
111 real(dp) :: full_coeffs(2*NDIM+1, DTIMES(tree%n_cell))
112 integer,
allocatable :: stencil_ix(:)
113 integer,
parameter :: zero_to_n(max_stencil_size) = [(i, i=0, max_stencil_size-1)]
116 n_boxes =
size(tree%lvls(1)%ids)
118 if (tree%coord_t == af_cyl .or. mg%i_lsf /= -1)
then
122 mg%csolver%symmetric = 0
125 if (mg%csolver%symmetric == 1)
then
126 stencil_size = ndim + 1
127 allocate(stencil_ix(stencil_size))
131 stencil_ix = [1, 3, 5]
133 stencil_ix = [1, 3, 5, 7]
136 stencil_size = 2*ndim + 1
137 allocate(stencil_ix(stencil_size))
139 stencil_ix = [1, 2, 3]
141 stencil_ix = [1, 2, 3, 4, 5]
143 stencil_ix = [1, 2, 3, 4, 5, 6, 7]
148 call hypre_create_matrix(mg%csolver%matrix, mg%csolver%grid, &
149 stencil_size, stencil_offsets(:, stencil_ix), mg%csolver%symmetric)
151 if (.not.
allocated(mg%csolver%bc_to_rhs))
then
152 allocate(mg%csolver%bc_to_rhs(nc**(ndim-1), af_num_neighbors, n_boxes))
154 if (.not.
allocated(mg%csolver%lsf_fac))
then
155 allocate(mg%csolver%lsf_fac(dtimes(nc), n_boxes))
157 allocate(coeffs(stencil_size, tree%n_cell**ndim))
159 mg%csolver%bc_to_rhs = 0.0_dp
160 mg%csolver%lsf_fac = 0.0_dp
163 do n = 1,
size(tree%lvls(1)%ids)
164 id = tree%lvls(1)%ids(n)
166 associate(box => tree%boxes(id))
167 call af_stencil_get_box(box, mg%operator_key, full_coeffs)
168 call stencil_handle_boundaries(box, mg, full_coeffs, &
169 mg%csolver%bc_to_rhs(:, :, n))
173 i = af_stencil_index(box, mg%operator_key)
174 if (
allocated(box%stencils(i)%f))
then
175 mg%csolver%lsf_fac(dtimes(:), n) = box%stencils(i)%f
182 coeffs(:, cnt) = full_coeffs(stencil_ix, ijk)
185 ilo = (tree%boxes(id)%ix - 1) * nc + 1
188 stencil_size, zero_to_n(1:stencil_size), coeffs, ierr)
189 if (ierr /= 0) error stop
"HYPRE_StructMatrixSetBoxValues failed"
192 call hypre_structmatrixassemble(mg%csolver%matrix, ierr)
222 subroutine hypre_destroy_solver(cs)
223 type(coarse_solve_t),
intent(inout) :: cs
226 select case (cs%solver_type)
227 case (coarse_solver_hypre_cycred)
228 call hypre_structcycreddestroy(cs%solver, ierr)
229 case (coarse_solver_hypre_smg)
230 call hypre_structsmgdestroy(cs%solver, ierr)
231 case (coarse_solver_hypre_pfmg)
232 call hypre_structpfmgdestroy(cs%solver, ierr)
234 error stop
"hypre_solver_destroy: unknown solver type"
238 subroutine hypre_create_grid(grid, nx, periodic)
239 type(c_ptr),
intent(out) :: grid
240 integer,
intent(in) :: nx(NDIM)
241 logical,
intent(in) :: periodic(NDIM)
242 integer :: ierr, ilo(NDIM)
243 integer :: period(NDIM)
248 call hypre_structgridcreate(mpi_comm_world, ndim, grid, ierr)
251 call hypre_structgridsetextents(grid, ilo, nx, ierr)
260 call hypre_structgridsetperiodic(grid, period, ierr)
264 call hypre_structgridassemble(grid, ierr)
268 subroutine hypre_create_vector(grid, nx, vec)
269 type(c_ptr),
intent(in) :: grid
270 integer,
intent(in) :: nx(:)
271 type(c_ptr),
intent(out) :: vec
275 call hypre_structvectorcreate(mpi_comm_world, grid, vec, ierr)
278 call hypre_structvectorinitialize(vec, ierr)
281 call hypre_structvectorassemble(vec, ierr)
286 subroutine coarse_solver_set_rhs_phi(tree, mg)
287 type(af_t),
intent(inout) :: tree
288 type(mg_t),
intent(in) :: mg
289 integer :: n, nb, nc, id, bc_type, ierr
290 integer :: ilo(ndim), ihi(ndim), ix
291 real(dp) :: tmp(dtimes(tree%n_cell))
292 real(dp) :: bc_val(tree%n_cell**(ndim-1))
296 do n = 1,
size(tree%lvls(1)%ids)
297 id = tree%lvls(1)%ids(n)
299 tmp = tree%boxes(id)%cc(dtimes(1:nc), mg%i_rhs)
302 do nb = 1, af_num_neighbors
303 if (tree%boxes(id)%neighbors(nb) < af_no_box)
then
304 ix = tree%boxes(id)%nb_to_bc_index(nb)
305 call mg%sides_bc(tree%boxes(id), nb, mg%i_phi, &
306 tree%boxes(id)%bc_coords(:, :, ix), &
308 tree%boxes(id)%bc_val(:, mg%i_phi, ix) = bc_val
309 tree%boxes(id)%bc_type(mg%i_phi, ix) = bc_type
312 call af_get_index_bc_inside(nb, nc, 1, ilo, ihi)
316 tmp(dslice(ilo, ihi)) = &
317 tmp(dslice(ilo, ihi)) + &
318 reshape(mg%csolver%bc_to_rhs(:, nb, n) * pack(bc_val, .true.), &
324 if (mg%i_lsf /= -1)
then
325 tmp = tmp + mg%csolver%lsf_fac(dtimes(:), n) * &
326 mg_lsf_boundary_value(tree%boxes(id), mg)
329 ilo = (tree%boxes(id)%ix - 1) * nc + 1
331 call hypre_structvectorsetboxvalues(mg%csolver%rhs, ilo, ihi, &
332 pack(tmp, .true.), ierr)
334 tmp = tree%boxes(id)%cc(dtimes(1:nc), mg%i_phi)
335 call hypre_structvectorsetboxvalues(mg%csolver%phi, ilo, ihi, &
336 pack(tmp, .true.), ierr)
341 subroutine coarse_solver_get_phi(tree, mg)
342 type(af_t),
intent(inout) :: tree
343 type(mg_t),
intent(in) :: mg
344 integer :: n, nc, id, ierr
345 integer :: ilo(ndim), ihi(ndim)
346 real(dp) :: tmp(tree%n_cell**ndim)
350 do n = 1,
size(tree%lvls(1)%ids)
351 id = tree%lvls(1)%ids(n)
352 ilo = (tree%boxes(id)%ix - 1) * nc + 1
355 call hypre_structvectorgetboxvalues(mg%csolver%phi, ilo, ihi, tmp, ierr)
356 tree%boxes(id)%cc(dtimes(1:nc), mg%i_phi) = reshape(tmp, [dtimes(nc)])
361 subroutine hypre_create_matrix(A, grid, stencil_size, offsets, symmetric)
362 type(c_ptr),
intent(out) :: A
363 type(c_ptr),
intent(in) :: grid
364 integer,
intent(in) :: stencil_size
365 integer,
intent(in) :: offsets(NDIM, stencil_size)
366 integer,
intent(in) :: symmetric
367 type(c_ptr) :: stencil
371 call hypre_structstencilcreate(ndim, stencil_size, stencil, ierr)
374 do i = 1, stencil_size
375 call hypre_structstencilsetelement(stencil, i-1, offsets(:, i), ierr)
379 call hypre_structmatrixcreate(mpi_comm_world, grid, stencil, a, ierr)
382 call hypre_structmatrixsetsymmetric(a, symmetric, ierr)
385 call hypre_structmatrixinitialize(a, ierr)
387 call hypre_structstencildestroy(stencil, ierr)
393 subroutine hypre_prepare_solve(cs)
394 type(coarse_solve_t),
intent(inout) :: cs
397 select case (cs%solver_type)
398 case (coarse_solver_hypre_cycred)
399 call hypre_structcycredcreate(mpi_comm_world, cs%solver, ierr)
400 call hypre_structcycredsetup(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
401 case (coarse_solver_hypre_smg)
402 call hypre_structsmgcreate(mpi_comm_world, cs%solver, ierr)
403 call hypre_structsmgsetmaxiter(cs%solver, cs%max_iterations, ierr)
404 call hypre_structsmgsettol(cs%solver, cs%tolerance, ierr)
405 call hypre_structsmgsetnumprerelax(cs%solver, cs%n_cycle_down, ierr)
406 call hypre_structsmgsetnumpostrelax(cs%solver, cs%n_cycle_up, ierr)
407 call hypre_structsmgsetup(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
408 case (coarse_solver_hypre_pfmg)
409 call hypre_structpfmgcreate(mpi_comm_world, cs%solver, ierr)
410 call hypre_structpfmgsetmaxiter(cs%solver, cs%max_iterations, ierr)
411 call hypre_structpfmgsettol(cs%solver, cs%tolerance, ierr)
412 call hypre_structpfmgsetnumprerelax(cs%solver, cs%n_cycle_down, ierr)
413 call hypre_structpfmgsetnumpostrelax(cs%solver, cs%n_cycle_up, ierr)
414 call hypre_structpfmgsetup(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
416 error stop
"hypre_prepare_solve: unknown solver type"
421 subroutine coarse_solver(cs, num_iterations)
422 type(coarse_solve_t),
intent(in) :: cs
423 integer,
intent(out) :: num_iterations
426 select case (cs%solver_type)
427 case (coarse_solver_hypre_cycred)
428 call hypre_structcycredsolve(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
430 case (coarse_solver_hypre_smg)
431 call hypre_structsmgsolve(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
432 call hypre_structsmggetnumiterations(cs%solver, num_iterations, ierr)
433 case (coarse_solver_hypre_pfmg)
434 call hypre_structpfmgsolve(cs%solver, cs%matrix, cs%rhs, cs%phi, ierr)
435 call hypre_structpfmggetnumiteration(cs%solver, num_iterations, ierr)
437 error stop
"coarse_solver: unknown solver type"
442 subroutine stencil_handle_boundaries(box, mg, stencil, bc_to_rhs)
443 type(box_t),
intent(in) :: box
444 type(mg_t),
intent(in) :: mg
445 real(dp),
intent(inout) :: stencil(2*NDIM+1, DTIMES(box%n_cell))
446 real(dp),
intent(inout) :: bc_to_rhs(box%n_cell**(NDIM-1), af_num_neighbors)
447 integer :: nb, nc, lo(NDIM), hi(NDIM)
448 integer :: nb_id, nb_dim, bc_type
449 real(dp) :: coords(NDIM, box%n_cell**(NDIM-1))
450 real(dp) :: bc_val(box%n_cell**(NDIM-1))
455 do nb = 1, af_num_neighbors
456 nb_id = box%neighbors(nb)
458 if (nb_id < af_no_box)
then
459 nb_dim = af_neighb_dim(nb)
460 call af_get_face_coords(box, nb, coords)
461 call mg%sides_bc(box, nb, mg%i_phi, coords, bc_val, bc_type)
464 call af_get_index_bc_inside(nb, nc, 1, lo, hi)
466 select case (bc_type)
467 case (af_bc_dirichlet)
471 stencil(1, dslice(lo, hi)) = &
472 stencil(1, dslice(lo, hi)) - &
473 stencil(nb+1, dslice(lo, hi))
474 bc_to_rhs(:, nb) = pack(-2 * stencil(nb+1, dslice(lo, hi)), .true.)
475 stencil(nb+1, dslice(lo, hi)) = 0.0_dp
478 stencil(1, dslice(lo, hi)) = &
479 stencil(1, dslice(lo, hi)) + &
480 stencil(nb+1, dslice(lo, hi))
482 -pack(stencil(nb+1, dslice(lo, hi)) * &
483 box%dr(nb_dim), .true.) * af_neighb_high_pm(nb)
484 stencil(nb+1, dslice(lo, hi)) = 0.0_dp
486 error stop
"mg_box_lpl_stencil: unsupported boundary condition"