105 class(mesh_t),
pointer :: mesh_in, mesh_out
106 type(partition_transfer_t) :: partition_transfer
107 integer :: nsend, nrecv, dim
108 integer,
allocatable :: order_in(:), order_out(:)
109 integer(int64),
allocatable :: order_in_global(:), order_out_global(:)
110 logical,
allocatable :: overlap_map(:)
111 logical :: do_restriction, do_prolongation
112 type(stencil_t) :: transfer_stencil
113 real(real64),
allocatable :: weights(:)
114 real(real64),
allocatable :: weights_generic(:, :)
115 integer,
allocatable :: stencil_points(:, :)
116 integer,
allocatable :: eta(:)
117 integer :: interpolation_level
118 integer :: scale_norms
119 logical :: generic_interpolation
121 procedure :: dregridding_do_transfer_1, zregridding_do_transfer_1
122 procedure :: dregridding_do_transfer_2, zregridding_do_transfer_2
123 generic :: do_transfer => dregridding_do_transfer_1, zregridding_do_transfer_1
124 generic :: do_transfer => dregridding_do_transfer_2, zregridding_do_transfer_2
129 procedure regridding_init
132 integer,
parameter :: &
133 NEAREST_NEIGHBOR = 0, &
142 function regridding_init(mesh_out, mesh_in, space_in, namespace)
result(this)
143 class(mesh_t),
target,
intent(in) :: mesh_out
144 class(mesh_t),
target,
intent(in) :: mesh_in
145 class(space_t),
intent(in) :: space_in
146 type(namespace_t),
intent(in) :: namespace
147 class(regridding_t),
pointer :: this
149 integer :: ip_in, ip_out, index(1:space_in%dim), idim, ii, is, size_array
150 integer(int64),
allocatable :: global_indices_in(:), order_in(:), order_out(:)
151 integer(int64),
allocatable :: order_in_original(:), order_out_original(:)
152 integer(int64),
allocatable :: global_indices_in_tmp(:)
153 integer(int64),
allocatable :: global_indices_in_original(:)
154 integer,
allocatable :: partition_in(:)
155 integer(int64) :: ipg_coarse, ipg_in
156 real(real64) :: spacing_ratio(1:space_in%dim)
157 real(real64) :: x_fine(1:space_in%dim), x_coarse(1:space_in%dim), x_primitive(1:space_in%dim)
158 real(real64) :: x_out(1:space_in%dim), x_in(1:space_in%dim), rmin, r_current
159 real(real64),
allocatable :: M(:, :), p(:)
160 real(real64) :: scaling(1:space_in%dim, 1:space_in%dim), rotation(1:space_in%dim, 1:space_in%dim)
161 integer :: i_coarse, ip_fine, ip_mindist, cube_size
162 integer :: index_stencil(1:space_in%dim), shift(1:space_in%dim)
163 logical :: same_eta, on_coarse_grid, found, on_in_grid
164 type(lihash_t) :: global_indices
165 class(mesh_t),
pointer :: mesh_coarse, mesh_fine
166 class(coordinate_system_t),
pointer :: coarse_coord, fine_coord
172 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%interpolation_level == nearest_neighbor)
then
240 this%generic_interpolation = .
true.
243 if (this%generic_interpolation)
then
244 this%do_prolongation = .
true.
245 this%do_restriction = .false.
249 this%mesh_in => mesh_in
250 this%mesh_out => mesh_out
251 if (.not. this%do_prolongation)
then
252 mesh_fine => this%mesh_in
253 mesh_coarse => this%mesh_out
255 mesh_coarse => this%mesh_in
256 mesh_fine => this%mesh_out
261 size_array = mesh_fine%np
262 safe_allocate(global_indices_in_tmp(size_array))
263 safe_allocate(global_indices_in_original(size_array))
265 if (.not. this%generic_interpolation)
then
267 do ip_fine = 1, mesh_fine%np
269 on_coarse_grid = .
true.
270 if (this%do_restriction .or. this%do_prolongation)
then
271 do idim = 1, this%dim
272 on_coarse_grid = on_coarse_grid .and. mod(index(idim), this%eta(idim)) == 0
275 if (on_coarse_grid)
then
277 index(:) = index(:) / this%eta(:)
280 else if (this%do_restriction .or. this%do_prolongation)
then
284 index(:) =
floor(real(index(:)) / this%eta(:)) - (this%interpolation_level-1)/2
285 cube_size = 1+this%interpolation_level
286 do is = 1, cube_size**this%dim
290 index_stencil(:) = index(:) + shift(:)
299 do ip_out = 1, mesh_out%np
301 x_out = mesh_out%coord_system%to_cartesian(real(index, real64)*mesh_out%spacing)
302 x_in = mesh_in%coord_system%from_cartesian(x_out)/mesh_in%spacing
303 on_in_grid = all(abs((x_in - nint(x_in))) < 10.0_real64*
m_epsilon)
312 index(:) =
floor(x_in) - (max(this%interpolation_level, 1)-1)/2
313 cube_size = 1+max(this%interpolation_level, 1)
314 do is = 1, cube_size**this%dim
318 index_stencil(:) = index(:) + shift(:)
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 (mesh_coarse%parallel_in_domains)
then
342 mesh_in%mpi_grp, mesh_out%mpi_grp, partition_in, &
343 this%nsend, this%nrecv, order_in, order_out, inverse=this%do_prolongation)
347 if (space_in%is_periodic())
then
348 global_indices_in(1:ii) = global_indices_in_original(1:ii)
350 mesh_in%mpi_grp, mesh_out%mpi_grp, partition_in, &
351 this%nsend, this%nrecv, order_in_original, order_out_original, inverse=this%do_prolongation)
353 order_in_original = order_in
354 order_out_original = order_out
358 safe_allocate(this%order_in(1:this%nsend))
359 safe_allocate(this%order_in_global(1:this%nsend))
360 safe_allocate(this%order_out(1:this%nrecv))
361 safe_allocate(this%order_out_global(1:this%nrecv))
364 do ip_in = 1, this%nsend
365 if (this%do_restriction)
then
367 this%order_in_global(ip_in) = order_in_original(ip_in)
368 this%order_in(ip_in) = 0
369 else if (this%do_prolongation)
then
371 this%order_in_global(ip_in) = order_in(ip_in)
379 if (.not. this%do_restriction)
then
380 if (this%order_in(ip_in) == 0)
then
381 write(
message(1),
'(a,i10,a,i10)')
"Error in regridding part 1: mesh point ", &
382 this%order_in(ip_in),
" is not stored in partition ", mesh_in%pv%partno
389 do ip_out = 1, this%nrecv
390 if (.not. this%do_prolongation)
then
391 this%order_out_global(ip_out) = order_out(ip_out)
395 this%order_out_global(ip_out) = order_out_original(ip_out)
396 this%order_out(ip_out) = 0
398 if (.not. this%do_prolongation)
then
399 if (this%order_out(ip_out) == 0)
then
400 write(
message(1),
'(a,i10,a,i10)')
"Error in regridding part 2: mesh point ", &
401 this%order_out(ip_out),
" is not stored in partition ", mesh_out%pv%partno
410 select type(coord_system => mesh_coarse%coord_system)
416 rotation = matmul(coord_system%basis%vectors, scaling)
418 coarse_coord => mesh_coarse%coord_system
421 select type(coord_system => mesh_fine%coord_system)
425 matmul(transpose(rotation), coord_system%basis%vectors))
427 fine_coord => mesh_fine%coord_system
430 if (.not. this%generic_interpolation)
then
431 if (this%do_restriction .or. this%do_prolongation)
then
434 call get_transfer_stencil(this%transfer_stencil, this%dim, this%eta(1), this%interpolation_level)
435 safe_allocate(this%weights(1:this%transfer_stencil%size))
437 cube_size = 1+this%interpolation_level
438 safe_allocate(m(1:cube_size**this%dim, 1:cube_size**this%dim))
439 safe_allocate(p(1:cube_size**this%dim))
440 do ii = 1, cube_size**this%dim
444 x_primitive = (shift - (this%interpolation_level-1)/2)*mesh_coarse%spacing
445 x_coarse = coarse_coord%to_cartesian(x_primitive)
450 do ii = 1, this%transfer_stencil%size
452 shift = -
floor(real(this%transfer_stencil%points(:, ii), real64)/real(this%eta, real64))
453 x_fine = real(this%transfer_stencil%points(:, ii), real64) + shift*this%eta
454 x_fine = fine_coord%to_cartesian(x_fine * mesh_fine%spacing)
460 call convert_from_base(shift+(this%interpolation_level-1)/2, cube_size, i_coarse)
461 i_coarse = i_coarse + 1
462 this%weights(ii) = p(i_coarse)
466 if (this%do_restriction)
then
467 this%weights(:) = this%weights(:) * mesh_fine%volume_element/mesh_coarse%volume_element
475 cube_size = 1+max(this%interpolation_level, 1)
476 safe_allocate(this%weights_generic(1:cube_size**this%dim, 1:mesh_out%np))
477 this%weights_generic =
m_zero
478 safe_allocate(this%stencil_points(1:cube_size**this%dim, 1:mesh_out%np))
479 this%stencil_points = -1
483 do ip_out = 1, this%nrecv
485 call lihash_insert(global_indices, this%order_out_global(ip_out), ip_out)
488 safe_allocate(m(1:cube_size**this%dim, 1:cube_size**this%dim))
489 safe_allocate(p(1:cube_size**this%dim))
490 do ip_out = 1, mesh_out%np
492 x_out = fine_coord%to_cartesian(real(index, real64)*mesh_out%spacing)
493 x_in = coarse_coord%from_cartesian(x_out)/mesh_in%spacing
494 on_in_grid = all(abs((x_in - nint(x_in))) < 10.0_real64*
m_epsilon)
498 this%stencil_points(1, ip_out) =
lihash_lookup(global_indices, ipg_in, found)
499 this%weights_generic(1, ip_out) =
m_one
504 index(:) =
floor(x_in) - (max(this%interpolation_level, 1)-1)/2
507 do is = 1, cube_size**this%dim
511 index_stencil(:) = index(:) + shift(:)
516 this%stencil_points(is, ip_out) =
lihash_lookup(global_indices, ipg_in, found)
517 x_in = coarse_coord%to_cartesian(index_stencil*mesh_in%spacing)
522 r_current = norm2(x_in - x_out)
525 if (r_current < rmin - 10.*
m_epsilon .and. found)
then
527 ip_mindist = this%stencil_points(is, ip_out)
530 if (this%interpolation_level == nearest_neighbor)
then
532 this%weights_generic(1, ip_out) =
m_one
533 this%stencil_points(:, ip_out) = -1
534 this%stencil_points(1, ip_out) = ip_mindist
540 this%weights_generic(:, ip_out) = matmul(p, m)
549 select case (this%scale_norms)
554 safe_allocate(this%overlap_map(1:this%mesh_in%np))
555 this%overlap_map = this%mesh_out%box%contains_points(this%mesh_in%np, this%mesh_in%x)
558 safe_deallocate_a(partition_in)
559 safe_deallocate_a(global_indices_in)
560 safe_deallocate_a(order_in)
561 safe_deallocate_a(order_out)
564 select type(coord_system => mesh_coarse%coord_system)
566 safe_deallocate_p(coarse_coord)
568 nullify(coarse_coord)
570 select type(coord_system => mesh_fine%coord_system)
572 safe_deallocate_p(fine_coord)
580 class(
mesh_t),
intent(in) :: mesh
581 integer(int64),
intent(in) :: ipg
582 integer,
intent(inout) :: ii
587 if (ipg > 0 .and. ipg <= mesh%np_global .or. &
588 ipg > 0 .and. space_in%is_periodic())
then
590 if (.not. found)
then
593 if (ii >= size_array)
then
594 size_array = size_array * 2
598 if (ipg <= mesh%np_global)
then
599 global_indices_in_tmp(ii) = ipg
600 global_indices_in_original(ii) = ipg
601 else if (ipg > mesh%np_global)
then
603 global_indices_in_original(ii) = ipg
611 real(real64),
intent(in) :: x(1:this%dim)
613 integer :: cube_size, i, j, shift(1:this%dim)
616 cube_size = 1+this%interpolation_level
617 do i = 1, cube_size**this%dim
630 integer,
intent(in) :: dim
631 integer,
intent(in) :: eta
632 integer,
intent(in) :: order
634 integer :: i, offset, cube_size, shift(1:dim)
638 cube_size = eta*(order + 1) - 1
641 offset = eta * (order/2 + 1) - 1
642 do i = 1, cube_size**dim
644 this%points(:, i) = shift(:) - offset
659 safe_deallocate_a(this%eta)
660 safe_deallocate_a(this%order_in)
661 safe_deallocate_a(this%order_in_global)
662 safe_deallocate_a(this%order_out)
663 safe_deallocate_a(this%order_out_global)
664 safe_deallocate_a(this%weights)
665 select case (this%scale_norms)
669 safe_deallocate_a(this%overlap_map)
676#include "regridding_inc.F90"
679#include "complex.F90"
680#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.
subroutine, public convert_to_base(num, base, converted)
convert an integer in base 10 to a different base
subroutine, public convert_from_base(converted, base, num)
convert an integer to base 10 from a different base
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.
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
integer, parameter linear
This module defines stencils used in Octopus.
subroutine, public stencil_allocate(this, dim, size)
subroutine, public stencil_init_center(this)
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:(1+this%interpolation_level) **this%dim) evaluate_polynomials(x)
subroutine get_transfer_stencil(this, dim, eta, order)
subroutine insert_global_point(mesh, ipg, ii)
Describes mesh distribution to nodes.
contains the information of the meshes and provides the transfer functions
The class representing the stencil, which is used for non-local mesh operations.