94 class(mesh_t),
pointer :: mesh_in, mesh_out
95 type(partition_transfer_t) :: partition_transfer
96 integer :: nsend, nrecv, dim
97 integer,
allocatable :: order_in(:), order_out(:)
98 integer(int64),
allocatable :: order_in_global(:), order_out_global(:)
99 logical,
allocatable :: overlap_map(:)
100 logical :: do_restriction, do_prolongation
101 type(stencil_t) :: transfer_stencil
102 real(real64),
allocatable :: weights(:)
103 integer,
allocatable :: eta(:)
104 integer :: interpolation_level
105 integer :: scale_norms
107 procedure :: dregridding_do_transfer_1, zregridding_do_transfer_1
108 procedure :: dregridding_do_transfer_2, zregridding_do_transfer_2
109 generic :: do_transfer => dregridding_do_transfer_1, zregridding_do_transfer_1
110 generic :: do_transfer => dregridding_do_transfer_2, zregridding_do_transfer_2
115 procedure regridding_init
118 integer,
parameter :: &
128 function regridding_init(mesh_out, mesh_in, space_in, namespace)
result(this)
129 class(mesh_t),
target,
intent(in) :: mesh_out
130 class(mesh_t),
target,
intent(in) :: mesh_in
131 class(space_t),
intent(in) :: space_in
132 type(namespace_t),
intent(in) :: namespace
133 class(regridding_t),
pointer :: this
135 integer :: ip_in, ip_out, index(1:space_in%dim), idim, ii, is, size_array
136 integer(int64),
allocatable :: global_indices_in(:), order_in(:), order_out(:)
137 integer(int64),
allocatable :: global_indices_in_tmp(:)
138 integer,
allocatable :: partition_in(:)
139 integer(int64) :: ipg_out, ipg_in
140 real(real64) :: spacing_ratio(1:space_in%dim)
141 integer :: index_stencil(1:space_in%dim)
142 logical :: same_eta, on_coarse_grid, found
143 type(stencil_t) :: cube_stencil
144 type(lihash_t) :: global_indices
162 call parse_variable(namespace,
"RegriddingInterpolationLevel", linear, this%interpolation_level)
180 if (mesh_out%coord_system%local_basis .or. &
181 mesh_in%coord_system%local_basis .or. &
182 .not. mesh_out%coord_system%orthogonal .or. &
183 .not. mesh_in%coord_system%orthogonal .or. &
184 .not. (mesh_out%coord_system%dim == space_in%dim) .or. &
185 space_in%is_periodic())
then
186 message(1) =
"Currently, regridding is only possible for orthogonal, non-periodic systems."
189 this%dim = space_in%dim
190 spacing_ratio(:) = mesh_out%spacing(1:space_in%dim)/mesh_in%spacing(1:space_in%dim)
192 this%do_restriction = all(spacing_ratio >
m_one)
193 this%do_prolongation = all(spacing_ratio <
m_one)
195 if (this%do_prolongation) spacing_ratio =
m_one/spacing_ratio
197 safe_allocate(this%eta(1:space_in%dim))
198 do idim = 1, space_in%dim
199 this%eta(idim) = nint(spacing_ratio(idim))
201 if (any(abs((spacing_ratio - this%eta)/spacing_ratio) >
m_epsilon))
then
202 message(1) =
'Only commensurate grids allowed for regridding.'
206 do idim = 2, space_in%dim
207 same_eta = same_eta .and. this%eta(idim) == this%eta(idim-1)
209 if (.not. same_eta)
then
210 message(1) =
'Commensurate grids need to have same ratio in all dimensions for regridding.'
214 this%mesh_in => mesh_in
215 this%mesh_out => mesh_out
219 if (.not. this%do_prolongation)
then
221 size_array = mesh_in%np
222 safe_allocate(global_indices_in_tmp(size_array))
225 do ip_in = 1, mesh_in%np
227 if (this%do_restriction)
then
228 on_coarse_grid = .
true.
229 do idim = 1, space_in%dim
230 on_coarse_grid = on_coarse_grid .and. mod(index(idim), this%eta(idim)) == 0
232 if (.not. on_coarse_grid) cycle
234 index(:) = index(:) / this%eta(:)
237 if (ipg_out > 0 .and. ipg_out <= mesh_out%np_global)
then
240 global_indices_in_tmp(ii) = ipg_out
244 if (this%do_restriction)
then
245 if (this%interpolation_level == linear)
then
252 do is = 1, cube_stencil%size
253 if (cube_stencil%center == is) cycle
254 index_stencil(:) = index(:) + cube_stencil%points(1:space_in%dim, is)
256 if (ipg_out > 0 .and. ipg_out <= mesh_out%np_global)
then
261 if (ii >= size_array)
then
262 size_array = size_array * 2
265 global_indices_in_tmp(ii) = ipg_out
278 size_array = mesh_out%np
279 safe_allocate(global_indices_in_tmp(size_array))
281 do ip_out = 1, mesh_out%np
284 on_coarse_grid = .
true.
285 do idim = 1, space_in%dim
286 on_coarse_grid = on_coarse_grid .and. mod(index(idim), this%eta(idim)) == 0
288 if (.not. on_coarse_grid) cycle
290 index(:) = index(:) / this%eta(:)
292 if (ipg_in > 0 .and. ipg_in <= mesh_in%np_global)
then
295 global_indices_in_tmp(ii) = ipg_in
305 do is = 1, cube_stencil%size
306 if (cube_stencil%center == is) cycle
307 index_stencil(:) = index(:) + cube_stencil%points(1:space_in%dim, is)
309 if (ipg_in > 0 .and. ipg_in <= mesh_in%np_global)
then
314 if (ii >= size_array)
then
315 size_array = size_array * 2
318 global_indices_in_tmp(ii) = ipg_in
327 safe_allocate(global_indices_in(ii))
328 safe_allocate(partition_in(ii))
329 global_indices_in(1:ii) = global_indices_in_tmp(1:ii)
330 safe_deallocate_a(global_indices_in_tmp)
332 if (.not. this%do_prolongation)
then
333 if (mesh_out%parallel_in_domains)
then
340 if (mesh_in%parallel_in_domains)
then
351 mesh_in%mpi_grp, mesh_out%mpi_grp, partition_in, &
352 this%nsend, this%nrecv, order_in, order_out, inverse=this%do_prolongation)
354 safe_allocate(this%order_in(1:this%nsend))
355 safe_allocate(this%order_in_global(1:this%nsend))
356 safe_allocate(this%order_out(1:this%nrecv))
357 safe_allocate(this%order_out_global(1:this%nrecv))
360 do ip_in = 1, this%nsend
361 if (this%do_restriction)
then
363 this%order_in_global(ip_in) = order_in(ip_in)
364 this%order_in(ip_in) = 0
365 else if (this%do_prolongation)
then
367 this%order_in_global(ip_in) = order_in(ip_in)
375 if (.not. this%do_restriction)
then
376 if (this%order_in(ip_in) == 0 .or. this%order_in(ip_in) > mesh_in%np)
then
377 write(
message(1),
'(a,i10,a,i10)')
"Error in regridding part 1: mesh point ", &
378 this%order_in(ip_in),
" is not stored in partition ", mesh_in%pv%partno
385 do ip_out = 1, this%nrecv
386 if (.not. this%do_prolongation)
then
387 this%order_out_global(ip_out) = order_out(ip_out)
391 this%order_out_global(ip_out) = order_out(ip_out)
392 this%order_out(ip_out) = 0
394 if (.not. this%do_prolongation)
then
395 if (this%order_out(ip_out) == 0 .or. this%order_out(ip_out) > mesh_out%np)
then
396 write(
message(1),
'(a,i10,a,i10)')
"Error in regridding part 2: mesh point ", &
397 this%order_out(ip_out),
" is not stored in partition ", mesh_out%pv%partno
403 if (this%interpolation_level == linear)
then
405 if (this%do_restriction .or. this%do_prolongation)
then
407 safe_allocate(this%weights(1:this%transfer_stencil%size))
408 this%weights(:) =
m_one
409 do ii = 1, this%transfer_stencil%size
410 do idim = 1, space_in%dim
412 this%weights(ii) = this%weights(ii) * &
413 (
m_one - abs(this%transfer_stencil%points(idim, ii))/real(this%eta(idim), real64))
416 if (this%do_restriction)
then
417 this%weights(ii) = this%weights(ii) / real(this%eta(idim), real64)
424 select case (this%scale_norms)
429 safe_allocate(this%overlap_map(1:this%mesh_in%np))
430 this%overlap_map = this%mesh_out%box%contains_points(this%mesh_in%np, this%mesh_in%x)
433 safe_deallocate_a(partition_in)
434 safe_deallocate_a(global_indices_in)
435 safe_deallocate_a(order_in)
436 safe_deallocate_a(order_out)
447 safe_deallocate_a(this%eta)
448 safe_deallocate_a(this%order_in)
449 safe_deallocate_a(this%order_in_global)
450 safe_deallocate_a(this%order_out)
451 safe_deallocate_a(this%order_out_global)
452 safe_deallocate_a(this%weights)
453 select case (this%scale_norms)
457 safe_deallocate_a(this%overlap_map)
464#include "regridding_inc.F90"
467#include "complex.F90"
468#include "regridding_inc.F90"
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
This module implements a simple hash table for non-negative integer keys and integer values.
integer function, public lihash_lookup(h, key, found)
Look up a value in the hash table h. If found is present, it indicates if key could be found in the t...
subroutine, public lihash_insert(h, key, val)
Insert a (key, val) pair into the hash table h.
subroutine, public lihash_end(h)
Free a hash table.
subroutine, public lihash_init(h)
Initialize a hash table h.
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public mesh_global_index_to_coords(mesh, ipg, ix)
Given a global point index, this function returns the set of integer coordinates of the point.
integer(int64) function, public mesh_global_index_from_coords(mesh, ix)
This function returns the true global index of the point for a given vector of integer coordinates.
subroutine, public mesh_local_index_to_coords(mesh, ip, ix)
Given a local point index, this function returns the set of integer coordinates of the point.
integer function, public mesh_global2local(mesh, ipg)
This function returns the local mesh index for a given global index.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public partition_transfer_init(this, np, global_index, mpi_grp_in, mpi_grp_out, part_out, nsend, nrec, order_in, order_out, inverse)
initialize the partition transfer object
subroutine, public partition_transfer_end(this)
Implementation details for regridding.
integer, parameter nearest_neighbor
class(regridding_t) function, pointer regridding_init(mesh_out, mesh_in, space_in, namespace)
Generate a re-mapping of points from mesh_in to mesh_out.
subroutine regridding_finalize(this)
integer, parameter scale_norm2
integer, parameter scale_none
This module defines routines, generating operators for a cubic stencil.
subroutine, public stencil_cube_get_lapl(this, dim, order)
This module defines stencils used in Octopus.
subroutine, public stencil_end(this)
This module is intended to contain simple general-purpose utility functions and procedures.
subroutine, public make_array_larger(array, new_size)
contains the information of the meshes and provides the transfer functions