79 integer,
allocatable :: imin(:)
80 integer,
allocatable :: imax(:)
81 integer,
allocatable :: ri(:, :)
87 type(stencil_t),
public :: stencil
88 type(mesh_t),
pointer :: mesh => null()
89 integer,
allocatable :: nn(:)
90 integer,
public :: np = 0
92 real(real64),
allocatable,
public :: w(:,:)
94 logical,
public :: const_w = .
true.
96 type(accel_mem_t),
public :: buff_weights
97 type(accel_mem_t),
public :: buff_half_weights
99 character(len=40) :: label
102 integer,
public :: nri = 0
103 integer,
allocatable,
public :: ri(:,:)
104 integer,
allocatable,
public :: rimap(:)
105 integer,
allocatable,
public :: rimap_inv(:)
107 integer :: ninner = 0
108 integer :: nouter = 0
110 type(nl_operator_index_t) :: inner
111 type(nl_operator_index_t) :: outer
113 type(accel_kernel_t) :: kernel
114 type(accel_mem_t) :: buff_imin
115 type(accel_mem_t) :: buff_imax
116 type(accel_mem_t) :: buff_ri
117 type(accel_mem_t) :: buff_map
118 type(accel_mem_t) :: buff_all
119 type(accel_mem_t) :: buff_inner
120 type(accel_mem_t) :: buff_outer
121 type(accel_mem_t) :: buff_stencil
122 type(accel_mem_t) :: buff_ip_to_xyz
123 type(accel_mem_t) :: buff_xyz_to_ip
126 type(nl_operator_t),
public,
pointer :: coarser => null()
130 integer,
parameter :: &
136 integer,
parameter :: &
143 logical :: compact_boundaries
148 integer,
intent(in) :: opid, type
152 integer :: dfunction_global = -1
153 integer :: zfunction_global = -1
154 integer :: function_opencl
162 type(namespace_t),
intent(in) :: namespace
199 call parse_variable(namespace,
'OperateComplex', default, zfunction_global)
234 call parse_variable(namespace,
'NLOperatorCompactBoundaries', .false., compact_boundaries)
236 if (compact_boundaries)
then
257 character(len=*),
intent(in) :: label
285 safe_allocate_source_a(opo%nn, opi%nn)
286 safe_allocate_source_a(opo%w, opi%w)
288 opo%const_w = opi%const_w
291 assert(
allocated(opi%ri))
293 safe_allocate_source_a(opo%ri, opi%ri)
294 safe_allocate_source_a(opo%rimap, opi%rimap)
295 safe_allocate_source_a(opo%rimap_inv, opi%rimap_inv)
297 if (opi%mesh%parallel_in_domains)
then
298 opo%inner%nri = opi%inner%nri
299 safe_allocate_source_a(opo%inner%imin, opi%inner%imin)
300 safe_allocate_source_a(opo%inner%imax, opi%inner%imax)
301 safe_allocate_source_a(opo%inner%ri, opi%inner%ri)
303 opo%outer%nri = opi%outer%nri
304 safe_allocate_source_a(opo%outer%imin, opi%outer%imin)
305 safe_allocate_source_a(opo%outer%imax, opi%outer%imax)
306 safe_allocate_source_a(opo%outer%ri, opi%outer%ri)
324 class(
space_t),
intent(in) :: space
325 type(
mesh_t),
target,
intent(in) :: mesh
327 integer,
intent(in) :: np
328 logical,
optional,
intent(in) :: const_w
329 logical,
optional,
intent(in) :: regenerate
331 integer :: ii, jj, p1(space%dim), time, current
332 integer,
allocatable :: st1(:), st2(:), st1r(:)
334 integer :: ir, maxp, iinner, iouter
335 logical :: change, force_change
336 character(len=200) :: flags
337 integer,
allocatable :: inner_points(:), outer_points(:), all_points(:)
341 if (mesh%parallel_in_domains .and. .not. const_w)
then
351 if (
present(const_w)) op%const_w = const_w
355 safe_allocate(op%w(1:op%stencil%size, 1))
357 message(1) =
'Info: nl_operator_build: working with constant weights.'
361 safe_allocate(op%w(1:op%stencil%size, 1:op%np))
363 message(1) =
'Info: nl_operator_build: working with non-constant weights.'
372 safe_allocate(st1(1:op%stencil%size))
373 safe_allocate(st1r(1:op%stencil%size))
374 safe_allocate(st2(1:op%stencil%size))
383 do jj = 1, op%stencil%size
392 st1(jj) = min(st1(jj), mesh%np + 1)
397 st1(1:op%stencil%size) = st1(1:op%stencil%size) - ii
399 change = any(st1 /= st2)
403 force_change = any(st1 + ii > mesh%np) .and. all(st2 + ii - 1 <= mesh%np)
407 do jj = 1, op%stencil%size
408 if (st1(jj) + ii > mesh%np .and. st2(jj) + ii - 1 > mesh%np .and. st2(jj) + ii <= mesh%np_part)
then
415 change = any(st1r /= st2)
417 if (.not. change) st1 = st1r
421 if (change .or. force_change)
then
426 if (time == 1) op%nri = op%nri + 1
430 current = current + 1
431 op%ri(1:op%stencil%size, current) = st1(1:op%stencil%size)
435 if (time == 2) op%rimap(ii) = current
441 safe_deallocate_a(op%ri)
442 safe_deallocate_a(op%rimap)
443 safe_deallocate_a(op%rimap_inv)
445 safe_allocate(op%ri(1:op%stencil%size, 1:op%nri))
446 safe_allocate(op%rimap(1:op%np))
447 safe_allocate(op%rimap_inv(1:op%nri + 1))
454 if (mesh%use_curvilinear)
then
455 safe_allocate(op%nn(1:op%nri))
457 op%nn = op%stencil%size
466 op%rimap_inv(op%rimap(jj) + 1) = jj
468 op%rimap_inv(op%nri + 1) = op%np
470 safe_deallocate_a(st1)
471 safe_deallocate_a(st1r)
472 safe_deallocate_a(st2)
475 nn = op%rimap_inv(jj + 1) - op%rimap_inv(jj)
478 if (op%mesh%parallel_in_domains)
then
485 maxp = op%rimap_inv(ir + 1) + maxval(op%ri(1:op%stencil%size, ir))
488 op%inner%nri = op%inner%nri + 1
489 assert(op%inner%nri <= op%nri)
492 op%outer%nri = op%outer%nri + 1
493 assert(op%outer%nri <= op%nri)
497 assert(op%inner%nri + op%outer%nri == op%nri)
500 safe_deallocate_a(op%inner%imin)
501 safe_deallocate_a(op%inner%imax)
502 safe_deallocate_a(op%inner%ri)
503 safe_deallocate_a(op%outer%imin)
504 safe_deallocate_a(op%outer%imax)
505 safe_deallocate_a(op%outer%ri)
507 safe_allocate(op%inner%imin(1:op%inner%nri + 1))
508 safe_allocate(op%inner%imax(1:op%inner%nri))
509 safe_allocate(op%inner%ri(1:op%stencil%size, 1:op%inner%nri))
511 safe_allocate(op%outer%imin(1:op%outer%nri + 1))
512 safe_allocate(op%outer%imax(1:op%outer%nri))
513 safe_allocate(op%outer%ri(1:op%stencil%size, 1:op%outer%nri))
519 maxp = op%rimap_inv(ir + 1) + maxval(op%ri(1:op%stencil%size, ir))
523 op%inner%imin(iinner) = op%rimap_inv(ir)
524 op%inner%imax(iinner) = op%rimap_inv(ir + 1)
525 op%inner%ri(1:op%stencil%size, iinner) = op%ri(1:op%stencil%size, ir)
529 op%outer%imin(iouter) = op%rimap_inv(ir)
530 op%outer%imax(iouter) = op%rimap_inv(ir + 1)
531 op%outer%ri(1:op%stencil%size, iouter) = op%ri(1:op%stencil%size, ir)
536 do ir = 1, op%inner%nri
537 do ii = op%inner%imin(ir) + 1, op%inner%imax(ir)
538 assert(all(ii + op%inner%ri(1:op%stencil%size, ir) <= mesh%np))
546 write(flags,
'(i5)') op%stencil%size
547 flags=
'-DNDIM=3 -DSTENCIL_SIZE='//trim(adjustl(flags))
549 if (op%mesh%parallel_in_domains) flags =
'-DINDIRECT '//trim(flags)
551 select case (function_opencl)
562 select case (function_opencl)
574 if (op%mesh%parallel_in_domains)
then
576 safe_allocate(inner_points(1:op%mesh%np))
577 safe_allocate(outer_points(1:op%mesh%np))
578 safe_allocate(all_points(1:op%mesh%np))
583 do ii = 1, op%mesh%np
584 all_points(ii) = ii - 1
585 maxp = ii + maxval(op%ri(1:op%stencil%size, op%rimap(ii)))
586 if (maxp <= op%mesh%np)
then
587 op%ninner = op%ninner + 1
588 inner_points(op%ninner) = ii - 1
590 op%nouter = op%nouter + 1
591 outer_points(op%nouter) = ii - 1
604 safe_deallocate_a(inner_points)
605 safe_deallocate_a(outer_points)
606 safe_deallocate_a(all_points)
620 integer :: istencil, idir
626 write(
message(1),
'(3a)')
'Debug info: Finite difference weights for ', trim(this%label),
'.'
627 write(
message(2),
'(a)')
' Spacing:'
628 do idir = 1, this%mesh%box%dim
629 write(
message(2),
'(a,f16.8)') trim(
message(2)), this%mesh%spacing(idir)
633 do istencil = 1, this%stencil%size
634 select case(this%mesh%box%dim)
636 write(
message(1),
'(a,i3,1i4,f25.10)')
' ', istencil, this%stencil%points(1:1, istencil), this%w(istencil, 1)
638 write(
message(1),
'(a,i3,2i4,f25.10)')
' ', istencil, this%stencil%points(1:2, istencil), this%w(istencil, 1)
640 write(
message(1),
'(a,i3,3i4,f25.10)')
' ', istencil, this%stencil%points(1:3, istencil), this%w(istencil, 1)
656 type(
mesh_t),
target,
intent(in) :: mesh
657 logical,
intent(in) :: self_adjoint
659 integer :: ip, jp, kp, lp, index, ii, p1(1:mesh%box%dim)
660 real(real64),
pointer,
contiguous :: vol_pp(:),
weights(:, :), tmp(:)
661 real(real64) :: factor
665 if (self_adjoint)
then
675 if (mesh%parallel_in_domains)
then
677 safe_allocate(vol_pp(1:mesh%np_part))
678 vol_pp(1:mesh%np) = mesh%vol_pp(1:mesh%np)
681 if (.not.op%const_w)
then
682 safe_allocate(
weights(1:op%stencil%size, 1:mesh%np_part))
683 safe_allocate(tmp(1:mesh%np_part))
684 do ii = 1, op%stencil%size
685 tmp(1:mesh%np) = op%w(ii, 1:mesh%np)
687 weights(ii, 1:mesh%np_part) = tmp(1:mesh%np_part)
689 safe_deallocate_p(tmp)
692 vol_pp => mesh%vol_pp
696 if (.not.op%const_w)
then
699 do jp = 1, op%stencil%size
701 if (index <= mesh%np)
then
703 do lp = 1, op%stencil%size
709 else if (index <= mesh%np + mesh%pv%np_ghost)
then
712 do lp = 1, op%stencil%size
714 op%stencil%points(1:mesh%box%dim, lp))
723 opt%w(1:op%stencil%size, 1) = op%w(1:op%stencil%size, 1)
728 if (mesh%parallel_in_domains)
then
729 safe_deallocate_p(vol_pp)
745 select case (function_opencl)
752 if (op%mesh%parallel_in_domains)
then
769 safe_deallocate_a(op%inner%imin)
770 safe_deallocate_a(op%inner%imax)
771 safe_deallocate_a(op%inner%ri)
772 safe_deallocate_a(op%outer%imin)
773 safe_deallocate_a(op%outer%imax)
774 safe_deallocate_a(op%outer%ri)
776 safe_deallocate_a(op%w)
778 safe_deallocate_a(op%ri)
779 safe_deallocate_a(op%rimap)
780 safe_deallocate_a(op%rimap_inv)
781 safe_deallocate_a(op%nn)
792 integer,
intent(in) :: is
793 integer,
intent(in) :: ip
795 res = ip + op%ri(is, op%rimap(ip))
806 if (accel_is_enabled() .and. op%const_w)
then
807 call accel_create_buffer(op%buff_weights, accel_mem_read_only, type_float, op%stencil%size)
808 call accel_create_buffer(op%buff_half_weights, accel_mem_read_only, type_float, op%stencil%size)
823 if (accel_is_enabled() .and. op%const_w)
then
824 call accel_write_buffer(op%buff_weights, op%stencil%size, op%w(:, 1))
825 call accel_write_buffer(op%buff_half_weights, op%stencil%size, -m_half*op%w(:, 1))
840 ii = op%rimap_inv(jj + 1) + maxval(op%ri(1:op%stencil%size, jj))
841 np_bc = max(np_bc, ii)
856#include "nl_operator_inc.F90"
859#include "complex.F90"
860#include "nl_operator_inc.F90"
subroutine, public accel_release_buffer(this)
subroutine, public accel_kernel_build(this, file_name, kernel_name, flags)
pure logical function, public accel_is_enabled()
integer, parameter, public accel_mem_read_only
integer pure function, public accel_max_workgroup_size()
This module implements batches of mesh functions.
Module implementing boundary conditions in Octopus.
subroutine, public dpar_vec_ghost_update(pv, v_local)
Updates ghost points of every node.
type(debug_t), save, public debug
real(real64), parameter, public m_zero
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module implements the index, used for the mesh points.
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public weights(N, M, cc, side)
Compute the weights for finite-difference calculations:
This module defines the meshes, which are used in Octopus.
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_local_index_to_coords(mesh, ip, ix)
Given a local point index, this function returns the set of integer coordinates of the point.
logical pure function, public mesh_compact_boundaries(mesh)
subroutine, public messages_obsolete_variable(namespace, name, rep)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
This module handles the communicators for the various parallelization strategies.
This module defines non-local operators.
subroutine, public dnl_operator_operate_diag(op, fo)
subroutine, public nl_operator_init(op, label)
initialize an instance of a non-local operator by setting the label
integer, parameter op_map
integer, parameter op_max
integer, parameter op_vec
subroutine, public dnl_operator_operate_batch(op, fi, fo, ghost_update, profile, points, factor, async)
subroutine, public dnl_operator_operate(op, fi, fo, ghost_update, profile, points)
subroutine, public nl_operator_update_gpu_buffers(op)
subroutine, public nl_operator_global_init(namespace)
initialize global settings for non-local operators
subroutine, public nl_operator_copy(opo, opi)
subroutine, public nl_operator_output_weights(this)
subroutine, public nl_operator_end(op)
integer, parameter, public op_inner
subroutine, public znl_operator_operate(op, fi, fo, ghost_update, profile, points)
logical pure function, public nl_operator_compact_boundaries()
subroutine, public nl_operator_global_end()
integer, parameter, public op_outer
subroutine, public nl_operator_build(space, mesh, op, np, const_w, regenerate)
logical compact_boundaries
subroutine, public znl_operator_operate_batch(op, fi, fo, ghost_update, profile, points, factor, async)
integer, parameter op_nomap
subroutine, public nl_operator_adjoint(op, opt, mesh, self_adjoint)
opt has to be initialised and built.
integer pure function, public nl_operator_np_zero_bc(op)
subroutine, public znl_operator_operate_diag(op, fo)
integer pure function, public nl_operator_get_index(op, is, ip)
subroutine, public nl_operator_allocate_gpu_buffers(op)
integer, parameter op_min
This module contains interfaces for routines in operate.c.
Some general things and nomenclature:
This module defines stencils used in Octopus.
subroutine, public stencil_end(this)
subroutine, public stencil_copy(input, output)
type(type_t), public type_float
type(type_t), public type_integer
Describes mesh distribution to nodes.
index type for non-local operators
data type for non local operators