I’m developing a Julia wrapper for KIM-API called kim_api.jl and encountering a puzzling issue where my Julia callback function isn’t being invoked by the C library during computation.
So KIM-API is supposed to register a callback function as a void *, and call it whenever needed. Here idea was to write that function in Julia and provide pointer to it using ccall from julia. So essentially the call is supposed to look like:
Julia (ccall) → KIM-API C function (julia_fptr) → (*julia_fptr)()
Now,
- The callback registration succeeds
- C callbacks work fine
- The Julia callback works when called manually
but when my module functions try to do the same, nothing happens, no errors, no faults, it just never calls the julia function.
See in the script below, specially these 4 line:
data_obj_ptr = pointer_from_objref(containers)
fptr= kim_api.@cast_as_kim_neigh_fptr(kim_api.kim_neighbors_callback)
set_callback_pointer!(args, kim_api.GetNeighborList, kim_api.c, fptr, data_obj_ptr)
compute!(model, args)
using kim_api, StaticArrays
positions = [SVector(0.0, 0.0, 0.0), SVector(1.1, 1.0, 0.0)]
cell = [5.43 0.0 0.0; 0.0 5.43 0.0; 0.0 0.0 5.43]
pbc = [true, true, true]
species = ["Si", "Si"]
is_manual = false
if length(ARGS) > 0 && ARGS[1] == "manual"
is_manual = true
end
if is_manual
units_in = kim_api.get_lammps_style_units(:metal)
model, accepted = create_model(kim_api.Numbering(0), units_in...,"SW_StillingerWeber_1985_Si__MO_405512056662_006")
args = create_compute_arguments(model)
n_cutoffs, cutoffs, will_not_request_ghost_neigh = get_neighbor_list_pointers(model)
species_support_map = get_species_map_closure(model)
containers, all_positions, all_species, contributing, atom_indices =
create_kim_neighborlists(positions, cutoffs, species;
cell=cell, pbc=pbc,
will_not_request_ghost_neigh=will_not_request_ghost_neigh)
particle_species_codes = species_support_map(all_species)
coords = reduce(hcat, all_positions) # Vector{SVector} to Matrix{Cdouble/Float64}
n = size(coords, 2)
n_ref = Ref{Cint}(n)
set_argument_pointer!(args, kim_api.particleContributing, contributing)
set_argument_pointer!(args, kim_api.coordinates, coords)
set_argument_pointer!(args, kim_api.numberOfParticles, n_ref)
set_argument_pointer!(args, kim_api.particleSpeciesCodes, particle_species_codes)
energy = Ref{Cdouble}(0.0)
forces = zeros(3, n)
set_argument_pointer!(args, kim_api.partialEnergy, energy)
set_argument_pointer!(args, kim_api.partialForces, forces)
data_obj_ptr = pointer_from_objref(containers)
fptr= kim_api.@cast_as_kim_neigh_fptr(kim_api.kim_neighbors_callback)
set_callback_pointer!(args, kim_api.GetNeighborList, kim_api.c, fptr, data_obj_ptr)
compute!(model, args)
println(energy)
else
model = kim_api.KIMModel("SW_StillingerWeber_1985_Si__MO_405512056662_006")
result = model(species, positions, cell, pbc)
println("Energy: ", result)
end
when I call it as
julia script.jl manual
Everything works fine and I get the energy, but when I run it inside my module closure, I always get energy as zero, and the function output is never printed.
What am I doing wrong? First time writing a Julia package, so please let me know if anything trivial missing. ChatGPT was of no help!