63 integer,
parameter :: INNER_POINT = 1
64 integer,
parameter :: ENLARGEMENT_POINT = 2
65 integer,
parameter :: BOUNDARY = -1
76 subroutine mesh_init_stage_1(mesh, namespace, space, box, coord_system, spacing, enlarge)
77 class(mesh_t),
intent(inout) :: mesh
78 type(namespace_t),
intent(in) :: namespace
79 class(space_t),
intent(in) :: space
80 class(box_t),
target,
intent(in) :: box
81 class(coordinate_system_t),
target,
intent(in) :: coord_system
82 real(real64),
intent(in) :: spacing(1:space%dim)
83 integer,
intent(in) :: enlarge(1:space%dim)
85 integer :: idir, jj, delta
86 real(real64) :: x(space%dim), chi(space%dim), spacing_new(-1:1), box_bounds(2, space%dim)
93 safe_allocate(mesh%spacing(1:space%dim))
94 mesh%spacing = spacing
96 mesh%use_curvilinear = coord_system%local_basis
97 mesh%coord_system => coord_system
100 mesh%idx%enlarge = enlarge
103 select type (coord_system)
111 do idir = 1, space%dim
118 chi(idir) = real(jj, real64) * mesh%spacing(idir)
119 if (mesh%use_curvilinear)
then
120 x = coord_system%to_cartesian(chi)
127 mesh%idx%nr(2, idir) = jj - 1
131 mesh%idx%nr(1,:) = -mesh%idx%nr(2,:)
134 do idir = 1, space%periodic_dim
135 if (mesh%idx%nr(2, idir) == 0)
then
137 mesh%idx%nr(2, idir) = 1
138 mesh%idx%nr(1, idir) = -1
146 spacing_new(delta) =
m_two*maxval(abs(
box_bounds(:, idir))) / real(2 * mesh%idx%nr(2, idir) + 1 - delta, real64)
147 spacing_new(delta) = abs(spacing_new(delta) - spacing(idir))
150 delta = minloc(spacing_new, dim = 1) - 2
155 mesh%spacing(idir) =
m_two*maxval(abs(
box_bounds(:, idir))) / real(2 * mesh%idx%nr(2, idir) + 1 - delta, real64)
158 if (delta == -1)
then
159 mesh%idx%nr(1, idir) = mesh%idx%nr(1, idir) - 1
160 else if (delta == 1)
then
161 mesh%idx%nr(2, idir) = mesh%idx%nr(2, idir) - 1
166 if ( any(abs(mesh%spacing - spacing) > 1.e-6_real64) )
then
167 call messages_write(
'The spacing has been modified to make it commensurate with the periodicity of the system.')
171 do idir = space%periodic_dim + 1, space%dim
172 if (mesh%idx%nr(2, idir) == 0)
then
173 write(
message(1),
'(a,i2)')
'Spacing > box size in direction ', idir
178 mesh%idx%ll = mesh%idx%nr(2, :) - mesh%idx%nr(1, :) + 1
180 mesh%idx%stride(:) = 1
181 do idir = 2, space%dim+1
182 mesh%idx%stride(idir) = mesh%idx%stride(idir-1) * &
183 (mesh%idx%ll(idir-1) + 2*mesh%idx%enlarge(idir-1))
196 subroutine mesh_init_stage_2(mesh, namespace, space, box, stencil, grp, regenerate)
197 class(
mesh_t),
intent(inout) :: mesh
199 class(
space_t),
intent(in) :: space
200 class(
box_t),
intent(in) :: box
203 logical,
optional,
intent(in) :: regenerate
206 real(real64) :: chi(1:space%dim)
207 real(real64) :: pos(space%dim)
208 integer :: point(space%dim), point_stencil(space%dim), grid_sizes(space%dim)
209 integer(int64) :: global_size
210 integer(int32) :: local_size
211 integer(int64) :: ispatial, ispatialb, istart, iend, spatial_size, ipg
212 integer :: ip, ib, ib2, np, np_boundary, ii
214 type(
lihash_t) :: spatial_to_boundary
215 integer(int64),
allocatable :: boundary_to_spatial(:), boundary_to_spatial_reordered(:)
216 integer(int64),
allocatable :: grid_to_spatial(:), grid_to_spatial_initial(:), grid_to_spatial_reordered(:)
217 integer(int64),
allocatable :: spatial_to_grid(:)
218 integer,
allocatable :: sizes(:)
219 integer(int64),
allocatable :: offsets(:)
220 integer :: size_boundary
222 integer(int64),
pointer :: ptr(:)
223 type(
mpi_grp_t) :: internode_grp, intranode_grp
230 mesh%idx%nr(1, :) = mesh%idx%nr(1, :) - mesh%idx%enlarge(:)
231 mesh%idx%nr(2, :) = mesh%idx%nr(2, :) + mesh%idx%enlarge(:)
248 grid_sizes = mesh%idx%nr(2, :) - mesh%idx%nr(1, :) + 1
249 mesh%idx%offset = grid_sizes/2
250 if (space%dim > 1 .and. any(grid_sizes > 2**(int(63/space%dim, int64))))
then
251 write(
message(1),
'(A, I10, A, I2, A)')
"Error: grid too large, more than ", 2**(int(63/space%dim, int64)), &
252 " points in one direction for ", space%dim,
" dimensions. This is not supported."
255 global_size = product(int(grid_sizes, int64))
257 mesh%idx%bits = maxval(ceiling(
log(real(grid_sizes, real64) )/
log(2.0_real64)))
260 spatial_size = global_size
262 spatial_size = 2**(space%dim*mesh%idx%bits)
266 istart = spatial_size * grp%rank/grp%size
267 iend = spatial_size * (grp%rank+1)/grp%size - 1
268 if (.not. (iend - istart + 1 < huge(0_int32)))
then
269 write(
message(1),
'(A, I10, A, I2, A)')
"Error: local grid too large, more than ", &
270 huge(0_int32),
" points. This is not supported. Maybe use more MPI ranks?"
273 local_size = int(iend - istart + 1, int32)
275 safe_allocate(grid_to_spatial_initial(1:local_size))
279 do ispatial = istart, iend
282 if (any(point < mesh%idx%nr(1, :) + mesh%idx%enlarge)) cycle
283 if (any(point > mesh%idx%nr(2, :) - mesh%idx%enlarge)) cycle
285 chi = real(point, real64) * mesh%spacing
286 pos = mesh%coord_system%to_cartesian(chi)
287 if (.not. box%contains_point(pos)) cycle
288 grid_to_spatial_initial(ip) = ispatial
289 assert(ip + 1 < huge(ip))
294 call rebalance_array(grp,grid_to_spatial_initial(1:np), grid_to_spatial, sizes)
297 safe_deallocate_a(grid_to_spatial_initial)
299 safe_allocate(spatial_to_grid(grid_to_spatial(1):grid_to_spatial(np)))
300 safe_deallocate_a(sizes)
303 do ispatial = grid_to_spatial(1), grid_to_spatial(np)
304 spatial_to_grid(ispatial) = -1
308 spatial_to_grid(grid_to_spatial(ip)) = ip
314 safe_allocate(boundary_to_spatial(1:size_boundary))
318 do is = 1, stencil%size
319 if (stencil%center == is) cycle
320 point_stencil(1:space%dim) = point(1:space%dim) + stencil%points(1:space%dim, is)
323 assert(ispatialb >= 0)
324 if (ispatialb >= lbound(spatial_to_grid, dim=1, kind=int64) .and. &
325 ispatialb <= ubound(spatial_to_grid, dim=1, kind=int64))
then
326 if (spatial_to_grid(ispatialb) > 0) cycle
329 chi = real(point_stencil, real64) * mesh%spacing
330 pos = mesh%coord_system%to_cartesian(chi)
331 if (box%contains_point(pos)) cycle
336 boundary_to_spatial(ib) = ispatialb
340 if (ib >= size_boundary)
then
341 size_boundary = size_boundary * 2
348 safe_deallocate_a(spatial_to_grid)
351 call reorder_points(namespace, space, grp, mesh%idx, grid_to_spatial, grid_to_spatial_reordered)
352 safe_deallocate_a(grid_to_spatial)
354 call rebalance_array(grp,grid_to_spatial_reordered, grid_to_spatial, sizes)
356 mesh%np_global = sizes(0)
357 do ii = 1, grp%size - 1
358 mesh%np_global = mesh%np_global + sizes(ii)
360 safe_deallocate_a(sizes)
361 safe_deallocate_a(grid_to_spatial_reordered)
365 call reorder_points(namespace, space, grp, mesh%idx, boundary_to_spatial, boundary_to_spatial_reordered)
366 safe_deallocate_a(boundary_to_spatial)
368 call rebalance_array(grp,boundary_to_spatial_reordered, boundary_to_spatial, sizes)
369 safe_deallocate_a(boundary_to_spatial_reordered)
372 np_boundary = sizes(grp%rank)
373 mesh%np_part_global = mesh%np_global + sizes(0)
374 do ii = 1, grp%size - 1
375 mesh%np_part_global = mesh%np_part_global + sizes(ii)
377 safe_deallocate_a(sizes)
383 call create_intranode_communicator(grp, intranode_grp, internode_grp)
384 call lmpi_create_shared_memory_window(mesh%np_part_global, intranode_grp, &
385 mesh%idx%window_grid_to_spatial, mesh%idx%grid_to_spatial_global)
387 safe_allocate(mesh%idx%grid_to_spatial_global(1:mesh%np_part_global))
391 call grp%gatherv(grid_to_spatial, np, mpi_integer8, &
392 mesh%idx%grid_to_spatial_global, sizes, offsets, mpi_integer8, 0)
396 call grp%gatherv(boundary_to_spatial, np_boundary, mpi_integer8, &
397 mesh%idx%grid_to_spatial_global(mesh%np_global+1:), sizes, offsets, mpi_integer8, 0)
402 call lmpi_create_shared_memory_window(spatial_size, intranode_grp, &
403 mesh%idx%window_spatial_to_grid, ptr)
404 mesh%idx%spatial_to_grid_global(0:spatial_size-1) => ptr(1:spatial_size)
406 safe_allocate(mesh%idx%spatial_to_grid_global(0:spatial_size-1))
408 if (grp%is_root())
then
411 do ispatial = 0, spatial_size-1
412 mesh%idx%spatial_to_grid_global(ispatial) = 0
415 do ipg = 1, mesh%np_part_global
416 mesh%idx%spatial_to_grid_global(mesh%idx%grid_to_spatial_global(ipg)) = ipg
422 if (intranode_grp%is_root())
then
423 call internode_grp%bcast(mesh%idx%grid_to_spatial_global(1), mesh%np_part_global, mpi_integer8, 0)
424 call internode_grp%bcast(mesh%idx%spatial_to_grid_global(0), spatial_size, mpi_integer8, 0)
426 call lmpi_sync_shared_memory_window(mesh%idx%window_grid_to_spatial, intranode_grp)
427 call lmpi_sync_shared_memory_window(mesh%idx%window_spatial_to_grid, intranode_grp)
430 safe_deallocate_a(offsets)
431 safe_deallocate_a(sizes)
433 safe_deallocate_a(boundary_to_spatial)
434 safe_deallocate_a(grid_to_spatial)
445 subroutine mesh_init_stage_3(mesh, namespace, space, stencil, mc, parent, regenerate)
446 class(
mesh_t),
intent(inout) :: mesh
448 class(
space_t),
intent(in) :: space
451 type(
mesh_t),
optional,
intent(in) :: parent
452 logical,
optional,
intent(in) :: regenerate
454 integer :: ip, jj(space%dim), np
461 mesh%parallel_in_domains = (mesh%mpi_grp%size > 1)
466 if (mesh%parallel_in_domains)
then
470 assert(mesh%np_part_global < huge(mesh%np_part))
472 mesh%np_part =
i8_to_i4(mesh%np_part_global)
476 mesh%pv%np_global = mesh%np_global
478 mesh%pv%np_bndry = mesh%np_part - mesh%np
484 safe_allocate(mesh%x(1:space%dim, 1:mesh%np_part))
485 safe_allocate(mesh%x_t(1:mesh%np_part, 1:space%dim))
486 do ip = 1, mesh%np_part
488 mesh%x_t(ip, 1:space%dim) = mesh%x(1:space%dim, ip)
492 safe_allocate(mesh%chi(1:space%dim, 1:mesh%np_part))
493 do ip = 1, mesh%np_part
495 mesh%chi(:, ip) = jj*mesh%spacing
501 if (mesh%coord_system%local_basis)
then
506 safe_allocate(mesh%jacobian_inverse(1:space%dim, 1:space%dim, np))
508 mesh%jacobian_inverse(:, :, ip) = mesh%coord_system%jacobian_inverse(mesh%chi(:, ip))
517 integer :: jj, ipart, jpart
518 integer(int64) :: ipg, jpg
519 integer,
allocatable :: gindex(:), gedges(:)
520 logical,
allocatable :: nb(:, :)
521 integer :: idx(space%dim), jx(space%dim)
522 type(mpi_comm) :: graph_comm
523 integer :: iedge, nnb
524 logical :: use_topo, reorder, partition_print
527 logical :: has_virtual_partition = .false.
529 type(
restart_t) :: restart_load, restart_dump
530 integer,
allocatable :: part_vec(:)
538 call restart_load%end()
553 call parse_variable(namespace,
'MeshPartitionVirtualSize', mesh%mpi_grp%size, vsize)
555 if (vsize /= mesh%mpi_grp%size)
then
556 write(
message(1),
'(a,I7)')
"Changing the partition size to", vsize
557 write(
message(2),
'(a)')
"The execution will crash."
559 has_virtual_partition = .
true.
561 has_virtual_partition = .false.
564 if (.not.
present(parent))
then
574 call restart_dump%end()
577 if (has_virtual_partition)
then
580 write(
message(1),
'(a)')
"Execution has ended."
581 write(
message(2),
'(a)')
"If you want to run your system, do not use MeshPartitionVirtualSize."
597 call parse_variable(namespace,
'MeshUseTopology', .false., use_topo)
601 safe_allocate(part_vec(1:mesh%np_global))
607 safe_allocate(nb(1:mesh%mpi_grp%size, 1:mesh%mpi_grp%size))
610 do ipg = 1, mesh%np_global
611 ipart = part_vec(ipg)
613 do jj = 1, stencil%size
614 jx = idx + stencil%points(:, jj)
616 if (jpg > 0 .and. jpg <= mesh%np_global)
then
617 jpart = part_vec(jpg)
618 if (ipart /= jpart ) nb(ipart, jpart) = .
true.
622 safe_deallocate_a(part_vec)
626 safe_allocate(gindex(1:mesh%mpi_grp%size))
627 safe_allocate(gedges(1:count(nb)))
631 do ipart = 1, mesh%mpi_grp%size
632 do jpart = 1, mesh%mpi_grp%size
633 if (nb(ipart, jpart))
then
635 gedges(iedge) = jpart - 1
638 gindex(ipart) = iedge
641 assert(iedge == count(nb))
644 call mpi_graph_create(mesh%mpi_grp%comm, mesh%mpi_grp%size, gindex, gedges, reorder, graph_comm)
649 safe_deallocate_a(nb)
650 safe_deallocate_a(gindex)
651 safe_deallocate_a(gedges)
656 call par_vec_init(mesh%mpi_grp, mesh%np_global, mesh%idx, stencil,&
657 space, mesh%partition, mesh%pv, namespace)
661 jpart = mesh%pv%partno
662 do ipart = 1, mesh%pv%npart
663 if (ipart == jpart) cycle
664 if (mesh%pv%ghost_scounts(ipart) /= 0) nnb = nnb + 1
666 assert(nnb >= 0 .and. nnb < mesh%pv%npart)
669 mesh%np = mesh%pv%np_local
670 mesh%np_part = mesh%np + mesh%pv%np_ghost + mesh%pv%np_bndry
683 if (partition_print)
then
702 if (mesh%use_curvilinear) np = mesh%np_part
704 if (mesh%np_part == 0) np = 0
706 safe_allocate(mesh%vol_pp(1:np))
709 mesh%vol_pp(ip) = product(mesh%spacing)
713 mesh%vol_pp(ip) = mesh%vol_pp(ip)*mesh%coord_system%jacobian_determinant(mesh%chi(:, ip))
716 if (mesh%use_curvilinear .or. mesh%np_part == 0)
then
717 mesh%volume_element =
m_one
719 mesh%volume_element = mesh%vol_pp(1)
733 integer(int64),
contiguous,
intent(in) :: data_input(:)
734 integer(int64),
allocatable,
intent(out) :: data_output(:)
735 integer,
allocatable,
optional,
intent(out) :: output_sizes(:)
737 integer,
allocatable :: initial_sizes(:), final_sizes(:)
738 integer(int64),
allocatable :: initial_offsets(:), final_offsets(:)
739 integer,
allocatable :: scounts(:), sdispls(:)
740 integer,
allocatable :: rcounts(:), rdispls(:)
742 integer(int64) :: itmp
747 safe_allocate(initial_sizes(0:grp%size-1))
748 call grp%allgather(
size(data_input), 1, mpi_integer, initial_sizes(0), 1, mpi_integer)
749 safe_allocate(initial_offsets(0:grp%size))
750 initial_offsets(0) = 0
751 do irank = 1, grp%size
752 initial_offsets(irank) = initial_offsets(irank-1) + initial_sizes(irank-1)
757 safe_allocate(final_offsets(0:grp%size))
758 safe_allocate(final_sizes(0:grp%size-1))
760 do irank = 0, grp%size
761 final_offsets(irank) = sum(int(initial_sizes, int64)) * irank/grp%size
763 do irank = 0, grp%size - 1
764 assert(final_offsets(irank + 1) - final_offsets(irank) < huge(0_int32))
765 final_sizes(irank) = int(final_offsets(irank + 1) - final_offsets(irank), int32)
768 safe_allocate(scounts(0:grp%size-1))
769 safe_allocate(sdispls(0:grp%size-1))
770 safe_allocate(rcounts(0:grp%size-1))
771 safe_allocate(rdispls(0:grp%size-1))
774 do irank = 0, grp%size - 1
776 itmp = min(final_offsets(irank+1), initial_offsets(grp%rank+1)) - &
777 max(final_offsets(irank), initial_offsets(grp%rank))
778 assert(itmp < huge(0_int32))
782 scounts(irank) = int(itmp, int32)
786 do irank = 1, grp%size - 1
787 sdispls(irank) = sdispls(irank - 1) + scounts(irank - 1)
789 assert(sum(int(scounts, int64)) < huge(0_int32))
790 assert(sum(scounts) == initial_sizes(grp%rank))
793 do irank = 0, grp%size - 1
795 itmp = min(final_offsets(grp%rank+1), initial_offsets(irank+1)) - &
796 max(final_offsets(grp%rank), initial_offsets(irank))
797 assert(itmp < huge(0_int32))
801 rcounts(irank) = int(itmp, int32)
805 do irank = 1, grp%size - 1
806 rdispls(irank) = rdispls(irank - 1) + rcounts(irank - 1)
809 assert(sum(rcounts) == final_sizes(grp%rank))
811 safe_allocate(data_output(1:final_sizes(grp%rank)))
812 call grp%alltoallv(data_input, scounts, sdispls, mpi_integer8, &
813 data_output, rcounts, rdispls, mpi_integer8)
816 if (
present(output_sizes))
then
817 safe_allocate(output_sizes(0:grp%size-1))
818 output_sizes(:) = final_sizes(:)
821 safe_deallocate_a(final_offsets)
822 safe_deallocate_a(final_sizes)
824 safe_deallocate_a(scounts)
825 safe_deallocate_a(sdispls)
826 safe_deallocate_a(rcounts)
827 safe_deallocate_a(rdispls)
837 subroutine reorder_points(namespace, space, grp, idx, grid_to_spatial, grid_to_spatial_reordered)
839 class(
space_t),
intent(in) :: space
841 type(
index_t),
intent(in) :: idx
842 integer(int64),
intent(in) :: grid_to_spatial(:)
843 integer(int64),
allocatable,
intent(out) :: grid_to_spatial_reordered(:)
845 integer :: bsize(space%dim), order, default
846 integer :: nn, idir, ipg, ip, number_of_blocks(space%dim)
848 integer,
parameter :: &
850 order_original = 2, &
852 integer :: point(1:space%dim)
853 integer(int64),
allocatable :: reorder_indices(:), reorder_recv(:)
854 integer,
allocatable :: index_map(:), indices(:)
855 integer(int64),
allocatable :: grid_to_spatial_recv(:)
856 integer,
allocatable :: initial_sizes(:)
857 integer(int64),
allocatable :: initial_offsets(:)
858 integer(int64) :: istart, iend, indstart, indend, spatial_size
859 integer :: irank, local_size, num_recv
860 integer :: iunique, nunique
862 logical :: increase_with_dimension
864 integer,
allocatable :: scounts(:), sdispls(:), rcounts(:), rdispls(:)
865 integer(int64),
allocatable :: spatial_cutoff(:)
887 default = order_blocks
890 if (space%dim == 1)
then
891 order = order_original
909 call parse_variable(namespace,
'MeshBlockDirection', 1, direction)
910 increase_with_dimension = direction == 1
911 if (direction /= 1 .and. direction /= 2)
then
916 case (order_original)
918 safe_allocate(grid_to_spatial_reordered(1:
size(grid_to_spatial)))
919 grid_to_spatial_reordered(1:
size(grid_to_spatial)) = grid_to_spatial(1:
size(grid_to_spatial))
920 case (order_blocks, order_cube)
921 if (order == order_cube)
then
922 bsize = idx%nr(2, :) - idx%nr(1, :) + 1
935 if (
conf%target_states_block_size < 16)
then
936 bsize(1) = 80 * 4 / abs(
conf%target_states_block_size)
937 if (space%dim > 1) bsize(2) = 4
938 if (space%dim > 2) bsize(3:) = 10
940 bsize(1) = max(4 * 16 / abs(
conf%target_states_block_size), 1)
941 if (space%dim > 1) bsize(2) = 15
942 if (space%dim > 2) bsize(3:) = 15
945 if (
parse_block(namespace,
'MeshBlockSize', blk) == 0)
then
947 if (nn /= space%dim)
then
948 message(1) =
"Error: number of entries in MeshBlockSize must match the number of dimensions."
957 number_of_blocks = (idx%nr(2, :) - idx%nr(1, :) + 1) / bsize + 1
964 safe_allocate(initial_sizes(0:grp%size-1))
965 call grp%allgather(
size(grid_to_spatial), 1, mpi_integer, initial_sizes(0), 1, mpi_integer)
966 safe_allocate(initial_offsets(0:grp%size))
967 initial_offsets(0) = 0
968 do irank = 1, grp%size
969 initial_offsets(irank) = initial_offsets(irank-1) + initial_sizes(irank-1)
973 istart = initial_offsets(grp%rank)
974 iend = initial_offsets(grp%rank + 1) - 1
975 assert(iend - istart + 1 < huge(0_int32))
976 local_size = int(iend - istart + 1, int32)
977 assert(local_size == initial_sizes(grp%rank))
980 safe_allocate(reorder_indices(1:local_size))
981 safe_allocate(indices(1:local_size))
982 safe_allocate(grid_to_spatial_reordered(1:local_size))
984 do ip = 1, local_size
986 point = point + idx%offset
987 reorder_indices(ip) =
get_blocked_index(space%dim, point, bsize, number_of_blocks, increase_with_dimension)
991 call sort(reorder_indices, indices)
994 do ip = 1, local_size
995 grid_to_spatial_reordered(ip) = grid_to_spatial(indices(ip))
999 if(local_size > 0)
then
1000 indstart = reorder_indices(1)
1001 indend = reorder_indices(local_size)
1003 indstart = huge(1_int64)
1006 call grp%allreduce_inplace(indstart, 1, mpi_integer8, mpi_min)
1007 call grp%allreduce_inplace(indend, 1, mpi_integer8, mpi_max)
1008 spatial_size = indend - indstart + 1
1011 safe_allocate(spatial_cutoff(0:grp%size-1))
1012 do irank = 0, grp%size - 1
1013 spatial_cutoff(irank) = spatial_size * (irank+1)/grp%size + indstart
1016 safe_allocate(scounts(0:grp%size-1))
1017 safe_allocate(sdispls(0:grp%size-1))
1018 safe_allocate(rcounts(0:grp%size-1))
1019 safe_allocate(rdispls(0:grp%size-1))
1025 do ip = 1, local_size
1026 if (reorder_indices(ip) >= spatial_cutoff(irank))
then
1028 do while (reorder_indices(ip) >= spatial_cutoff(irank))
1031 assert(irank < grp%size)
1033 scounts(irank) = scounts(irank) + 1
1035 safe_deallocate_a(spatial_cutoff)
1036 assert(sum(scounts) == local_size)
1040 do irank = 1, grp%size - 1
1041 sdispls(irank) = sdispls(irank - 1) + scounts(irank - 1)
1044 call grp%alltoall(scounts, 1, mpi_integer, &
1045 rcounts, 1, mpi_integer)
1048 do irank = 1, grp%size - 1
1049 rdispls(irank) = rdispls(irank - 1) + rcounts(irank - 1)
1053 num_recv = max(sum(rcounts), 1)
1055 safe_allocate(reorder_recv(1:num_recv))
1056 call grp%alltoallv(reorder_indices, scounts, sdispls, mpi_integer8, &
1057 reorder_recv, rcounts, rdispls, mpi_integer8)
1058 safe_deallocate_a(reorder_indices)
1061 safe_allocate(grid_to_spatial_recv(1:num_recv))
1062 call grp%alltoallv(grid_to_spatial_reordered, scounts, sdispls, mpi_integer8, &
1063 grid_to_spatial_recv, rcounts, rdispls, mpi_integer8)
1064 safe_deallocate_a(grid_to_spatial_reordered)
1067 safe_allocate(reorder_indices(1:num_recv))
1068 safe_allocate(index_map(1:num_recv))
1069 if (sum(rcounts) > 0)
then
1074 do ipg = 2, sum(rcounts)
1075 if (reorder_indices(ipg) /= reorder_indices(ipg-1))
then
1076 nunique = nunique + 1
1081 safe_allocate(grid_to_spatial_reordered(1:nunique))
1083 grid_to_spatial_reordered(iunique) = grid_to_spatial_recv(index_map(1))
1084 do ipg = 2, sum(rcounts)
1085 if (reorder_indices(ipg) /= reorder_indices(ipg-1))
then
1086 iunique = iunique + 1
1087 grid_to_spatial_reordered(iunique) = grid_to_spatial_recv(index_map(ipg))
1091 safe_allocate(grid_to_spatial_reordered(1:0))
1094 safe_deallocate_a(initial_offsets)
1095 safe_deallocate_a(initial_sizes)
1097 safe_deallocate_a(reorder_indices)
1098 safe_deallocate_a(reorder_recv)
1100 safe_deallocate_a(grid_to_spatial_recv)
1101 safe_deallocate_a(index_map)
1102 safe_deallocate_a(indices)
1104 safe_deallocate_a(scounts)
1105 safe_deallocate_a(sdispls)
1106 safe_deallocate_a(rcounts)
1107 safe_deallocate_a(rdispls)
1116 integer,
intent(in) :: local_size
1117 integer,
allocatable,
intent(out) :: sizes(:)
1118 integer(int64),
allocatable,
intent(out) :: offsets(:)
1125 safe_allocate(sizes(0:mpi_grp%size-1))
1126 call mpi_grp%allgather(local_size, 1, mpi_integer, sizes(0), 1, mpi_integer)
1127 safe_allocate(offsets(0:mpi_grp%size))
1129 do irank = 1, mpi_grp%size
1130 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__
subroutine do_partition()
subroutine mesh_get_vol_pp()
calculate the volume of integration
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.
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.