@@ -81,6 +81,7 @@ pub fn pybca(py: Python, m: &PyModule) -> PyResult<()> {
8181 m. add_function ( wrap_pyfunction ! ( simple_bca_py, m) ?) ?;
8282 m. add_function ( wrap_pyfunction ! ( simple_bca_list_py, m) ?) ?;
8383 m. add_function ( wrap_pyfunction ! ( compound_bca_list_py, m) ?) ?;
84+ m. add_function ( wrap_pyfunction ! ( compound_bca_list_1D_py, m) ?) ?;
8485 Ok ( ( ) )
8586}
8687
@@ -1173,6 +1174,212 @@ pub fn compound_bca_list_py(energies: Vec<f64>, ux: Vec<f64>, uy: Vec<f64>, uz:
11731174 ( total_output, incident)
11741175}
11751176
1177+ #[ cfg( feature = "python" ) ]
1178+ ///compound_bca_list_1D_py(ux, uy, uz, energy, Z1, m1, Ec1, Es1, Z2, m2, Ec2, Es2, Eb2 n2, dx)
1179+ /// runs a BCA simulation for a list of particles and outputs a list of sputtered, reflected, and implanted particles.
1180+ /// Args:
1181+ /// energies (list(f64)): initial ion energies in eV.
1182+ /// ux (list(f64)): initial ion directions x. ux != 0.0 to avoid gimbal lock
1183+ /// uy (list(f64)): initial ion directions y.
1184+ /// uz (list(f64)): initial ion directions z.
1185+ /// Z1 (list(f64)): initial ion atomic numbers.
1186+ /// m1 (list(f64)): initial ion masses in amu.
1187+ /// Ec1 (list(f64)): ion cutoff energies in eV. If ion energy < Ec1, it stops in the material.
1188+ /// Es1 (list(f64)): ion surface binding energies. Assumed planar.
1189+ /// Z2 (list(f64)): target material species atomic numbers.
1190+ /// m2 (list(f64)): target material species masses in amu.
1191+ /// Ec2 (list(f64)): target material species cutoff energies in eV. If recoil energy < Ec2, it stops in the material.
1192+ /// Es2 (list(f64)): target species surface binding energies. Assumed planar.
1193+ /// Eb2 (list(f64)): target material species bulk binding energies in eV.
1194+ /// n2 (list(list(f64))): target material species atomic number densities in inverse cubic Angstroms.
1195+ /// dx (list(f64)): target material layer thicknesses starting at surface.
1196+ /// Returns:
1197+ /// output (NX9 list of f64): each row in the list represents an output particle (implanted,
1198+ /// sputtered, or reflected). Each row consists of:
1199+ /// [Z, m (amu), E (eV), x, y, z, (angstrom), ux, uy, uz]
1200+ /// incident (list(bool)): whether each row of output was an incident ion or originated in the target
1201+ /// stopped (list(bool)): whether each row of output is associated with a particle that stopped in the target
1202+ #[ pyfunction]
1203+ pub fn compound_bca_list_1D_py ( ux : Vec < f64 > , uy : Vec < f64 > , uz : Vec < f64 > , energies : Vec < f64 > , Z1 : Vec < f64 > , m1 : Vec < f64 > , Ec1 : Vec < f64 > , Es1 : Vec < f64 > , Z2 : Vec < f64 > , m2 : Vec < f64 > , Ec2 : Vec < f64 > , Es2 : Vec < f64 > , Eb2 : Vec < f64 > , n2 : Vec < Vec < f64 > > , dx : Vec < f64 > ) -> ( Vec < [ f64 ; 9 ] > , Vec < bool > , Vec < bool > ) {
1204+ let mut total_output = vec ! [ ] ;
1205+ let mut incident = vec ! [ ] ;
1206+ let mut stopped = vec ! [ ] ;
1207+
1208+ let num_layers_target = n2. len ( ) ;
1209+ let num_species = Z2 . len ( ) ;
1210+ let num_incident_ions = energies. len ( ) ;
1211+
1212+ assert_eq ! ( ux. len( ) , num_incident_ions, "Input error: list of x-directions is not the same length as list of incident energies." ) ;
1213+ assert_eq ! ( uy. len( ) , num_incident_ions, "Input error: list of y-directions is not the same length as list of incident energies." ) ;
1214+ assert_eq ! ( uz. len( ) , num_incident_ions, "Input error: list of z-directions is not the same length as list of incident energies." ) ;
1215+ assert_eq ! ( Z1 . len( ) , num_incident_ions, "Input error: list of incident atomic numbers is not the same length as list of incident energies." ) ;
1216+ assert_eq ! ( m1. len( ) , num_incident_ions, "Input error: list of incident atomic masses is not the same length as list of incident energies." ) ;
1217+ assert_eq ! ( Es1 . len( ) , num_incident_ions, "Input error: list of incident surface binding energies is not the same length as list of incident energies." ) ;
1218+ assert_eq ! ( Ec1 . len( ) , num_incident_ions, "Input error: list of incident cutoff energies is not the same length as list of incident energies." ) ;
1219+
1220+ assert_eq ! ( m2. len( ) , num_species, "Input error: list of target atomic masses is not the same length as atomic numbers." ) ;
1221+ assert_eq ! ( Ec2 . len( ) , num_species, "Input error: list of target cutoff energies is not the same length as atomic numbers." ) ;
1222+ assert_eq ! ( Es2 . len( ) , num_species, "Input error: list of target surface binding energies is not the same length as atomic numbers." ) ;
1223+ assert_eq ! ( Eb2 . len( ) , num_species, "Input error: list of target bulk binding energies is not the same length as atomic numbers." ) ;
1224+ assert_eq ! ( n2[ 0 ] . len( ) , num_species, "Input error: first layer list of target number densities is not the same length as atomic numbers." ) ;
1225+
1226+ assert_eq ! ( n2[ 0 ] . len( ) , num_species, "Input error: first layer species list of target number densities is not the same length as atomic numbers." ) ;
1227+ assert_eq ! ( dx. len( ) , num_layers_target, "Input error: number of layer thicknesses not the same as number of layers in atomic densities list." ) ;
1228+
1229+ #[ cfg( feature = "distributions" ) ]
1230+ let options = Options {
1231+ name : "test" . to_string ( ) ,
1232+ track_trajectories : false ,
1233+ track_recoils : true ,
1234+ track_recoil_trajectories : false ,
1235+ write_buffer_size : 8000 ,
1236+ weak_collision_order : 3 ,
1237+ suppress_deep_recoils : true ,
1238+ high_energy_free_flight_paths : true ,
1239+ electronic_stopping_mode : ElectronicStoppingMode :: LOW_ENERGY_NONLOCAL ,
1240+ mean_free_path_model : MeanFreePathModel :: LIQUID ,
1241+ interaction_potential : vec ! [ vec![ InteractionPotential :: KR_C ] ] ,
1242+ scattering_integral : vec ! [ vec![ ScatteringIntegral :: MENDENHALL_WELLER ] ] ,
1243+ num_threads : 1 ,
1244+ num_chunks : 1 ,
1245+ use_hdf5 : false ,
1246+ root_finder : vec ! [ vec![ Rootfinder :: DEFAULTNEWTON ] ] ,
1247+ track_displacements : false ,
1248+ track_energy_losses : false ,
1249+ energy_min : 0.0 ,
1250+ energy_max : 10.0 ,
1251+ energy_num : 11 ,
1252+ angle_min : 0.0 ,
1253+ angle_max : 90.0 ,
1254+ angle_num : 11 ,
1255+ x_min : 0.0 ,
1256+ y_min : -10.0 ,
1257+ z_min : -10.0 ,
1258+ x_max : 10.0 ,
1259+ y_max : 10.0 ,
1260+ z_max : 10.0 ,
1261+ x_num : 11 ,
1262+ y_num : 11 ,
1263+ z_num : 11 ,
1264+ } ;
1265+
1266+ #[ cfg( not( feature = "distributions" ) ) ]
1267+ let options = Options {
1268+ name : "test" . to_string ( ) ,
1269+ track_trajectories : false ,
1270+ track_recoils : true ,
1271+ track_recoil_trajectories : false ,
1272+ write_buffer_size : 8000 ,
1273+ weak_collision_order : 3 ,
1274+ suppress_deep_recoils : true ,
1275+ high_energy_free_flight_paths : false ,
1276+ electronic_stopping_mode : ElectronicStoppingMode :: LOW_ENERGY_NONLOCAL ,
1277+ mean_free_path_model : MeanFreePathModel :: LIQUID ,
1278+ interaction_potential : vec ! [ vec![ InteractionPotential :: KR_C ] ] ,
1279+ scattering_integral : vec ! [ vec![ ScatteringIntegral :: MENDENHALL_WELLER ] ] ,
1280+ num_threads : 1 ,
1281+ num_chunks : 1 ,
1282+ use_hdf5 : false ,
1283+ root_finder : vec ! [ vec![ Rootfinder :: DEFAULTNEWTON ] ] ,
1284+ track_displacements : false ,
1285+ track_energy_losses : false ,
1286+ } ;
1287+
1288+ let y = 0.0 ;
1289+ let z = 0.0 ;
1290+
1291+ let material_parameters = material:: MaterialParameters {
1292+ energy_unit : "EV" . to_string ( ) ,
1293+ mass_unit : "AMU" . to_string ( ) ,
1294+ Eb : Eb2 ,
1295+ Es : Es2 ,
1296+ Ec : Ec2 ,
1297+ Z : Z2 ,
1298+ m : m2,
1299+ interaction_index : vec ! [ 0 ; num_species] ,
1300+ surface_binding_model : SurfaceBindingModel :: INDIVIDUAL ,
1301+ bulk_binding_model : BulkBindingModel :: INDIVIDUAL ,
1302+ } ;
1303+
1304+ let geometry_input = geometry:: Mesh1DInput {
1305+ length_unit : "ANGSTROM" . to_string ( ) ,
1306+ densities : n2,
1307+ layer_thicknesses : dx,
1308+ electronic_stopping_correction_factors : vec ! [ 1.0 ; num_layers_target]
1309+ } ;
1310+
1311+ let m = material:: Material :: < Mesh1D > :: new ( & material_parameters, & geometry_input) ;
1312+
1313+ let x = -m. geometry . top_energy_barrier_thickness /2. ;
1314+
1315+ let mut index: usize = 0 ;
1316+ for ( ( ( ( ( ( ( E1_ , ux_) , uy_) , uz_) , Z1_ ) , Ec1_ ) , Es1_ ) , m1_) in energies. iter ( ) . zip ( ux) . zip ( uy) . zip ( uz) . zip ( Z1 ) . zip ( Ec1 ) . zip ( Es1 ) . zip ( m1) {
1317+
1318+ let mut dir = Vector :: new ( ux_, uy_, uz_) ;
1319+ dir. normalize ( ) ;
1320+
1321+ let mut energy_out;
1322+ let p = particle:: Particle {
1323+ m : m1_* AMU ,
1324+ Z : Z1_ ,
1325+ E : E1_ * EV ,
1326+ Ec : Ec1_ * EV ,
1327+ Es : Es1_ * EV ,
1328+ pos : Vector :: new ( x, y, z) ,
1329+ dir : dir,
1330+ pos_origin : Vector :: new ( x, y, z) ,
1331+ pos_old : Vector :: new ( x, y, z) ,
1332+ dir_old : dir,
1333+ energy_origin : E1_ * EV ,
1334+ asymptotic_deflection : 0.0 ,
1335+ stopped : false ,
1336+ left : false ,
1337+ incident : true ,
1338+ first_step : true ,
1339+ trajectory : vec ! [ ] ,
1340+ energies : vec ! [ ] ,
1341+ track_trajectories : false ,
1342+ number_collision_events : 0 ,
1343+ backreflected : false ,
1344+ interaction_index : 0 ,
1345+ weight : 0.0 ,
1346+ tag : 0 ,
1347+ tracked_vector : Vector :: new ( 0. , 0. , 0. ) ,
1348+ } ;
1349+
1350+ let output = bca:: single_ion_bca ( p, & m, & options) ;
1351+
1352+ for particle in output {
1353+ if ( particle. left ) | ( particle. incident ) {
1354+
1355+ incident. push ( particle. incident ) ;
1356+ stopped. push ( particle. stopped ) ;
1357+
1358+ if particle. stopped {
1359+ energy_out = 0.
1360+ } else {
1361+ energy_out = particle. E /EV
1362+ }
1363+ total_output. push (
1364+ [
1365+ particle. Z ,
1366+ particle. m /AMU ,
1367+ energy_out,
1368+ particle. pos . x /ANGSTROM ,
1369+ particle. pos . y /ANGSTROM ,
1370+ particle. pos . z /ANGSTROM ,
1371+ particle. dir . x ,
1372+ particle. dir . y ,
1373+ particle. dir . z ,
1374+ ]
1375+ ) ;
1376+ }
1377+ }
1378+ index += 1 ;
1379+ }
1380+ ( total_output, incident, stopped)
1381+ }
1382+
11761383#[ cfg( feature = "python" ) ]
11771384/// simple_bca_py( x, y, z, ux, uy, uz, energy, Z1, m1, Ec1, Es1, Z2, m2, Ec2, Es2, n2, Eb2)
11781385/// --
0 commit comments