95 class(box_t),
pointer :: box
96 class(coordinate_system_t),
pointer :: coord_system
98 logical :: use_curvilinear
99 logical :: use_vol_pp = .false.
101 real(real64),
allocatable :: spacing(:)
108 integer(int64) :: np_global
109 integer(int64) :: np_part_global
110 logical :: parallel_in_domains
111 type(mpi_grp_t) :: mpi_grp
112 type(par_vec_t) :: pv
113 type(partition_t) :: partition
115 real(real64),
allocatable :: x(:,:)
116 real(real64),
allocatable :: x_t(:,:)
117 real(real64),
allocatable :: chi(:,:)
118 real(real64) :: volume_element
119 real(real64),
allocatable :: vol_pp(:)
120 type(accel_mem_t) :: vol_pp_buffer
121 type(accel_mem_t) :: sqrt_vol_pp_buffer
122 real(real64),
allocatable :: jacobian_inverse(:,:,:)
124 logical :: masked_periodic_boundaries
125 character(len=256) :: periodic_boundary_mask
131 procedure :: dmesh_allreduce_0, zmesh_allreduce_0, imesh_allreduce_0, lmesh_allreduce_0
132 procedure :: dmesh_allreduce_1, zmesh_allreduce_1, imesh_allreduce_1, lmesh_allreduce_1
133 procedure :: dmesh_allreduce_2, zmesh_allreduce_2, imesh_allreduce_2, lmesh_allreduce_2
134 procedure :: dmesh_allreduce_3, zmesh_allreduce_3, imesh_allreduce_3, lmesh_allreduce_3
135 procedure :: dmesh_allreduce_4, zmesh_allreduce_4, imesh_allreduce_4, lmesh_allreduce_4
136 procedure :: dmesh_allreduce_5, zmesh_allreduce_5, imesh_allreduce_5, lmesh_allreduce_5
137 procedure :: dmesh_allreduce_6, zmesh_allreduce_6, imesh_allreduce_6, lmesh_allreduce_6
138 generic :: allreduce => dmesh_allreduce_0, zmesh_allreduce_0, imesh_allreduce_0, lmesh_allreduce_0
139 generic :: allreduce => dmesh_allreduce_1, zmesh_allreduce_1, imesh_allreduce_1, lmesh_allreduce_1
140 generic :: allreduce => dmesh_allreduce_2, zmesh_allreduce_2, imesh_allreduce_2, lmesh_allreduce_2
141 generic :: allreduce => dmesh_allreduce_3, zmesh_allreduce_3, imesh_allreduce_3, lmesh_allreduce_3
142 generic :: allreduce => dmesh_allreduce_4, zmesh_allreduce_4, imesh_allreduce_4, lmesh_allreduce_4
143 generic :: allreduce => dmesh_allreduce_5, zmesh_allreduce_5, imesh_allreduce_5, lmesh_allreduce_5
144 generic :: allreduce => dmesh_allreduce_6, zmesh_allreduce_6, imesh_allreduce_6, lmesh_allreduce_6
162 real(real64) :: u(3), v(3)
163 real(real64) :: origin(3)
164 real(real64) :: spacing
165 integer :: nu, mu, nv, mv
175 real(real64) :: origin(2)
176 real(real64) :: spacing
183 class(mesh_t),
intent(inout) :: this
187 call this%set_time_dependent(.false.)
195 class(
space_t),
intent(in) :: space
197 real(real64),
intent(in) :: alpha
198 integer,
contiguous,
intent(out) :: db(:)
207 do idir = 1, space%periodic_dim
208 db(idir) = mesh%idx%ll(idir)
210 do idir = space%periodic_dim + 1, space%dim
211 db(idir) = nint(alpha * (mesh%idx%ll(idir) - 1)) + 1
221 integer,
optional,
intent(in) :: iunit
222 type(
namespace_t),
optional,
intent(in) :: namespace
225 real(real64) :: cutoff
230 do ii = 1, this%box%dim
238 write(
message(2),
'(a, i10)')
' # inner mesh = ', this%np_global
239 write(
message(3),
'(a, i10)')
' # total mesh = ', this%np_part_global
251 pure subroutine mesh_r(mesh, ip, rr, origin, coords)
252 class(
mesh_t),
intent(in) :: mesh
253 integer,
intent(in) :: ip
254 real(real64),
intent(out) :: rr
255 real(real64),
intent(in),
optional :: origin(:)
256 real(real64),
intent(out),
optional :: coords(:)
258 real(real64) :: xx(1:mesh%box%dim)
261 if (
present(origin)) xx = xx - origin
264 if (
present(coords))
then
273 integer(int64),
intent(in) :: ipg
274 real(real64),
intent(out) :: rr
275 real(real64),
contiguous,
intent(in),
optional :: origin(:)
276 real(real64),
contiguous,
intent(out),
optional :: coords(:)
278 real(real64) :: xx(1:mesh%box%dim)
281 if (
present(origin)) xx = xx - origin
284 if (
present(coords))
then
296 class(
mesh_t),
intent(in) :: mesh
297 real(real64),
intent(in) :: pos(:)
298 real(real64),
intent(out) :: dmin
299 integer,
intent(out) :: rankmin
310 dd = sum((pos - mesh%x(:, ip))**2)
311 if ((dd < dmin) .or. (ip == 1))
then
318 call mesh%mpi_grp%bcast(imin, 1, mpi_integer, rankmin)
326 class(
mesh_t),
intent(in ) :: mesh
327 real(real64),
contiguous,
intent(inout) :: values(:, :)
329 integer :: i, ip, ndim
331 real(real64) :: dummy
335 if (mesh%parallel_in_domains)
then
336 ndim =
size(values, 1)
337 do i = 1,
size(values, 2)
340 if (mesh%mpi_grp%rank == process) values(:, i) = mesh%x(:, ip)
341 call mesh%mpi_grp%bcast(values(:, i), ndim, mpi_double_precision, process)
344 do i = 1,
size(values, 2)
346 values(:, i) = mesh%x(:, ip)
360 class(
mesh_t),
intent(in) :: mesh
363 gmax =
m_pi / (maxval(mesh%spacing))
370 type(
mesh_t),
intent(in) :: mesh
371 character(len=*),
intent(in) :: dir
372 character(len=*),
intent(in) :: filename
373 type(mpi_grp_t),
intent(in) :: mpi_grp
374 type(namespace_t),
intent(in) :: namespace
375 integer,
intent(out) :: ierr
383 iunit = io_open(trim(dir)//
"/"//trim(filename), namespace, action=
'write', &
384 die=.false., grp=mpi_grp)
385 if (iunit == -1)
then
386 message(1) =
"Unable to open file '"//trim(dir)//
"/"//trim(filename)//
"'."
387 call messages_warning(1, namespace=namespace)
390 if (mpi_grp%is_root())
then
391 write(iunit,
'(a20,i21)')
'np_part_global= ', mesh%np_part_global
392 write(iunit,
'(a20,i21)')
'np_global= ', mesh%np_global
393 write(iunit,
'(a20,i21)')
'algorithm= ', 1
394 write(iunit,
'(a20,i21)')
'checksum= ', mesh%idx%checksum
395 write(iunit,
'(a20,i21)')
'bits= ', mesh%idx%bits
396 write(iunit,
'(a20,i21)')
'dim= ', mesh%idx%dim
397 write(iunit,
'(a20,i21)')
'type= ', mesh%idx%type
398 do ii = 1, mesh%idx%dim
399 write(iunit,
'(a7,i2,a11,i21)')
'offset(',ii,
')= ', mesh%idx%offset(ii)
401 do ii = 1, mesh%idx%dim
402 write(iunit,
'(a7,i2,a11,i21)')
'nn(',ii,
')= ', mesh%idx%nr(2, ii) - mesh%idx%nr(1, ii) + 1
405 call io_close(iunit, grp=mpi_grp)
418 read_np_part, read_np, bits, type, offset, nn, ierr)
419 type(
mesh_t),
intent(in) :: mesh
420 character(len=*),
intent(in) :: dir
421 character(len=*),
intent(in) :: filename
422 type(mpi_grp_t),
intent(in) :: mpi_grp
423 type(namespace_t),
intent(in) :: namespace
424 integer(int64),
intent(out) :: read_np_part
425 integer(int64),
intent(out) :: read_np
426 integer,
intent(out) :: bits
427 integer,
intent(out) :: type
428 integer,
intent(out) :: offset(1:mesh%idx%dim)
429 integer,
intent(out) :: nn(1:mesh%idx%dim)
430 integer,
intent(out) :: ierr
432 character(len=20) :: str
433 character(len=100) :: lines(7)
434 integer :: iunit, algorithm, dim, err, ii
435 integer(int64) :: checksum
441 read_np_part = 0_int64
444 iunit = io_open(trim(dir)//
"/"//trim(filename), namespace, action=
'read', &
445 status=
'old', die=.false., grp=mpi_grp)
446 if (iunit == -1)
then
448 message(1) =
"Unable to open file '"//trim(dir)//
"/"//trim(filename)//
"'."
449 call messages_warning(1, namespace=namespace)
451 call iopar_read(mpi_grp, iunit, lines, 7, err)
455 read(lines(1),
'(a20,i21)') str, read_np_part
456 read(lines(2),
'(a20,i21)') str, read_np
457 read(lines(3),
'(a20,i21)') str, algorithm
458 read(lines(4),
'(a20,i21)') str, checksum
459 read(lines(5),
'(a20,i21)') str, bits
460 read(lines(6),
'(a20,i21)') str, dim
461 read(lines(7),
'(a20,i21)') str,
type
463 if (dim /= mesh%idx%dim)
then
467 call iopar_read(mpi_grp, iunit, lines, dim, err)
472 read(lines(ii),
'(a20,i21)') str, offset(ii)
477 call iopar_read(mpi_grp, iunit, lines, dim, err)
482 read(lines(ii),
'(a20,i21)') str, nn(ii)
487 assert(read_np_part >= read_np)
489 if (read_np_part == mesh%np_part_global &
490 .and. read_np == mesh%np_global &
491 .and. algorithm == 1 &
492 .and. checksum == mesh%idx%checksum)
then
498 call io_close(iunit, grp=mpi_grp)
506 type(
mesh_t),
intent(in) :: mesh
507 character(len=*),
intent(in) :: dir
508 character(len=*),
intent(in) :: filename
509 type(namespace_t),
intent(in) :: namespace
510 type(mpi_grp_t),
intent(in) :: mpi_grp
511 logical,
intent(out) :: grid_changed
512 logical,
intent(out) :: grid_reordered
513 integer(int64),
allocatable,
intent(out) :: map(:)
514 integer,
intent(out) :: ierr
516 integer(int64) :: ipg, ipg_new, read_np_part, read_np
518 integer :: bits,
type, offset(mesh%idx%dim), point(mesh%idx%dim), nn(mesh%idx%dim)
519 integer(int64),
allocatable :: read_indices(:)
520 type(index_t) :: idx_old
526 grid_changed = .false.
527 grid_reordered = .false.
531 bits,
type, offset, nn, err)
534 message(1) =
"Unable to read mesh fingerprint from '"//trim(dir)//
"/"//trim(filename)//
"'."
535 call messages_warning(1, namespace=namespace)
537 else if (read_np > 0)
then
538 if (.not.
associated(mesh%box))
then
543 grid_changed = .
true.
548 grid_reordered = (read_np == mesh%np_global)
551 safe_allocate(read_indices(1:read_np_part))
552 call io_binary_read(trim(io_workpath(dir, namespace))//
"/indices.obf", read_np_part, &
556 message(1) =
"Unable to read index map from '"//trim(dir)//
"'."
557 call messages_warning(1, namespace=namespace)
560 call index_init(idx_old, mesh%idx%dim)
563 idx_old%nr(1, :) = -offset
564 idx_old%nr(2, :) = -offset + nn - 1
565 idx_old%offset = offset
566 idx_old%stride(1) = 1
567 do idir = 2, mesh%idx%dim
568 idx_old%stride(idir) = idx_old%stride(idir-1) * nn(idir-1)
571 safe_allocate(map(1:read_np))
574 call index_spatial_to_point(idx_old, mesh%idx%dim, read_indices(ipg), point)
579 if (map(ipg) > mesh%np_global) map(ipg) = 0
581 if (map(ipg) == 0) grid_reordered = .false.
583 call index_end(idx_old)
586 safe_deallocate_a(read_indices)
596 class(
mesh_t),
intent(inout) :: this
601 call lmpi_destroy_shared_memory_window(this%idx%window_grid_to_spatial)
602 call lmpi_destroy_shared_memory_window(this%idx%window_spatial_to_grid)
603 nullify(this%idx%grid_to_spatial_global)
604 nullify(this%idx%spatial_to_grid_global)
606 safe_deallocate_p(this%idx%grid_to_spatial_global)
607 safe_deallocate_p(this%idx%spatial_to_grid_global)
610 safe_deallocate_a(this%x)
611 safe_deallocate_a(this%chi)
612 if (this%use_vol_pp .and. accel_is_enabled())
then
613 call accel_free_buffer(this%vol_pp_buffer)
614 call accel_free_buffer(this%sqrt_vol_pp_buffer)
616 safe_deallocate_a(this%vol_pp)
617 safe_deallocate_a(this%jacobian_inverse)
619 if (this%parallel_in_domains)
then
620 call par_vec_end(this%pv)
621 call partition_end(this%partition)
624 call index_end(this%idx)
625 safe_deallocate_a(this%spacing)
638 class(
mesh_t),
intent(in) :: mesh
639 class(space_t),
intent(in) :: space
640 integer,
intent(in) :: ip
642 integer :: ix(space%dim), nr(2, space%dim), idim
643 real(real64) :: xx(space%dim), rr, ufn_re, ufn_im
648 nr(1, :) = mesh%idx%nr(1, :) + mesh%idx%enlarge(:)
649 nr(2, :) = mesh%idx%nr(2, :) - mesh%idx%enlarge(:)
651 do idim = 1, space%periodic_dim
652 do while (ix(idim) < nr(1, idim))
653 ix(idim) = ix(idim) + mesh%idx%ll(idim)
655 do while (ix(idim) > nr(2, idim))
656 ix(idim) = ix(idim) - mesh%idx%ll(idim)
663 if (mesh%masked_periodic_boundaries)
then
664 call mesh_r(mesh, ip, rr, coords = xx)
665 call parse_expression(ufn_re, ufn_im, space%dim, xx, rr, m_zero, mesh%periodic_boundary_mask)
672 class(
mesh_t),
intent(in) :: mesh
673 class(space_t),
intent(in) :: space
674 integer(int64),
intent(in) :: ipg_in
676 integer :: ix(space%dim), nr(2, space%dim), idim
677 real(real64) :: xx(space%dim), rr, ufn_re, ufn_im
682 nr(1, :) = mesh%idx%nr(1, :) + mesh%idx%enlarge(:)
683 nr(2, :) = mesh%idx%nr(2, :) - mesh%idx%enlarge(:)
685 do idim = 1, space%periodic_dim
686 if (ix(idim) < nr(1, idim)) ix(idim) = ix(idim) + mesh%idx%ll(idim)
687 if (ix(idim) > nr(2, idim)) ix(idim) = ix(idim) - mesh%idx%ll(idim)
693 if (mesh%masked_periodic_boundaries)
then
695 call parse_expression(ufn_re, ufn_im, space%dim, xx, rr, m_zero, mesh%periodic_boundary_mask)
696 if (int(ufn_re) == 0) ipg = ipg_in
705 use iso_c_binding,
only: c_sizeof, c_long_long
706 class(
mesh_t),
intent(in) :: mesh
709 memory = c_sizeof(c_long_long) * real(mesh%np_part_global, real64) * 2
716 use iso_c_binding,
only: c_sizeof, c_long_long
717 class(
mesh_t),
intent(in) :: mesh
722 memory = memory + real64 * real(mesh%np_part, real64) * mesh%idx%dim
724 memory = memory + c_sizeof(c_long_long) * real(mesh%np_part, real64) * 2
731 class(
mesh_t),
intent(in) :: mesh
732 integer(int64),
intent(in) :: ipg
733 real(real64) :: xx(1:mesh%box%dim)
735 real(real64) :: chi(1:mesh%box%dim)
736 integer :: ix(1:mesh%box%dim)
741 chi = ix * mesh%spacing
742 xx = mesh%coord_system%to_cartesian(chi)
749 class(
mesh_t),
intent(in) :: mesh
750 type(symmetries_t),
intent(in) :: symm
751 integer,
intent(in) :: periodic_dim
753 integer :: iop, ip, idim, nops, ix(1:3)
754 real(real64) :: destpoint(1:3), srcpoint(1:3), lsize(1:3), offset(1:3)
755 real(real64),
parameter :: tol_spacing = 1e-12_real64
763 if (mesh%idx%ll(1) == mesh%idx%ll(2) .and. &
764 mesh%idx%ll(2) == mesh%idx%ll(3) .and. &
765 abs(mesh%spacing(1) - mesh%spacing(2)) < tol_spacing .and. &
766 abs(mesh%spacing(2) - mesh%spacing(3)) < tol_spacing)
return
770 message(1) =
"Checking if the real-space grid is symmetric"
771 call messages_info(1)
773 lsize(1:3) = real(mesh%idx%ll(1:3), real64)
774 offset(1:3) = real(mesh%idx%nr(1, 1:3) + mesh%idx%enlarge(1:3), real64)
776 nops = symmetries_number(symm)
783 destpoint(1:3) = real(ix(1:3), real64) - offset(1:3)
785 assert(all(destpoint >= 0))
786 assert(all(destpoint < lsize))
789 destpoint = destpoint - real(int(lsize)/2, real64)
793 destpoint(idim) = destpoint(idim)/lsize(idim)
798 srcpoint = symm_op_apply_red(symm%ops(iop), destpoint)
802 srcpoint(idim) = srcpoint(idim)*lsize(idim)
806 srcpoint = srcpoint + real(int(lsize)/2, real64)
809 do idim = 1, periodic_dim
810 if (nint(srcpoint(idim)) < 0 .or. nint(srcpoint(idim)) >= lsize(idim))
then
811 srcpoint(idim) = modulo(srcpoint(idim)+m_half*symprec, lsize(idim))
814 assert(all(srcpoint >= -symprec))
815 assert(all(srcpoint < lsize))
817 srcpoint(1:3) = srcpoint(1:3) + offset(1:3)
819 if (any(srcpoint-anint(srcpoint)> symprec*m_two))
then
820 message(1) =
"The real-space grid breaks at least one of the symmetries of the system."
821 message(2) =
"Change your spacing or use SymmetrizeDensity=no."
822 call messages_fatal(2)
833 class(
mesh_t),
intent(in) :: mesh
834 integer,
intent(in) :: ix(:)
836 index = index_from_coords(mesh%idx, ix)
842 type(
mesh_t),
intent(in) :: mesh
843 integer(int64),
intent(in) :: ipg
844 integer,
contiguous,
intent(out) :: ix(:)
846 call index_to_coords(mesh%idx, ipg, ix)
852 type(
mesh_t),
intent(in) :: mesh
853 integer,
intent(in) :: ix(:)
855 integer(int64) :: ipg
857 ipg = index_from_coords(mesh%idx, ix)
864 type(
mesh_t),
intent(in) :: mesh
865 integer,
intent(in) :: ip
866 integer,
contiguous,
intent(out) :: ix(:)
868 integer(int64) :: ipg
871 call index_to_coords(mesh%idx, ipg, ix)
876 type(
mesh_t),
intent(in) :: mesh
877 integer,
intent(in) :: ip
879 ipg = par_vec_local2global(mesh%pv, ip)
886 type(
mesh_t),
intent(in) :: mesh
887 integer(int64),
intent(in) :: ipg
889 ip = par_vec_global2local(mesh%pv, ipg)
895 type(
mesh_t),
intent(in) :: mesh
896 real(real64),
intent(inout) :: min_or_max
897 integer,
intent(out) :: rank_min_or_max
898 type(mpi_op),
intent(in) :: op
900 real(real64) :: loc_in(2), loc_out(2)
904 assert(op == mpi_minloc .or. op == mpi_maxloc)
907 if (mesh%parallel_in_domains)
then
908 loc_in(1) = min_or_max
909 loc_in(2) = mesh%mpi_grp%rank
910 call mesh%mpi_grp%allreduce(loc_in, loc_out, 1, mpi_2double_precision, op)
911 min_or_max = loc_out(1)
912 rank_min_or_max = nint(loc_out(2))
920 class(
mesh_t),
intent(in) :: mesh
921 type(space_t),
intent(in) :: space
929 do idir = 1, space%periodic_dim
930 mesh_red_min(idir) = real(mesh%idx%nr(1, idir) + mesh%idx%enlarge(idir), real64) &
931 / real(mesh%idx%ll(idir), real64)
941#include "mesh_inc.F90"
944#include "complex.F90"
945#include "mesh_inc.F90"
948#include "integer.F90"
949#include "mesh_inc.F90"
952#include "integer8.F90"
953#include "mesh_inc.F90"
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
This module implements a simple hash table for non-negative integer keys and integer values.
This module implements the index, used for the mesh points.
This module defines the meshes, which are used in Octopus.
integer(int64) function, public mesh_periodic_point(mesh, space, ip)
This function returns the point inside the grid corresponding to a boundary point when PBCs are used....
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 function, public mesh_local_index_from_coords(mesh, ix)
This function returns the local index of the point for a given vector of integer coordinates.
subroutine, public mesh_double_box(space, mesh, alpha, db)
finds the dimension of a box doubled in the non-periodic dimensions
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_check_symmetries(mesh, symm, periodic_dim)
subroutine, public mesh_write_info(this, iunit, namespace)
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.
subroutine, public mesh_discretize_values_to_mesh(mesh, values)
Assign a set of values to their nearest discrete points on the mesh.
integer function, public mesh_nearest_point(mesh, pos, dmin, rankmin)
Returns the index of the point which is nearest to a given vector position pos.
integer(int64) function, public mesh_periodic_point_global(mesh, space, ipg_in)
real(real64) pure function, public mesh_global_memory(mesh)
subroutine, public mesh_read_fingerprint(mesh, dir, filename, mpi_grp, namespace, read_np_part, read_np, bits, type, offset, nn, ierr)
This function reads the fingerprint of a mesh written in filename. If the meshes are equal (same fing...
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
subroutine, public mesh_check_dump_compatibility(mesh, dir, filename, namespace, mpi_grp, grid_changed, grid_reordered, map, ierr)
real(real64) function, public mesh_gcutoff(mesh)
mesh_gcutoff returns the "natural" band limitation of the grid mesh, in terms of the maximum G vector...
real(real64) function, dimension(space%dim) mesh_red_min(mesh, space)
Helper routine to compute the minimal index of the mesh in reduced coordinate.
subroutine, public mesh_minmaxloc(mesh, min_or_max, rank_min_or_max, op)
Given a local min/max this returns the global min/max and the rank where this is located.
integer function, public mesh_global2local(mesh, ipg)
This function returns the local mesh index for a given global index.
recursive subroutine, public mesh_end(this)
real(real64) pure function, public mesh_local_memory(mesh)
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 mesh_r_global(mesh, ipg, rr, origin, coords)
return the distance to the origin for a given grid point
subroutine, public mesh_write_fingerprint(mesh, dir, filename, mpi_grp, namespace, ierr)
subroutine mesh_init(this)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module contains some common usage patterns of MPI routines.
Some general things and nomenclature:
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
abstract class for basis sets
This data type defines a line, and a regular grid defined on this line (or rather,...
define a grid on a plane.
Describes mesh distribution to nodes.