65 integer,
parameter :: INNER_POINT = 1
66 integer,
parameter :: ENLARGEMENT_POINT = 2
67 integer,
parameter :: BOUNDARY = -1
78 subroutine mesh_init_stage_1(mesh, namespace, space, box, coord_system, spacing, enlarge)
79 class(mesh_t),
intent(inout) :: mesh
80 type(namespace_t),
intent(in) :: namespace
81 class(space_t),
intent(in) :: space
82 class(box_t),
target,
intent(in) :: box
83 class(coordinate_system_t),
target,
intent(in) :: coord_system
84 real(real64),
intent(in) :: spacing(1:space%dim)
85 integer,
intent(in) :: enlarge(1:space%dim)
87 integer :: idir, jj, delta
88 real(real64) :: x(space%dim), chi(space%dim), spacing_new(-1:1), box_bounds(2, space%dim)
95 safe_allocate(mesh%spacing(1:space%dim))
96 mesh%spacing = spacing
98 mesh%use_curvilinear = coord_system%local_basis
100 mesh%use_vol_pp = mesh%use_curvilinear
101 mesh%coord_system => coord_system
104 mesh%idx%enlarge = enlarge
107 select type (coord_system)
115 do idir = 1, space%dim
122 chi(idir) = real(jj, real64) * mesh%spacing(idir)
123 if (mesh%use_curvilinear)
then
124 x = coord_system%to_cartesian(chi)
131 mesh%idx%nr(2, idir) = jj - 1
135 mesh%idx%nr(1,:) = -mesh%idx%nr(2,:)
138 do idir = 1, space%periodic_dim
139 if (mesh%idx%nr(2, idir) == 0)
then
141 mesh%idx%nr(2, idir) = 1
142 mesh%idx%nr(1, idir) = -1
150 spacing_new(delta) =
m_two*maxval(abs(
box_bounds(:, idir))) / real(2 * mesh%idx%nr(2, idir) + 1 - delta, real64)
151 spacing_new(delta) = abs(spacing_new(delta) - spacing(idir))
154 delta = minloc(spacing_new, dim = 1) - 2
159 mesh%spacing(idir) =
m_two*maxval(abs(
box_bounds(:, idir))) / real(2 * mesh%idx%nr(2, idir) + 1 - delta, real64)
162 if (delta == -1)
then
163 mesh%idx%nr(1, idir) = mesh%idx%nr(1, idir) - 1
164 else if (delta == 1)
then
165 mesh%idx%nr(2, idir) = mesh%idx%nr(2, idir) - 1
170 if ( any(abs(mesh%spacing - spacing) > 1.e-6_real64) )
then
171 call messages_write(
'The spacing has been modified to make it commensurate with the periodicity of the system.')
175 do idir = space%periodic_dim + 1, space%dim
176 if (mesh%idx%nr(2, idir) == 0)
then
177 write(
message(1),
'(a,i2)')
'Spacing > box size in direction ', idir
182 mesh%idx%ll = mesh%idx%nr(2, :) - mesh%idx%nr(1, :) + 1
184 mesh%idx%stride(:) = 1
185 do idir = 2, space%dim+1
186 mesh%idx%stride(idir) = mesh%idx%stride(idir-1) * &
187 (mesh%idx%ll(idir-1) + 2*mesh%idx%enlarge(idir-1))
200 subroutine mesh_init_stage_2(mesh, namespace, space, box, stencil, grp, regenerate)
201 class(
mesh_t),
intent(inout) :: mesh
203 class(
space_t),
intent(in) :: space
204 class(
box_t),
intent(in) :: box
207 logical,
optional,
intent(in) :: regenerate
210 real(real64) :: chi(1:space%dim)
211 real(real64) :: pos(space%dim)
212 integer :: point(space%dim), point_stencil(space%dim), grid_sizes(space%dim)
213 integer(int64) :: global_size
214 integer(int32) :: local_size
215 integer(int64) :: ispatial, ispatialb, istart, iend, spatial_size, ipg
216 integer :: ip, ib, ib2, np, np_boundary, ii
218 type(
lihash_t) :: spatial_to_boundary
219 integer(int64),
allocatable :: boundary_to_spatial(:), boundary_to_spatial_reordered(:)
220 integer(int64),
allocatable :: grid_to_spatial(:), grid_to_spatial_initial(:), grid_to_spatial_reordered(:)
221 integer(int64),
allocatable :: spatial_to_grid(:)
222 integer,
allocatable ::
sizes(:)
223 integer(int64),
allocatable :: offsets(:)
224 integer :: size_boundary
226 integer(int64),
pointer :: ptr(:)
227 type(
mpi_grp_t) :: internode_grp, intranode_grp
234 mesh%idx%nr(1, :) = mesh%idx%nr(1, :) - mesh%idx%enlarge(:)
235 mesh%idx%nr(2, :) = mesh%idx%nr(2, :) + mesh%idx%enlarge(:)
252 grid_sizes = mesh%idx%nr(2, :) - mesh%idx%nr(1, :) + 1
253 mesh%idx%offset = grid_sizes/2
254 if (space%dim > 1 .and. any(grid_sizes > 2**(int(63/space%dim, int64))))
then
255 write(
message(1),
'(A, I10, A, I2, A)')
"Error: grid too large, more than ", 2**(int(63/space%dim, int64)), &
256 " points in one direction for ", space%dim,
" dimensions. This is not supported."
259 global_size = product(int(grid_sizes, int64))
261 mesh%idx%bits = maxval(ceiling(
log(real(grid_sizes, real64) )/
log(2.0_real64)))
264 spatial_size = global_size
266 spatial_size = 2**(space%dim*mesh%idx%bits)
270 istart = spatial_size * grp%rank/grp%size
271 iend = spatial_size * (grp%rank+1)/grp%size - 1
272 if (.not. (iend - istart + 1 < huge(0_int32)))
then
273 write(
message(1),
'(A, I10, A, I2, A)')
"Error: local grid too large, more than ", &
274 huge(0_int32),
" points. This is not supported. Maybe use more MPI ranks?"
277 local_size = int(iend - istart + 1, int32)
279 safe_allocate(grid_to_spatial_initial(1:local_size))
283 do ispatial = istart, iend
286 if (any(point < mesh%idx%nr(1, :) + mesh%idx%enlarge)) cycle
287 if (any(point > mesh%idx%nr(2, :) - mesh%idx%enlarge)) cycle
289 chi = real(point, real64) * mesh%spacing
290 pos = mesh%coord_system%to_cartesian(chi)
291 if (.not. box%contains_point(pos)) cycle
292 grid_to_spatial_initial(ip) = ispatial
293 assert(ip + 1 < huge(ip))
301 safe_deallocate_a(grid_to_spatial_initial)
303 safe_allocate(spatial_to_grid(grid_to_spatial(1):grid_to_spatial(np)))
304 safe_deallocate_a(
sizes)
307 do ispatial = grid_to_spatial(1), grid_to_spatial(np)
308 spatial_to_grid(ispatial) = -1
312 spatial_to_grid(grid_to_spatial(ip)) = ip
318 safe_allocate(boundary_to_spatial(1:size_boundary))
322 do is = 1, stencil%size
323 if (stencil%center == is) cycle
324 point_stencil(1:space%dim) = point(1:space%dim) + stencil%points(1:space%dim, is)
327 assert(ispatialb >= 0)
328 if (ispatialb >= lbound(spatial_to_grid, dim=1, kind=int64) .and. &
329 ispatialb <= ubound(spatial_to_grid, dim=1, kind=int64))
then
330 if (spatial_to_grid(ispatialb) > 0) cycle
333 chi = real(point_stencil, real64) * mesh%spacing
334 pos = mesh%coord_system%to_cartesian(chi)
335 if (box%contains_point(pos)) cycle
340 boundary_to_spatial(ib) = ispatialb
344 if (ib >= size_boundary)
then
345 size_boundary = size_boundary * 2
352 safe_deallocate_a(spatial_to_grid)
355 call reorder_points(namespace, space, grp, mesh%idx, grid_to_spatial, grid_to_spatial_reordered)
356 safe_deallocate_a(grid_to_spatial)
360 mesh%np_global =
sizes(0)
361 do ii = 1, grp%size - 1
362 mesh%np_global = mesh%np_global +
sizes(ii)
364 safe_deallocate_a(
sizes)
365 safe_deallocate_a(grid_to_spatial_reordered)
369 call reorder_points(namespace, space, grp, mesh%idx, boundary_to_spatial, boundary_to_spatial_reordered)
370 safe_deallocate_a(boundary_to_spatial)
373 safe_deallocate_a(boundary_to_spatial_reordered)
376 np_boundary =
sizes(grp%rank)
377 mesh%np_part_global = mesh%np_global +
sizes(0)
378 do ii = 1, grp%size - 1
379 mesh%np_part_global = mesh%np_part_global +
sizes(ii)
381 safe_deallocate_a(
sizes)
387 call create_intranode_communicator(grp, intranode_grp, internode_grp)
388 call lmpi_create_shared_memory_window(mesh%np_part_global, intranode_grp, &
389 mesh%idx%window_grid_to_spatial, mesh%idx%grid_to_spatial_global)
391 safe_allocate(mesh%idx%grid_to_spatial_global(1:mesh%np_part_global))
395 call grp%gatherv(grid_to_spatial, np, mpi_integer8, &
396 mesh%idx%grid_to_spatial_global,
sizes, offsets, mpi_integer8, 0)
400 call grp%gatherv(boundary_to_spatial, np_boundary, mpi_integer8, &
401 mesh%idx%grid_to_spatial_global(mesh%np_global+1:),
sizes, offsets, mpi_integer8, 0)
406 call lmpi_create_shared_memory_window(spatial_size, intranode_grp, &
407 mesh%idx%window_spatial_to_grid, ptr)
408 mesh%idx%spatial_to_grid_global(0:spatial_size-1) => ptr(1:spatial_size)
410 safe_allocate(mesh%idx%spatial_to_grid_global(0:spatial_size-1))
412 if (grp%is_root())
then
415 do ispatial = 0, spatial_size-1
416 mesh%idx%spatial_to_grid_global(ispatial) = 0
419 do ipg = 1, mesh%np_part_global
420 mesh%idx%spatial_to_grid_global(mesh%idx%grid_to_spatial_global(ipg)) = ipg
426 if (intranode_grp%is_root())
then
427 call internode_grp%bcast(mesh%idx%grid_to_spatial_global(1), mesh%np_part_global, mpi_integer8, 0)
428 call internode_grp%bcast(mesh%idx%spatial_to_grid_global(0), spatial_size, mpi_integer8, 0)
430 call lmpi_sync_shared_memory_window(mesh%idx%window_grid_to_spatial, intranode_grp)
431 call lmpi_sync_shared_memory_window(mesh%idx%window_spatial_to_grid, intranode_grp)
434 safe_deallocate_a(offsets)
435 safe_deallocate_a(
sizes)
437 safe_deallocate_a(boundary_to_spatial)
438 safe_deallocate_a(grid_to_spatial)
449 subroutine mesh_init_stage_3(mesh, namespace, space, stencil, mc, parent, regenerate)
450 class(
mesh_t),
intent(inout) :: mesh
452 class(
space_t),
intent(in) :: space
455 type(
mesh_t),
optional,
intent(in) :: parent
456 logical,
optional,
intent(in) :: regenerate
458 integer :: ip, jj(space%dim), np
465 mesh%parallel_in_domains = (mesh%mpi_grp%size > 1)
470 if (mesh%parallel_in_domains)
then
474 assert(mesh%np_part_global < huge(mesh%np_part))
476 mesh%np_part =
i8_to_i4(mesh%np_part_global)
480 mesh%pv%np_global = mesh%np_global
482 mesh%pv%np_bndry = mesh%np_part - mesh%np
488 safe_allocate(mesh%x(1:space%dim, 1:mesh%np_part))
489 safe_allocate(mesh%x_t(1:mesh%np_part, 1:space%dim))
490 do ip = 1, mesh%np_part
492 mesh%x_t(ip, 1:space%dim) = mesh%x(1:space%dim, ip)
496 safe_allocate(mesh%chi(1:space%dim, 1:mesh%np_part))
497 do ip = 1, mesh%np_part
499 mesh%chi(:, ip) = jj*mesh%spacing
505 if (mesh%coord_system%local_basis)
then
510 safe_allocate(mesh%jacobian_inverse(1:space%dim, 1:space%dim, np))
512 mesh%jacobian_inverse(:, :, ip) = mesh%coord_system%jacobian_inverse(mesh%chi(:, ip))
521 integer :: jj, ipart, jpart
522 integer(int64) :: ipg, jpg
523 integer,
allocatable :: gindex(:), gedges(:)
524 logical,
allocatable :: nb(:, :)
525 integer :: idx(space%dim), jx(space%dim)
526 type(mpi_comm) :: graph_comm
527 integer :: iedge, nnb
528 logical :: use_topo, reorder, partition_print
531 logical :: has_virtual_partition = .false.
533 type(
restart_t) :: restart_load, restart_dump
534 integer,
allocatable :: part_vec(:)
542 call restart_load%end()
557 call parse_variable(namespace,
'MeshPartitionVirtualSize', mesh%mpi_grp%size, vsize)
559 if (vsize /= mesh%mpi_grp%size)
then
560 write(
message(1),
'(a,I7)')
"Changing the partition size to", vsize
561 write(
message(2),
'(a)')
"The execution will crash."
563 has_virtual_partition = .
true.
565 has_virtual_partition = .false.
568 if (.not.
present(parent))
then
578 call restart_dump%end()
581 if (has_virtual_partition)
then
584 write(
message(1),
'(a)')
"Execution has ended."
585 write(
message(2),
'(a)')
"If you want to run your system, do not use MeshPartitionVirtualSize."
601 call parse_variable(namespace,
'MeshUseTopology', .false., use_topo)
605 safe_allocate(part_vec(1:mesh%np_global))
611 safe_allocate(nb(1:mesh%mpi_grp%size, 1:mesh%mpi_grp%size))
614 do ipg = 1, mesh%np_global
615 ipart = part_vec(ipg)
617 do jj = 1, stencil%size
618 jx = idx + stencil%points(:, jj)
620 if (jpg > 0 .and. jpg <= mesh%np_global)
then
621 jpart = part_vec(jpg)
622 if (ipart /= jpart ) nb(ipart, jpart) = .
true.
626 safe_deallocate_a(part_vec)
630 safe_allocate(gindex(1:mesh%mpi_grp%size))
631 safe_allocate(gedges(1:count(nb)))
635 do ipart = 1, mesh%mpi_grp%size
636 do jpart = 1, mesh%mpi_grp%size
637 if (nb(ipart, jpart))
then
639 gedges(iedge) = jpart - 1
642 gindex(ipart) = iedge
645 assert(iedge == count(nb))
648 call mpi_graph_create(mesh%mpi_grp%comm, mesh%mpi_grp%size, gindex, gedges, reorder, graph_comm)
653 safe_deallocate_a(nb)
654 safe_deallocate_a(gindex)
655 safe_deallocate_a(gedges)
660 call par_vec_init(mesh%mpi_grp, mesh%np_global, mesh%idx, stencil,&
661 space, mesh%partition, mesh%pv, namespace)
665 jpart = mesh%pv%partno
666 do ipart = 1, mesh%pv%npart
667 if (ipart == jpart) cycle
668 if (mesh%pv%ghost_scounts(ipart) /= 0) nnb = nnb + 1
670 assert(nnb >= 0 .and. nnb < mesh%pv%npart)
673 mesh%np = mesh%pv%np_local
674 mesh%np_part = mesh%np + mesh%pv%np_ghost + mesh%pv%np_bndry
687 if (partition_print)
then
706 if (mesh%use_vol_pp) np = mesh%np_part
708 if (mesh%np_part == 0) np = 0
710 safe_allocate(mesh%vol_pp(1:np))
713 mesh%vol_pp(ip) = product(mesh%spacing)
717 mesh%vol_pp(ip) = mesh%vol_pp(ip)*mesh%coord_system%jacobian_determinant(mesh%chi(:, ip))
720 if (mesh%use_vol_pp .or. mesh%np_part == 0)
then
721 mesh%volume_element =
m_one
723 mesh%volume_element = mesh%vol_pp(1)
747 integer(int64),
contiguous,
intent(in) :: data_input(:)
748 integer(int64),
allocatable,
intent(out) :: data_output(:)
749 integer,
allocatable,
optional,
intent(out) :: output_sizes(:)
751 integer,
allocatable :: initial_sizes(:), final_sizes(:)
752 integer(int64),
allocatable :: initial_offsets(:), final_offsets(:)
753 integer,
allocatable :: scounts(:), sdispls(:)
754 integer,
allocatable :: rcounts(:), rdispls(:)
756 integer(int64) :: itmp
761 safe_allocate(initial_sizes(0:grp%size-1))
762 call grp%allgather(
size(data_input), 1, mpi_integer, initial_sizes(0), 1, mpi_integer)
763 safe_allocate(initial_offsets(0:grp%size))
764 initial_offsets(0) = 0
765 do irank = 1, grp%size
766 initial_offsets(irank) = initial_offsets(irank-1) + initial_sizes(irank-1)
771 safe_allocate(final_offsets(0:grp%size))
772 safe_allocate(final_sizes(0:grp%size-1))
774 do irank = 0, grp%size
775 final_offsets(irank) = sum(int(initial_sizes, int64)) * irank/grp%size
777 do irank = 0, grp%size - 1
778 assert(final_offsets(irank + 1) - final_offsets(irank) < huge(0_int32))
779 final_sizes(irank) = int(final_offsets(irank + 1) - final_offsets(irank), int32)
782 safe_allocate(scounts(0:grp%size-1))
783 safe_allocate(sdispls(0:grp%size-1))
784 safe_allocate(rcounts(0:grp%size-1))
785 safe_allocate(rdispls(0:grp%size-1))
788 do irank = 0, grp%size - 1
790 itmp = min(final_offsets(irank+1), initial_offsets(grp%rank+1)) - &
791 max(final_offsets(irank), initial_offsets(grp%rank))
792 assert(itmp < huge(0_int32))
796 scounts(irank) = int(itmp, int32)
800 do irank = 1, grp%size - 1
801 sdispls(irank) = sdispls(irank - 1) + scounts(irank - 1)
803 assert(sum(int(scounts, int64)) < huge(0_int32))
804 assert(sum(scounts) == initial_sizes(grp%rank))
807 do irank = 0, grp%size - 1
809 itmp = min(final_offsets(grp%rank+1), initial_offsets(irank+1)) - &
810 max(final_offsets(grp%rank), initial_offsets(irank))
811 assert(itmp < huge(0_int32))
815 rcounts(irank) = int(itmp, int32)
819 do irank = 1, grp%size - 1
820 rdispls(irank) = rdispls(irank - 1) + rcounts(irank - 1)
823 assert(sum(rcounts) == final_sizes(grp%rank))
825 safe_allocate(data_output(1:final_sizes(grp%rank)))
826 call grp%alltoallv(data_input, scounts, sdispls, mpi_integer8, &
827 data_output, rcounts, rdispls, mpi_integer8)
830 if (
present(output_sizes))
then
831 safe_allocate(output_sizes(0:grp%size-1))
832 output_sizes(:) = final_sizes(:)
835 safe_deallocate_a(final_offsets)
836 safe_deallocate_a(final_sizes)
838 safe_deallocate_a(scounts)
839 safe_deallocate_a(sdispls)
840 safe_deallocate_a(rcounts)
841 safe_deallocate_a(rdispls)
851 subroutine reorder_points(namespace, space, grp, idx, grid_to_spatial, grid_to_spatial_reordered)
853 class(
space_t),
intent(in) :: space
855 type(
index_t),
intent(in) :: idx
856 integer(int64),
contiguous,
intent(in) :: grid_to_spatial(:)
857 integer(int64),
allocatable,
intent(out) :: grid_to_spatial_reordered(:)
859 integer :: bsize(space%dim), order, default
860 integer :: nn, idir, ipg, ip, number_of_blocks(space%dim)
862 integer,
parameter :: &
864 order_original = 2, &
866 integer :: point(1:space%dim)
867 integer(int64),
allocatable :: reorder_indices(:), reorder_recv(:)
868 integer,
allocatable :: index_map(:), indices(:)
869 integer(int64),
allocatable :: grid_to_spatial_recv(:)
870 integer,
allocatable :: initial_sizes(:)
871 integer(int64),
allocatable :: initial_offsets(:)
872 integer(int64) :: istart, iend, indstart, indend, spatial_size
873 integer :: irank, local_size, num_recv
874 integer :: iunique, nunique
876 logical :: increase_with_dimension
878 integer,
allocatable :: scounts(:), sdispls(:), rcounts(:), rdispls(:)
879 integer(int64),
allocatable :: spatial_cutoff(:)
901 default = order_blocks
904 if (space%dim == 1)
then
905 order = order_original
923 call parse_variable(namespace,
'MeshBlockDirection', 1, direction)
924 increase_with_dimension = direction == 1
925 if (direction /= 1 .and. direction /= 2)
then
930 case (order_original)
932 safe_allocate(grid_to_spatial_reordered(1:
size(grid_to_spatial)))
933 grid_to_spatial_reordered(1:
size(grid_to_spatial)) = grid_to_spatial(1:
size(grid_to_spatial))
934 case (order_blocks, order_cube)
935 if (order == order_cube)
then
936 bsize = idx%nr(2, :) - idx%nr(1, :) + 1
949 if (
conf%target_states_block_size < 16)
then
950 bsize(1) = 80 * 4 / abs(
conf%target_states_block_size)
951 if (space%dim > 1) bsize(2) = 4
952 if (space%dim > 2) bsize(3:) = 10
954 bsize(1) = max(4 * 16 / abs(
conf%target_states_block_size), 1)
955 if (space%dim > 1) bsize(2) = 15
956 if (space%dim > 2) bsize(3:) = 15
959 if (
parse_block(namespace,
'MeshBlockSize', blk) == 0)
then
961 if (nn /= space%dim)
then
962 message(1) =
"Error: number of entries in MeshBlockSize must match the number of dimensions."
971 number_of_blocks = (idx%nr(2, :) - idx%nr(1, :) + 1) / bsize + 1
978 safe_allocate(initial_sizes(0:grp%size-1))
979 call grp%allgather(
size(grid_to_spatial), 1, mpi_integer, initial_sizes(0), 1, mpi_integer)
980 safe_allocate(initial_offsets(0:grp%size))
981 initial_offsets(0) = 0
982 do irank = 1, grp%size
983 initial_offsets(irank) = initial_offsets(irank-1) + initial_sizes(irank-1)
987 istart = initial_offsets(grp%rank)
988 iend = initial_offsets(grp%rank + 1) - 1
989 assert(iend - istart + 1 < huge(0_int32))
990 local_size = int(iend - istart + 1, int32)
991 assert(local_size == initial_sizes(grp%rank))
994 safe_allocate(reorder_indices(1:local_size))
995 safe_allocate(indices(1:local_size))
996 safe_allocate(grid_to_spatial_reordered(1:local_size))
998 do ip = 1, local_size
1000 point = point + idx%offset
1001 reorder_indices(ip) =
get_blocked_index(space%dim, point, bsize, number_of_blocks, increase_with_dimension)
1005 call sort(reorder_indices, indices)
1008 do ip = 1, local_size
1009 grid_to_spatial_reordered(ip) = grid_to_spatial(indices(ip))
1013 if(local_size > 0)
then
1014 indstart = reorder_indices(1)
1015 indend = reorder_indices(local_size)
1017 indstart = huge(1_int64)
1020 call grp%allreduce_inplace(indstart, 1, mpi_integer8, mpi_min)
1021 call grp%allreduce_inplace(indend, 1, mpi_integer8, mpi_max)
1022 spatial_size = indend - indstart + 1
1025 safe_allocate(spatial_cutoff(0:grp%size-1))
1026 do irank = 0, grp%size - 1
1027 spatial_cutoff(irank) = spatial_size * (irank+1)/grp%size + indstart
1030 safe_allocate(scounts(0:grp%size-1))
1031 safe_allocate(sdispls(0:grp%size-1))
1032 safe_allocate(rcounts(0:grp%size-1))
1033 safe_allocate(rdispls(0:grp%size-1))
1039 do ip = 1, local_size
1040 if (reorder_indices(ip) >= spatial_cutoff(irank))
then
1042 do while (reorder_indices(ip) >= spatial_cutoff(irank))
1045 assert(irank < grp%size)
1047 scounts(irank) = scounts(irank) + 1
1049 safe_deallocate_a(spatial_cutoff)
1050 assert(sum(scounts) == local_size)
1054 do irank = 1, grp%size - 1
1055 sdispls(irank) = sdispls(irank - 1) + scounts(irank - 1)
1058 call grp%alltoall(scounts, 1, mpi_integer, &
1059 rcounts, 1, mpi_integer)
1062 do irank = 1, grp%size - 1
1063 rdispls(irank) = rdispls(irank - 1) + rcounts(irank - 1)
1067 num_recv = max(sum(rcounts), 1)
1069 safe_allocate(reorder_recv(1:num_recv))
1070 call grp%alltoallv(reorder_indices, scounts, sdispls, mpi_integer8, &
1071 reorder_recv, rcounts, rdispls, mpi_integer8)
1072 safe_deallocate_a(reorder_indices)
1075 safe_allocate(grid_to_spatial_recv(1:num_recv))
1076 call grp%alltoallv(grid_to_spatial_reordered, scounts, sdispls, mpi_integer8, &
1077 grid_to_spatial_recv, rcounts, rdispls, mpi_integer8)
1078 safe_deallocate_a(grid_to_spatial_reordered)
1081 safe_allocate(reorder_indices(1:num_recv))
1082 safe_allocate(index_map(1:num_recv))
1083 if (sum(rcounts) > 0)
then
1088 do ipg = 2, sum(rcounts)
1089 if (reorder_indices(ipg) /= reorder_indices(ipg-1))
then
1090 nunique = nunique + 1
1095 safe_allocate(grid_to_spatial_reordered(1:nunique))
1097 grid_to_spatial_reordered(iunique) = grid_to_spatial_recv(index_map(1))
1098 do ipg = 2, sum(rcounts)
1099 if (reorder_indices(ipg) /= reorder_indices(ipg-1))
then
1100 iunique = iunique + 1
1101 grid_to_spatial_reordered(iunique) = grid_to_spatial_recv(index_map(ipg))
1105 safe_allocate(grid_to_spatial_reordered(1:0))
1108 safe_deallocate_a(initial_offsets)
1109 safe_deallocate_a(initial_sizes)
1111 safe_deallocate_a(reorder_indices)
1112 safe_deallocate_a(reorder_recv)
1114 safe_deallocate_a(grid_to_spatial_recv)
1115 safe_deallocate_a(index_map)
1116 safe_deallocate_a(indices)
1118 safe_deallocate_a(scounts)
1119 safe_deallocate_a(sdispls)
1120 safe_deallocate_a(rcounts)
1121 safe_deallocate_a(rdispls)
1130 integer,
intent(in) :: local_size
1131 integer,
allocatable,
intent(out) :: sizes(:)
1132 integer(int64),
allocatable,
intent(out) :: offsets(:)
1139 safe_allocate(sizes(0:mpi_grp%size-1))
1140 call mpi_grp%allgather(local_size, 1, mpi_integer, sizes(0), 1, mpi_integer)
1141 safe_allocate(offsets(0:mpi_grp%size))
1143 do irank = 1, mpi_grp%size
1144 offsets(irank) = offsets(irank-1) + sizes(irank-1)
Box bounds along some axes.
This is the common interface to a sorting routine. It performs the shell algorithm,...
double log(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
subroutine do_partition()
subroutine mesh_get_vol_pp()
calculate the volume of integration
pure logical function, public accel_is_enabled()
integer, parameter, public accel_mem_read_only
real(real64), parameter, public box_boundary_delta
This module handles the calculation mode.
integer, parameter, public p_strategy_domains
parallelization in domains
real(real64), parameter, public m_two
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
real(real64), parameter, public m_zero
type(conf_t), public conf
Global instance of Octopus configuration.
real(real64), parameter, public m_one
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 implements the index, used for the mesh points.
subroutine, public index_init(idx, dim)
This subroutine allocates memory and initializes some components.
integer(int64) function, public get_blocked_index(dim, point, bsize, number_of_blocks, increase_with_dimensions)
subroutine, public index_spatial_to_point(idx, dim, ispatial, point)
integer, parameter, public idx_hilbert
subroutine, public index_point_to_spatial(idx, dim, ispatial, point)
integer, parameter, public idx_cubic
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public merge_sorted_arrays(array, sizes, merged, index_map)
This module contains subroutines, related to the initialization of the mesh.
subroutine rebalance_array(grp, data_input, data_output, output_sizes)
re-distribute the points to improve load balancing
subroutine, public mesh_init_stage_3(mesh, namespace, space, stencil, mc, parent, regenerate)
When running parallel in domains, stencil and np_stencil are needed to compute the ghost points....
subroutine, public mesh_init_stage_1(mesh, namespace, space, box, coord_system, spacing, enlarge)
First stage mesh initialization.
subroutine get_sizes_offsets(local_size, sizes, offsets, mpi_grp)
return the sizes and offsets of a distributed array for all tasks of a mpi group.
subroutine reorder_points(namespace, space, grp, idx, grid_to_spatial, grid_to_spatial_reordered)
reorder the points in the grid according to the variables MeshOrder and MeshLocalOrder
subroutine, public mesh_init_stage_2(mesh, namespace, space, box, stencil, grp, regenerate)
This subroutine creates the global array of spatial indices and the inverse mapping.
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_local2global(mesh, ip)
This function returns the global mesh index for a given local index.
real(real64) function, dimension(1:mesh%box%dim), public mesh_x_global(mesh, ipg)
Given a global point index, this function returns the coordinates of the point.
subroutine, public mesh_partition_from_parent(mesh, parent)
create a mesh partition from a given parent mesh
subroutine, public mesh_partition_write_info(mesh, iunit, namespace)
subroutine, public mesh_partition_messages_debug(mesh, namespace)
subroutine, public mesh_partition(mesh, namespace, space, lapl_stencil, vsize)
This routine converts the mesh given by grid points into a graph.
subroutine, public mesh_partition_dump(restart, mesh, vsize, ierr)
subroutine, public mesh_partition_load(restart, mesh, ierr)
subroutine, public messages_end()
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public print_date(str)
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 messages_input_error(namespace, var, details, row, column)
This module contains some common usage patterns of MPI routines.
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
This module handles the communicators for the various parallelization strategies.
Some general things and nomenclature:
subroutine, public par_vec_end(pv)
Deallocate memory used by pv.
subroutine, public par_vec_init(mpi_grp, np_global, idx, stencil, space, partition, pv, namespace)
Initializes a par_vec_type object (parallel vector).
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public partition_get_global(partition, part_global, root)
Returns the global partition. If root is present, the partition is gathered only in that node....
subroutine, public profiling_end(namespace)
integer, parameter, public restart_partition
integer, parameter, public restart_type_dump
integer, parameter, public restart_type_load
This module is intended to contain "only mathematical" functions and procedures.
This module defines stencils used in Octopus.
integer, dimension(7), parameter sizes
type(type_t), parameter, public type_float
This module is intended to contain simple general-purpose utility functions and procedures.
subroutine, public make_array_larger(array, new_size)
class to tell whether a point is inside or outside
Describes mesh distribution to nodes.
This is defined even when running serial.
Stores all communicators and groups.
The class representing the stencil, which is used for non-local mesh operations.