Skip to content

Bindings: Fortran

Jon Drobny edited this page May 24, 2023 · 2 revisions

Through a combination of Rust-C/C++ interop and Fortran-C/C++ interop, the RustBCA library can be called from Fortran.

This requires functions to be handled a little differently, so specific functions for Fortran-Rust coupling have been written, and a Fortran wrapper rustbca.f90 is included with appropriate interface statements so that RustBCA library functions can be called relatively simply from Fortran codes.

Example

test_rustbca.f90 is located in the examples directory. It can be built and tested with the following series of commands:

#Build the library
cargo build --release --lib
#copy test source file to main directory.
cp examples/test_rustbca.f90 .
#Build the RustBCA Fortran wrappers
gfortran -c rustbca.f90 target/release/liblibRustBCA.so
#Build test_rustbca
gfortran test_rustbca.f90 target/release/liblibRustBCA.so
./a.out

The code should output:

 Elapsed time in seconds per ion per eV:    8.08222978E-07
 Elapsed time in ions per eV per s:    8.22675304E-07

With timing dependent on your specific machine.

Ion Reflection routine

The reflect_single_ion routine takes an incident ion and runs that ion through a single BCA trajectory in a flat, homogeneous, compound target with no recoils (which means no sputtered atoms). The energy and direction of the incident ion are passed by reference and modified in place.

Arguments

  • num_species_target (integer(c_int)): number of species in target
  • ux (real(c_double)): x-direction - modified in place after run is complete to new direction
  • uy (real(c_double)): y-direction - modified in place after run is complete to new direction
  • uz (real(c_double)): z-direction - modified in place after run is complete to new direction
  • E1 (real(c_double)): Energy (eV) - modified in place after run is complete to new energy; if E = 0, ion was implanted in target, not reflected
  • Z1 (real(c_double)): atomic number of incident ion
  • m1 (real(c_double)): atomic mass of incident ion (amu)
  • Ec1 (real(c_double)): cutoff energy of incident ion (eV)
  • Es1 (real(c_double)): surface binding energy of incident ion (eV)
  • Z2 (real(c_double), dimension(:)): atomic numbers of target species
  • m2 (real(c_double), dimension(:)): atomic masses of target species (amu)
  • Ec2 (real(c_double), dimension(:)): cutoff energies of target species (eV)
  • Es2 (real(c_double), dimension(:)): surface binding energies of target species (eV)
  • Eb2 (real(c_double), dimension(:)): bulk binding energies of target species (eV)
  • n2 (real(c_double), dimension(:)): number densities of target species (1/A^3)

Full BCA in Fortran

The compound_bca_list_fortran function gives nearly complete access to a homogeneous, flat target BCA simulation with two lines of code. First, the function is called. Note that, in order to overcome a lack of easily sharing structs between Fortran and C, and additionally the inability for functions to output multiple objects in both Fortran and Rust, this function does mutate a single argument as part of the output - the number of emitted particles after the simulation. Note also that the function returns a C pointer - the second line of code is used to convert the C pointer to the output data to a Fortran pointer (which contains size and shape information, so that the resulting Fortran pointer can be accessed like a normal Fortran array).

Arguments

  • N_ions (integer(c_int)): number of incident ions
  • track_recoils (logical(c_bool)): whether to generate recoils or not - turn off to disable sputtering
  • ux, uy, uz (real(c_double), dimension(:)): ion direction unit vector
  • E1(real(c_double), dimension(:)): ion energy (eV)
  • Z1 (real(c_double), dimension(:)): ion atomic numbers
  • m1 (real(c_double), dimension(:)): ion masses (amu)
  • Ec1 (real(c_double), dimension(:)): ion cutoff energies (eV)
  • Es1 (real(c_double), dimension(:)): ion surface binding energies (eV)
  • num_species_target (integer(c_int)): number of target species
  • Z2 (real(c_double), dimension(:)): target atomic numbers
  • m2 (real(c_double), dimension(:)): target masses (amu)
  • Ec2 (real(c_double), dimension(:)): target cutoff energies (eV)
  • Es2 (real(c_double), dimension(:)): target surface binding energies (eV)
  • Eb2 (real(c_double), dimension(:)): target bulk binding energies (eV)
  • n2 (real(c_double), dimension(:)): target number densities (1/Angstrom^3)
  • num_emitted_particles (integer(c_int)): NOTE: OUTPUT number of emitted particles

Returns

  • bca_output (real(c_double), dimension(:,6)): Z, m (amu), E (eV), ux, uy, uz

Usage

!rustbca.f90 includes interface statements that allow Rust/Fortran interop via C/C++ FFI
use rustbca
use, intrinsic :: iso_binding_c

...

bca_output_c = compound_bca_list_fortran(N_ions, track_recoils, ux, uy, uz, E, &
    Z1, m1, Ec1, Es1, &
    num_species_target, Z2, m2, Ec2, Es2, Eb2, n2, &
    num_emitted_particles)

!Convert the C pointer (which has been forgotten by the Rust library) to a Fortran pointer
call c_f_pointer(bca_output_c, bca_output_f, [num_emitted_particles, 6])