integer(c_int) function beach_kernel_build( &
handle, nsrc, src_pos_ptr, theta, leaf_max, order, softening, use_periodic2, periodic_axes_ptr, &
periodic_len_ptr, image_layers, far_correction, ewald_alpha, ewald_layers, box_min_ptr, box_max_ptr &
) bind(C, name='beach_kernel_build') result(status)
type(c_ptr), value :: handle
integer(c_int), value :: nsrc
type(c_ptr), value :: src_pos_ptr
real(c_double), value :: theta
integer(c_int), value :: leaf_max
integer(c_int), value :: order
real(c_double), value :: softening
integer(c_int), value :: use_periodic2
type(c_ptr), value :: periodic_axes_ptr
type(c_ptr), value :: periodic_len_ptr
integer(c_int), value :: image_layers
integer(c_int), value :: far_correction
real(c_double), value :: ewald_alpha
integer(c_int), value :: ewald_layers
type(c_ptr), value :: box_min_ptr
type(c_ptr), value :: box_max_ptr
type(field_kernel_handle), pointer :: kernel
real(c_double), pointer :: src_pos(:, :)
integer(c_int), pointer :: periodic_axes(:)
real(c_double), pointer :: periodic_len(:)
real(c_double), pointer :: box_min(:)
real(c_double), pointer :: box_max(:)
type(fmm_options_type) :: options
status = get_kernel(handle, kernel)
if (status /= beach_kernel_ok) return
if (nsrc <= 0_c_int .or. .not. c_associated(src_pos_ptr)) then
status = beach_kernel_invalid_argument
return
end if
if (theta <= 0.0_c_double .or. leaf_max <= 0_c_int .or. order < 0_c_int .or. softening < 0.0_c_double) then
status = beach_kernel_invalid_argument
return
end if
call c_f_pointer(src_pos_ptr, src_pos, [3, int(nsrc)])
options%theta = real(theta, dp)
options%leaf_max = int(leaf_max, i32)
options%order = int(order, i32)
options%softening = real(softening, dp)
if (use_periodic2 /= 0_c_int) then
if (.not. c_associated(periodic_axes_ptr) .or. .not. c_associated(periodic_len_ptr) .or. &
.not. c_associated(box_min_ptr) .or. .not. c_associated(box_max_ptr)) then
status = beach_kernel_invalid_argument
return
end if
if (image_layers < 0_c_int .or. ewald_layers < 0_c_int .or. ewald_alpha < 0.0_c_double) then
status = beach_kernel_invalid_argument
return
end if
call c_f_pointer(periodic_axes_ptr, periodic_axes, [2])
call c_f_pointer(periodic_len_ptr, periodic_len, [2])
call c_f_pointer(box_min_ptr, box_min, [3])
call c_f_pointer(box_max_ptr, box_max, [3])
if (any(periodic_axes < 1_c_int) .or. any(periodic_axes > 3_c_int) .or. &
periodic_axes(1) == periodic_axes(2) .or. any(periodic_len <= 0.0_c_double) .or. &
any(box_max <= box_min)) then
status = beach_kernel_invalid_argument
return
end if
options%use_periodic2 = .true.
options%periodic_axes = int(periodic_axes, i32)
options%periodic_len = real(periodic_len, dp)
options%periodic_image_layers = int(image_layers, i32)
options%periodic_ewald_alpha = real(ewald_alpha, dp)
options%periodic_ewald_layers = int(ewald_layers, i32)
options%target_box_min = real(box_min, dp)
options%target_box_max = real(box_max, dp)
select case (far_correction)
case (0_c_int)
options%periodic_far_correction = 'auto'
case (1_c_int)
options%periodic_far_correction = 'none'
case (2_c_int)
options%periodic_far_correction = 'm2l_root_oracle'
case default
status = beach_kernel_invalid_argument
return
end select
end if
if (kernel%charged) call destroy_state(kernel%state)
if (kernel%built) call destroy_plan(kernel%plan)
call build_plan(kernel%plan, real(src_pos, dp), options)
kernel%built = .true.
kernel%charged = .false.
status = beach_kernel_ok
end function beach_kernel_build