106 class(mesh_t),
pointer :: mesh_in, mesh_out
107 type(partition_transfer_t) :: partition_transfer
108 integer :: nsend, nrecv, dim
109 integer,
allocatable :: order_in(:), order_out(:)
110 integer(int64),
allocatable :: order_in_global(:), order_out_global(:)
111 logical,
allocatable :: overlap_map(:)
112 logical :: do_restriction, do_prolongation
113 type(stencil_t) :: transfer_stencil
114 real(real64),
allocatable :: weights(:)
115 real(real64),
allocatable :: weights_generic(:, :)
116 integer,
allocatable :: stencil_points(:, :)
117 integer,
allocatable :: eta(:)
118 integer :: interpolation_level
119 integer :: scale_norms
120 logical :: generic_interpolation
122 procedure :: dregridding_do_transfer_1, zregridding_do_transfer_1
123 procedure :: dregridding_do_transfer_2, zregridding_do_transfer_2
124 generic :: do_transfer => dregridding_do_transfer_1, zregridding_do_transfer_1
125 generic :: do_transfer => dregridding_do_transfer_2, zregridding_do_transfer_2
130 procedure regridding_init
133 integer,
parameter :: &
143 function regridding_init(mesh_out, mesh_in, space_in, namespace)
result(this)
144 class(mesh_t),
target,
intent(in) :: mesh_out
145 class(mesh_t),
target,
intent(in) :: mesh_in
146 class(space_t),
intent(in) :: space_in
147 type(namespace_t),
intent(in) :: namespace
148 class(regridding_t),
pointer :: this
150 integer :: ip_in, ip_out, index(1:space_in%dim), idim, ii, is, size_array
151 integer(int64),
allocatable :: global_indices_in(:), order_in(:), order_out(:)
152 integer(int64),
allocatable :: order_in_original(:), order_out_original(:)
153 integer(int64),
allocatable :: global_indices_in_tmp(:)
154 integer(int64),
allocatable :: global_indices_in_original(:)
155 integer,
allocatable :: partition_in(:)
156 integer(int64) :: ipg_coarse, ipg_in
157 real(real64) :: spacing_ratio(1:space_in%dim)
158 real(real64) :: x_fine(1:space_in%dim), x_coarse(1:space_in%dim), x_primitive(1:space_in%dim)
159 real(real64) :: x_out(1:space_in%dim), x_in(1:space_in%dim), rmin, r_current
160 real(real64) :: M(1:2**space_in%dim, 1:2**space_in%dim), p(1:2**space_in%dim)
161 real(real64) :: scaling(1:space_in%dim, 1:space_in%dim), rotation(1:space_in%dim, 1:space_in%dim)
162 integer :: i_coarse, ip_fine, ip_mindist
163 integer :: index_stencil(1:space_in%dim), shift(1:space_in%dim)
164 logical :: same_eta, on_coarse_grid, found, on_in_grid
165 type(lihash_t) :: global_indices
166 class(mesh_t),
pointer :: mesh_coarse, mesh_fine
167 class(coordinate_system_t),
pointer :: coarse_coord, fine_coord
173 nullify(coarse_coord)
188 call parse_variable(namespace,
"RegriddingInterpolationLevel", linear, this%interpolation_level)
207 if (.not. (mesh_out%coord_system%dim == space_in%dim))
then
208 message(1) =
"For regridding, both grids need to have the same space dimension."
212 this%generic_interpolation = mesh_out%coord_system%local_basis .or. &
213 mesh_in%coord_system%local_basis .or. &
214 .not. (same_type_as(mesh_out%coord_system, mesh_in%coord_system))
216 this%dim = space_in%dim
217 spacing_ratio(:) = mesh_out%spacing(1:this%dim)/mesh_in%spacing(1:this%dim)
219 this%do_restriction = all(spacing_ratio >
m_one)
220 this%do_prolongation = all(spacing_ratio <
m_one)
222 if (this%do_prolongation) spacing_ratio =
m_one/spacing_ratio
224 safe_allocate(this%eta(1:this%dim))
225 do idim = 1, this%dim
226 this%eta(idim) = nint(spacing_ratio(idim))
228 if (any(abs((spacing_ratio - this%eta)/spacing_ratio) > 10.0_real64*
m_epsilon))
then
229 this%generic_interpolation = .
true.
232 do idim = 2, this%dim
233 same_eta = same_eta .and. this%eta(idim) == this%eta(idim-1)
235 if (.not. same_eta)
then
236 this%generic_interpolation = .
true.
239 if (this%generic_interpolation)
then
240 this%do_prolongation = .
true.
241 this%do_restriction = .false.
245 this%mesh_in => mesh_in
246 this%mesh_out => mesh_out
247 if (.not. this%do_prolongation)
then
248 mesh_fine => this%mesh_in
249 mesh_coarse => this%mesh_out
251 mesh_coarse => this%mesh_in
252 mesh_fine => this%mesh_out
257 size_array = mesh_fine%np
258 safe_allocate(global_indices_in_tmp(size_array))
259 safe_allocate(global_indices_in_original(size_array))
261 if (.not. this%generic_interpolation)
then
263 do ip_fine = 1, mesh_fine%np
265 on_coarse_grid = .
true.
266 if (this%do_restriction .or. this%do_prolongation)
then
267 do idim = 1, this%dim
268 on_coarse_grid = on_coarse_grid .and. mod(index(idim), this%eta(idim)) == 0
271 if (on_coarse_grid)
then
273 index(:) = index(:) / this%eta(:)
276 else if ((this%do_restriction .and. this%interpolation_level == linear) .or. this%do_prolongation)
then
279 index(:) =
floor(real(index(:)) / this%eta(:))
280 do is = 1, 2**this%dim
283 do idim = 1, this%dim
284 shift(idim) = ibits(is-1, idim-1, 1)
286 index_stencil(:) = index(:) + shift(:)
295 do ip_out = 1, mesh_out%np
297 x_out = mesh_out%coord_system%to_cartesian(real(index, real64)*mesh_out%spacing)
298 x_in = mesh_in%coord_system%from_cartesian(x_out)/mesh_in%spacing
299 on_in_grid = all(abs((x_in - nint(x_in))) < 10.0_real64*
m_epsilon)
307 index(:) =
floor(x_in)
308 do is = 1, 2**this%dim
311 do idim = 1, this%dim
312 shift(idim) = ibits(is-1, idim-1, 1)
314 index_stencil(:) = index(:) + shift(:)
323 safe_allocate(global_indices_in(ii))
324 safe_allocate(partition_in(ii))
325 global_indices_in(1:ii) = global_indices_in_tmp(1:ii)
326 safe_deallocate_a(global_indices_in_tmp)
328 if (mesh_coarse%parallel_in_domains)
then
338 mesh_in%mpi_grp, mesh_out%mpi_grp, partition_in, &
339 this%nsend, this%nrecv, order_in, order_out, inverse=this%do_prolongation)
343 if (space_in%is_periodic())
then
344 global_indices_in(1:ii) = global_indices_in_original(1:ii)
346 mesh_in%mpi_grp, mesh_out%mpi_grp, partition_in, &
347 this%nsend, this%nrecv, order_in_original, order_out_original, inverse=this%do_prolongation)
349 order_in_original = order_in
350 order_out_original = order_out
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_original(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)
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_original(ip_out)
392 this%order_out(ip_out) = 0
394 if (.not. this%do_prolongation)
then
395 if (this%order_out(ip_out) == 0)
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
406 select type(coord_system => mesh_coarse%coord_system)
412 rotation = matmul(coord_system%basis%vectors, scaling)
414 coarse_coord => mesh_coarse%coord_system
417 select type(coord_system => mesh_fine%coord_system)
421 matmul(transpose(rotation), coord_system%basis%vectors))
423 fine_coord => mesh_fine%coord_system
426 if (.not. this%generic_interpolation)
then
427 if (this%interpolation_level == linear .and. (this%do_restriction .or. this%do_prolongation))
then
431 safe_allocate(this%weights(1:this%transfer_stencil%size))
433 do ii = 1, 2**this%dim
436 do idim = 1, this%dim
437 x_primitive(idim) = real(ibits(ii-1, idim-1, 1), real64) * mesh_coarse%spacing(idim)
439 x_coarse = coarse_coord%to_cartesian(x_primitive)
444 do ii = 1, this%transfer_stencil%size
447 do idim = 1, this%dim
448 x_fine(idim) = real(this%transfer_stencil%points(idim, ii), real64)
450 if (x_fine(idim) <
m_zero)
then
451 x_fine(idim) = x_fine(idim) + real(this%eta(idim), real64)
453 i_coarse = ibset(i_coarse, idim-1)
456 x_fine = fine_coord%to_cartesian(x_fine * mesh_fine%spacing)
462 i_coarse = i_coarse + 1
463 this%weights(ii) = p(i_coarse)
467 if (this%do_restriction)
then
468 this%weights(:) = this%weights(:) * mesh_fine%volume_element/mesh_coarse%volume_element
473 safe_allocate(this%weights_generic(1:2**this%dim, 1:mesh_out%np))
474 this%weights_generic =
m_zero
475 safe_allocate(this%stencil_points(1:2**this%dim, 1:mesh_out%np))
476 this%stencil_points = -1
480 do ip_out = 1, this%nrecv
482 call lihash_insert(global_indices, this%order_out_global(ip_out), ip_out)
485 do ip_out = 1, mesh_out%np
487 x_out = fine_coord%to_cartesian(real(index, real64)*mesh_out%spacing)
488 x_in = coarse_coord%from_cartesian(x_out)/mesh_in%spacing
489 on_in_grid = all(abs((x_in - nint(x_in))) < 10.0_real64*
m_epsilon)
493 this%stencil_points(1, ip_out) =
lihash_lookup(global_indices, ipg_in, found)
494 this%weights_generic(1, ip_out) =
m_one
498 index(:) =
floor(x_in)
501 do is = 1, 2**this%dim
504 do idim = 1, this%dim
505 shift(idim) = ibits(is-1, idim-1, 1)
507 index_stencil(:) = index(:) + shift(:)
512 this%stencil_points(is, ip_out) =
lihash_lookup(global_indices, ipg_in, found)
513 x_in = coarse_coord%to_cartesian(index_stencil*mesh_in%spacing)
518 r_current = norm2(x_in - x_out)
521 if (r_current < rmin - 10.*
m_epsilon .and. found)
then
523 ip_mindist = this%stencil_points(is, ip_out)
529 select case (this%interpolation_level)
532 this%weights_generic(:, ip_out) = matmul(p, m)
535 this%weights_generic(1, ip_out) =
m_one
536 this%stencil_points(:, ip_out) = -1
537 this%stencil_points(1, ip_out) = ip_mindist
546 select case (this%scale_norms)
551 safe_allocate(this%overlap_map(1:this%mesh_in%np))
552 this%overlap_map = this%mesh_out%box%contains_points(this%mesh_in%np, this%mesh_in%x)
555 safe_deallocate_a(partition_in)
556 safe_deallocate_a(global_indices_in)
557 safe_deallocate_a(order_in)
558 safe_deallocate_a(order_out)
561 select type(coord_system => mesh_coarse%coord_system)
563 safe_deallocate_p(coarse_coord)
565 nullify(coarse_coord)
567 select type(coord_system => mesh_fine%coord_system)
569 safe_deallocate_p(fine_coord)
577 class(
mesh_t),
intent(in) :: mesh
578 integer(int64),
intent(in) :: ipg
579 integer,
intent(inout) :: ii
584 if (ipg > 0 .and. ipg <= mesh%np_global .or. &
585 ipg > 0 .and. space_in%is_periodic())
then
587 if (.not. found)
then
590 if (ii >= size_array)
then
591 size_array = size_array * 2
595 if (ipg <= mesh%np_global)
then
596 global_indices_in_tmp(ii) = ipg
597 global_indices_in_original(ii) = ipg
598 else if (ipg > mesh%np_global)
then
600 global_indices_in_original(ii) = ipg
608 real(real64),
intent(in) :: x(1:2**this%dim)
611 if (this%dim == 1)
then
614 else if (this%dim == 2)
then
619 else if (this%dim == 3)
then
629 message(1) =
"Regridding only implemented up to dimension 3"
641 safe_deallocate_a(this%eta)
642 safe_deallocate_a(this%order_in)
643 safe_deallocate_a(this%order_in_global)
644 safe_deallocate_a(this%order_out)
645 safe_deallocate_a(this%order_out_global)
646 safe_deallocate_a(this%weights)
647 select case (this%scale_norms)
651 safe_deallocate_a(this%overlap_map)
658#include "regridding_inc.F90"
661#include "complex.F90"
662#include "regridding_inc.F90"
double floor(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_huge
real(real64), parameter, public m_zero
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.
real(real64) function, dimension(1:n, 1:n), public lalg_remove_rotation(n, A)
Remove rotation from affine transformation A by computing the polar decomposition and discarding the ...
This module is intended to contain "only mathematical" functions and procedures.
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(int64) function, public mesh_periodic_point_global(mesh, space, ipg_in)
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.
This module is intended to contain simple general-purpose utility functions and procedures.
subroutine, public make_array_larger(array, new_size)
real(real64) function, dimension(1:2 **this%dim) evaluate_polynomials(x)
subroutine insert_global_point(mesh, ipg, ii)
Describes mesh distribution to nodes.
contains the information of the meshes and provides the transfer functions