1+ /**
2+ * Calculates the Continuous Slowing Down Approximation (CSDA) range in g/cm2 for multiple particles.
3+ * This function serves as a JavaScript wrapper for the C function AT_CSDA_range_g_cm2_multi from libAT.
4+ *
5+ * The CSDA range represents the expected path length a charged particle travels until it comes to rest,
6+ * calculated by integrating the reciprocal of the stopping power with respect to energy.
7+ *
8+ * @param {Object } parameters - Input parameters object
9+ * @param {number } parameters.n - Number of particles to calculate CSDA range for
10+ * @param {Array<number> } parameters.E_initial_MeV_u - Initial energies in MeV per nucleon
11+ * @param {Array<number> } parameters.particle_no - Particle type identifiers
12+ * @param {number } parameters.material_no - Material identifier
13+ * @returns {Array<number> } CSDA ranges in g/cm2 for each particle
14+ */
115export default function AT_CSDA_range_g_cm2_multi ( parameters ) {
2- let at_csda_range_g_cm2_multi = Module . cwrap ( 'AT_CSDA_range_g_cm2_multi' , 'null' , [ 'number' , 'array' , 'array' , 'array' , 'number' , 'number' ] ) ;
316
4- /*********************STANDARD PARAMETER*************************/
5- if ( typeof parameters . n === "undefined" ) {
6- alert ( "MESSAGE TO DEVELOPER: NO PARAMETER n IN OBJECT PASSED TO THIS FUNCTIONS" ) ;
7- return "error" ;
8- }
9- let n = parameters . n ;
17+ // Validate required parameters
18+ if ( ! parameters ) {
19+ throw new Error ( "Parameters object is required." ) ;
20+ }
21+ const requiredParams = [ 'n' , 'E_initial_MeV_u' , 'particle_no' , 'material_no' ] ;
22+ for ( const param of requiredParams ) {
23+ if ( typeof parameters [ param ] === "undefined" ) {
24+ throw new Error ( `Missing parameter: ${ param } ` ) ;
25+ }
26+ }
1027
11- /*********************INPUT ARRAY********************************/
12- if ( typeof parameters . E_initial_MeV_u === "undefined" ) {
13- alert ( "MESSAGE TO DEVELOPER: NO PARAMETER E_initial_MeV_u IN OBJECT PASSED TO THIS FUNCTIONS" ) ;
14- return "error" ;
15- }
16- let E_initial_MeV_u = parameters . E_initial_MeV_u ;
17- let E_initial_MeV_uData = new Float64Array ( E_initial_MeV_u ) ;
18- let E_initial_MeV_uDataBytesNumber = E_initial_MeV_uData . length * E_initial_MeV_uData . BYTES_PER_ELEMENT ;
19- let E_initial_MeV_uDataPointer = Module . _malloc ( E_initial_MeV_uDataBytesNumber ) ;
20- let E_initial_MeV_uHeap = new Uint8Array ( Module . HEAPF64 . buffer , E_initial_MeV_uDataPointer , E_initial_MeV_uDataBytesNumber ) ;
21- E_initial_MeV_uHeap . set ( new Uint8Array ( E_initial_MeV_uData . buffer ) ) ;
28+ // Extract parameters from the input object
29+ const n = parameters . n ;
30+ const E_initial_MeV_u = parameters . E_initial_MeV_u ;
31+ if ( ! Array . isArray ( E_initial_MeV_u ) ) {
32+ throw new Error ( "Parameter 'E_initial_MeV_u' must be an array." ) ;
33+ }
34+ const particle_no = parameters . particle_no ;
35+ const material_no = parameters . material_no ;
2236
23- /*********************INPUT ARRAY********************************/
24- if ( typeof parameters . particle_no === "undefined" ) {
25- alert ( "MESSAGE TO DEVELOPER: NO PARAMETER particle_no IN OBJECT PASSED TO THIS FUNCTIONS" ) ;
26- return "error" ;
27- }
28- let particle_no = parameters . particle_no ;
29- let particle_noData = new Int32Array ( particle_no ) ;
30- let particle_noDataBytesNumber = particle_noData . length * particle_noData . BYTES_PER_ELEMENT ;
31- let particle_noDataPointer = Module . _malloc ( particle_noDataBytesNumber ) ;
32- let particle_noHeap = new Uint8Array ( Module . HEAP32 . buffer , particle_noDataPointer , particle_noDataBytesNumber ) ;
33- particle_noHeap . set ( new Uint8Array ( particle_noData . buffer ) ) ;
37+ // Create a JavaScript wrapper for the C function using Emscripten's cwrap
38+ // null indicates no return type (the function returns values through pointers)
39+ const at_csda_range_g_cm2_multi = Module . cwrap ( 'AT_CSDA_range_g_cm2_multi' , null , [
40+ 'number' , // n
41+ 'number' , // E_initial_MeV_u pointer
42+ 'number' , // E_final_MeV_u pointer
43+ 'number' , // particle_no pointer
44+ 'number' , // material_no
45+ 'number' // CSDA_range_g_cm2 pointer
46+ ] ) ;
47+
48+ // Allocate memory for the initial energy array and copy data to Emscripten's heap
49+ const E_initial_MeV_uData = new Float64Array ( E_initial_MeV_u ) ;
50+ const E_initial_MeV_uDataBytesNumber = E_initial_MeV_uData . length * E_initial_MeV_uData . BYTES_PER_ELEMENT ;
51+ const E_initial_MeV_uDataPointer = Module . _malloc ( E_initial_MeV_uDataBytesNumber ) ;
52+ const E_initial_MeV_uHeap = new Uint8Array ( Module . HEAPF64 . buffer , E_initial_MeV_uDataPointer , E_initial_MeV_uDataBytesNumber ) ;
53+ E_initial_MeV_uHeap . set ( new Uint8Array ( E_initial_MeV_uData . buffer ) ) ;
3454
35- /*********************STANDARD PARAMETER*************************/
36- if ( typeof parameters . material_no === "undefined" ) {
37- alert ( "MESSAGE TO DEVELOPER: NO PARAMETER material_no IN OBJECT PASSED TO THIS FUNCTIONS" ) ;
38- return "error" ;
39- }
40- let material_no = parameters . material_no ;
55+ // Create final energy array (all zeros for complete stopping)
56+ // The final energy is set to 0 MeV/u to calculate the full CSDA range
57+ const E_final_MeV_uData = new Float64Array ( n ) ;
58+ for ( let i = 0 ; i < E_final_MeV_uData . length ; i ++ ) {
59+ E_final_MeV_uData [ i ] = 0.0 ;
60+ }
61+ const E_final_MeV_uDataBytesNumber = E_final_MeV_uData . length * E_final_MeV_uData . BYTES_PER_ELEMENT ;
62+ const E_final_MeV_uDataPointer = Module . _malloc ( E_final_MeV_uDataBytesNumber ) ;
63+ const E_final_MeV_uHeap = new Uint8Array ( Module . HEAPF64 . buffer , E_final_MeV_uDataPointer , E_final_MeV_uDataBytesNumber ) ;
64+ E_final_MeV_uHeap . set ( new Uint8Array ( E_final_MeV_uData . buffer ) ) ;
4165
42- /*********************OUTPUT ARRAY*******************************/
43- let CSDA_range_g_cm2ReturnData = new Float64Array ( new Array ( n ) ) ;
44- let CSDA_range_g_cm2ReturnDataBytesNumber = CSDA_range_g_cm2ReturnData . length * CSDA_range_g_cm2ReturnData . BYTES_PER_ELEMENT ;
45- let CSDA_range_g_cm2ReturnDataPointer = Module . _malloc ( CSDA_range_g_cm2ReturnDataBytesNumber ) ;
46- let CSDA_range_g_cm2ReturnHeap = new Uint8Array ( Module . HEAPF64 . buffer , CSDA_range_g_cm2ReturnDataPointer , CSDA_range_g_cm2ReturnDataBytesNumber ) ;
66+ // Create array for particle_no, using Int32Array for particle identifiers
67+ const particle_noData = new Int32Array ( particle_no ) ;
68+ const particle_noDataBytesNumber = particle_noData . length * particle_noData . BYTES_PER_ELEMENT ;
69+ const particle_noDataPointer = Module . _malloc ( particle_noDataBytesNumber ) ;
70+ const particle_noHeap = new Uint8Array ( Module . HEAP32 . buffer , particle_noDataPointer , particle_noDataBytesNumber ) ;
71+ particle_noHeap . set ( new Uint8Array ( particle_noData . buffer ) ) ;
4772
48- /*********************CALL FUNCTION******************************/
73+ // Create output array to store the calculated CSDA ranges
74+ const CSDA_range_g_cm2ReturnData = new Float64Array ( n ) ;
75+ const CSDA_range_g_cm2ReturnDataBytesNumber = CSDA_range_g_cm2ReturnData . length * CSDA_range_g_cm2ReturnData . BYTES_PER_ELEMENT ;
76+ const CSDA_range_g_cm2ReturnDataPointer = Module . _malloc ( CSDA_range_g_cm2ReturnDataBytesNumber ) ;
4977
50- // calculate CSDA range for completely slowing down ions
51- let E_final_MeV_uData = new Float64Array ( n ) ;
52- for ( let i = 0 ; i < E_final_MeV_uData . length ; i ++ ) {
53- E_final_MeV_uData [ i ] = 0.0 ;
54- }
55-
56- let result = at_csda_range_g_cm2_multi ( n , E_initial_MeV_uHeap , E_final_MeV_uData , particle_noHeap , material_no , CSDA_range_g_cm2ReturnHeap . byteOffset ) ;
57- let resultFromArray = new Float64Array ( CSDA_range_g_cm2ReturnHeap . buffer , CSDA_range_g_cm2ReturnHeap . byteOffset , CSDA_range_g_cm2ReturnData . length ) ;
58-
59- return [ ] . slice . call ( resultFromArray ) ;
78+ try {
79+ // Call the C function with pointers to the allocated memory
80+ at_csda_range_g_cm2_multi (
81+ n ,
82+ E_initial_MeV_uDataPointer ,
83+ E_final_MeV_uDataPointer ,
84+ particle_noDataPointer ,
85+ material_no ,
86+ CSDA_range_g_cm2ReturnDataPointer
87+ ) ;
88+
89+ // Create a view of the results in the Emscripten heap
90+ const resultFromArray = new Float64Array ( Module . HEAPF64 . buffer , CSDA_range_g_cm2ReturnDataPointer , n ) ;
91+
92+ // Return a JavaScript array with the results
93+ return Array . from ( resultFromArray ) ;
94+
95+ } finally {
96+ // // Free the allocated memory to prevent memory leaks
97+ // Module._free(E_initial_MeV_uDataPointer);
98+ // Module._free(E_final_MeV_uDataPointer);
99+ // Module._free(particle_noDataPointer);
100+ // Module._free(CSDA_range_g_cm2ReturnDataPointer);
101+ }
60102}
0 commit comments