4 #include "../src/cpp_macros.h"
12 integer,
parameter :: hypre_parcsr = 5555
15 integer,
parameter,
public :: coarse_solver_hypre_smg = 1
18 integer,
parameter,
public :: coarse_solver_hypre_pfmg = 2
21 integer,
parameter,
public :: coarse_solver_hypre_cycred = 3
24 integer,
parameter :: max_stencil_size = 2*ndim + 1
28 integer,
parameter :: stencil_offsets(1, max_stencil_size) = reshape([0, &
29 -1, 1], [1, max_stencil_size])
31 integer,
parameter :: stencil_offsets(2, max_stencil_size) = reshape([0, 0, &
33 0, -1, 0, 1], [2, max_stencil_size])
35 integer,
parameter :: stencil_offsets(3, max_stencil_size) = reshape([0, 0, 0, &
38 0, 0, -1, 0, 0, 1], [3, max_stencil_size])
42 integer,
parameter :: mpi_comm_world = 0
43 integer,
parameter :: num_procs = 1
44 integer,
parameter :: myid = 0
47 subroutine hypre_structmatrixsetboxvalues(matrix, ilower, iupper, nentries, &
48 entries, values, ierr)
50 type(c_ptr),
intent(in) :: matrix
51 integer,
intent(in) :: ilower(*), iupper(*)
52 integer,
intent(in) :: nentries, entries(*)
53 real(dp),
intent(in) :: values(*)
54 integer,
intent(out) :: ierr
55 end subroutine hypre_structmatrixsetboxvalues
58 public :: coarse_solver_initialize
59 public :: coarse_solver_destroy
60 public :: coarse_solver_set_rhs_phi
61 public :: coarse_solver_get_phi
62 public :: coarse_solver
63 public :: coarse_solver_update_matrix
66 public :: mg_lsf_boundary_value
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)
101 end subroutine coarse_solver_initialize
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
187 call hypre_structmatrixsetboxvalues(mg%csolver%matrix, ilo, ihi, &
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)
194 end subroutine hypre_set_matrix
197 subroutine coarse_solver_update_matrix(tree, mg)
198 type(af_t),
intent(inout) :: tree
199 type(mg_t),
intent(inout) :: mg
202 call hypre_structmatrixdestroy(mg%csolver%matrix, ierr)
203 call hypre_set_matrix(tree, mg)
204 call hypre_prepare_solve(mg%csolver)
205 end subroutine coarse_solver_update_matrix
208 subroutine coarse_solver_destroy(cs)
209 type(coarse_solve_t),
intent(inout) :: cs
212 call hypre_structgriddestroy(cs%grid, ierr)
213 call hypre_structmatrixdestroy(cs%matrix, ierr)
214 call hypre_structvectordestroy(cs%rhs, ierr)
215 call hypre_structvectordestroy(cs%phi, ierr)
217 call hypre_destroy_solver(cs)
218 call hypre_finalize(ierr)
219 end subroutine coarse_solver_destroy
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"
236 end subroutine hypre_destroy_solver
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)
265 end subroutine hypre_create_grid
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)
282 end subroutine hypre_create_vector
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)
338 end subroutine coarse_solver_set_rhs_phi
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)])
358 end subroutine coarse_solver_get_phi
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)
389 end subroutine hypre_create_matrix
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"
418 end subroutine hypre_prepare_solve
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"
439 end subroutine coarse_solver
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"
491 end subroutine stencil_handle_boundaries
494 function mg_lsf_boundary_value(box, mg)
result(bc)
495 type(box_t),
intent(in) :: box
496 type(mg_t),
intent(in) :: mg
497 real(dp) :: bc(dtimes(box%n_cell))
503 if (
associated(mg%lsf_boundary_function))
then
505 r = af_r_cc(box, [ijk])
506 bc(ijk) = mg%lsf_boundary_function(r)
509 bc = mg%lsf_boundary_value
511 end function mg_lsf_boundary_value
This module contains functionality for dealing with numerical stencils.
This module contains the basic types and constants that are used in the NDIM-dimensional version of A...
Module to solve elliptic PDEs on the coarse grid. This module contains an interface to Hypre,...
Type which stores all the boxes and levels, as well as some information about the number of boxes,...
Type to store multigrid options in.