rusty_green_kernel/
c_api.rs

1//! This module defines C API function to access all assembly and evaluation routines.
2
3use crate::*;
4use ndarray;
5use ndarray_linalg::{c32, c64};
6
7/// Assemble the Laplace kernel (double precision version).
8///
9///
10/// # Arguments
11///
12/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
13/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
14/// * `result_ptr` - Pointer to an existing `(ntargets, nsources)` array that stores the result.
15/// * `nsources`   - Number of sources.
16/// * `ntargets`   - Number of targets.
17/// * `num_threads`   - Number of threads to use
18#[no_mangle]
19pub extern "C" fn assemble_laplace_kernel_f64(
20    source_ptr: *const f64,
21    target_ptr: *const f64,
22    result_ptr: *mut f64,
23    nsources: usize,
24    ntargets: usize,
25    num_threads: usize,
26) {
27    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
28    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
29    let result =
30        unsafe { ndarray::ArrayViewMut2::from_shape_ptr((ntargets, nsources), result_ptr) };
31
32    f64::assemble_kernel_in_place(sources, targets, result, KernelType::Laplace, num_threads);
33}
34
35/// Assemble the Laplace kernel (single precision version).
36///
37///
38/// # Arguments
39///
40/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
41/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
42/// * `result_ptr` - Pointer to an existing `(ntargets, nsources)` array that stores the result.
43/// * `nsources`   - Number of sources.
44/// * `ntargets`   - Number of targets.
45/// * `num_threads`   - Number of threads to use
46#[no_mangle]
47pub extern "C" fn assemble_laplace_kernel_f32(
48    source_ptr: *const f32,
49    target_ptr: *const f32,
50    result_ptr: *mut f32,
51    nsources: usize,
52    ntargets: usize,
53    num_threads: usize,
54) {
55    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
56    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
57    let result =
58        unsafe { ndarray::ArrayViewMut2::from_shape_ptr((ntargets, nsources), result_ptr) };
59
60    f32::assemble_kernel_in_place(sources, targets, result, KernelType::Laplace, num_threads);
61}
62
63/// Evaluate the Laplace potential sum (double precision version).
64///
65///
66/// # Arguments
67///
68/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
69/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
70/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
71/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 1)` array (if `return_gradients is false)
72///                  or to an `(ncharge_vecs, ntargets, 4) array (if `return_gradients is true) that stores the result.
73/// * `nsources`   - Number of sources.
74/// * `ntargets`   - Number of targets.
75/// * `ncharge_vecs` - Number of charge vectors.
76/// * `return_gradients` - If true return also the gradients.
77/// * `num_threads`   - Number of threads to use
78#[no_mangle]
79pub extern "C" fn evaluate_laplace_kernel_f64(
80    source_ptr: *const f64,
81    target_ptr: *const f64,
82    charge_ptr: *const f64,
83    result_ptr: *mut f64,
84    nsources: usize,
85    ntargets: usize,
86    ncharge_vecs: usize,
87    return_gradients: bool,
88    num_threads: usize,
89) {
90    let kernel_type = KernelType::Laplace;
91
92    let eval_mode = match return_gradients {
93        true => EvalMode::ValueGrad,
94        false => EvalMode::Value,
95    };
96
97    let ncols: usize = match eval_mode {
98        EvalMode::Value => 1,
99        EvalMode::ValueGrad => 4,
100    };
101
102    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
103    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
104    let charges =
105        unsafe { ndarray::ArrayView2::from_shape_ptr((ncharge_vecs, nsources), charge_ptr) };
106    let result = unsafe {
107        ndarray::ArrayViewMut3::from_shape_ptr((ncharge_vecs, ntargets, ncols), result_ptr)
108    };
109
110    f64::evaluate_kernel_in_place(
111        sources,
112        targets,
113        charges,
114        result,
115        kernel_type,
116        eval_mode,
117        num_threads,
118    );
119}
120
121/// Evaluate the Laplace potential sum (single precision version).
122///
123///
124/// # Arguments
125///
126/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
127/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
128/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
129/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 1)` array (if `return_gradients is false)
130///                  or to an `(ncharge_vecs, ntargets, 4) array (if `return_gradients is true) that stores the result.
131/// * `nsources`   - Number of sources.
132/// * `ntargets`   - Number of targets.
133/// * `ncharge_vecs` - Number of charge vectors.
134/// * `return_gradients` - If true return also the gradients.
135/// * `num_threads`   - Number of threads to use
136#[no_mangle]
137pub extern "C" fn evaluate_laplace_kernel_f32(
138    source_ptr: *const f32,
139    target_ptr: *const f32,
140    charge_ptr: *const f32,
141    result_ptr: *mut f32,
142    nsources: usize,
143    ntargets: usize,
144    ncharge_vecs: usize,
145    return_gradients: bool,
146    num_threads: usize,
147) {
148    let kernel_type = KernelType::Laplace;
149
150    let eval_mode = match return_gradients {
151        true => EvalMode::ValueGrad,
152        false => EvalMode::Value,
153    };
154
155    let ncols: usize = match eval_mode {
156        EvalMode::Value => 1,
157        EvalMode::ValueGrad => 4,
158    };
159
160    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
161    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
162    let charges =
163        unsafe { ndarray::ArrayView2::from_shape_ptr((ncharge_vecs, nsources), charge_ptr) };
164    let result = unsafe {
165        ndarray::ArrayViewMut3::from_shape_ptr((ncharge_vecs, ntargets, ncols), result_ptr)
166    };
167
168    f32::evaluate_kernel_in_place(
169        sources,
170        targets,
171        charges,
172        result,
173        kernel_type,
174        eval_mode,
175        num_threads,
176    );
177}
178
179/// Assemble the Helmholtz kernel (double precision version).
180///
181///
182/// # Arguments
183///
184/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
185/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
186/// * `result_ptr` - Pointer to an existing `(ntargets,  2 * nsources)` array that stores the result
187///                  using a complex number memory layout.
188/// * `wavenumber_real` - Real part of the wavenumber parameter.
189/// * `wavenumber_imag` - Imaginary part of the wavenumber parameter.
190/// * `nsources`   - Number of sources.
191/// * `ntargets`   - Number of targets.
192/// * `num_threads`   - Number of threads to use
193#[no_mangle]
194pub extern "C" fn assemble_helmholtz_kernel_f64(
195    source_ptr: *const f64,
196    target_ptr: *const f64,
197    result_ptr: *mut f64,
198    wavenumber_real: f64,
199    wavenumber_imag: f64,
200    nsources: usize,
201    ntargets: usize,
202    num_threads: usize,
203) {
204
205    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
206    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
207    let result = unsafe {
208        ndarray::ArrayViewMut2::from_shape_ptr(
209            (ntargets, nsources),
210            result_ptr as *mut c64,
211        )
212    };
213    let wavenumber = c64::new(wavenumber_real, wavenumber_imag);
214    let kernel_type = KernelType::Helmholtz(wavenumber);
215
216
217    c64::assemble_kernel_in_place(sources, targets, result, kernel_type, num_threads);
218
219    
220}
221
222/// Assemble the Helmholtz kernel (single precision version).
223///
224///
225/// # Arguments
226///
227/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
228/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
229/// * `result_ptr` - Pointer to an existing `(ntargets, 2 * nsources)` array that stores the result
230///                  using a complex number memory layout.
231/// * `wavenumber_real` - Real part of the wavenumber parameter.
232/// * `wavenumber_imag` - Imaginary part of the wavenumber parameter.
233/// * `nsources`   - Number of sources.
234/// * `ntargets`   - Number of targets.
235/// * `num_threads`   - Number of threads to use
236#[no_mangle]
237pub extern "C" fn assemble_helmholtz_kernel_f32(
238    source_ptr: *const f32,
239    target_ptr: *const f32,
240    result_ptr: *mut f32,
241    wavenumber_real: f64,
242    wavenumber_imag: f64,
243    nsources: usize,
244    ntargets: usize,
245    num_threads: usize,
246) {
247
248    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
249    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
250    let result = unsafe {
251        ndarray::ArrayViewMut2::from_shape_ptr(
252            (ntargets, nsources),
253            result_ptr as *mut c32,
254        )
255    };
256    let wavenumber = c64::new(wavenumber_real, wavenumber_imag);
257    let kernel_type = KernelType::Helmholtz(wavenumber);
258
259
260    c32::assemble_kernel_in_place(sources, targets, result, kernel_type, num_threads);
261}
262
263/// Evaluate the Helmholtz potential sum (double precision version).
264///
265///
266/// # Arguments
267///
268/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
269/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
270/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
271/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 2)` array (if `return_gradients is false)
272///                  or to an `(ncharge_vecs, ntargets, 2 * 4) array (if `return_gradients is true) that stores the result
273///                  using a complex number memory layout.
274/// * `wavenumber_real` - Real part of the wavenumber parameter.
275/// * `wavenumber_imag` - Imaginary part of the wavenumber parameter.
276/// * `nsources`   - Number of sources.
277/// * `ntargets`   - Number of targets.
278/// * `ncharge_vecs` - Number of charge vectors.
279/// * `return_gradients` - If true return also the gradients.
280/// * `num_threads`   - Number of threads to use
281#[no_mangle]
282pub extern "C" fn evaluate_helmholtz_kernel_f64(
283    source_ptr: *const f64,
284    target_ptr: *const f64,
285    charge_ptr: *const f64,
286    result_ptr: *mut f64,
287    wavenumber_real: f64,
288    wavenumber_imag: f64,
289    nsources: usize,
290    ntargets: usize,
291    ncharge_vecs: usize,
292    return_gradients: bool,
293    num_threads: usize,
294) {
295
296    let eval_mode = match return_gradients {
297        true => EvalMode::ValueGrad,
298        false => EvalMode::Value,
299    };
300        
301    let ncols: usize = match eval_mode {
302        EvalMode::Value => 1,
303        EvalMode::ValueGrad => 4,
304    };
305    let wavenumber = c64::new(wavenumber_real, wavenumber_imag);
306
307    let kernel_type = KernelType::Helmholtz(wavenumber);
308    
309    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
310    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
311    let charges = unsafe {
312        ndarray::ArrayView2::from_shape_ptr(
313            (ncharge_vecs, nsources),
314            charge_ptr as *mut c64,
315        )
316    };
317    
318    let result = unsafe {
319        ndarray::ArrayViewMut3::from_shape_ptr(
320            (ncharge_vecs, ntargets, ncols),
321            result_ptr as *mut c64,
322        )
323    };
324    
325    c64::evaluate_kernel_in_place(
326        sources,
327        targets,
328        charges,
329        result,
330        kernel_type,
331        eval_mode,
332        num_threads,
333    );
334}
335
336/// Evaluate the Helmholtz potential sum (single precision version).
337///
338///
339/// # Arguments
340///
341/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
342/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
343/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
344/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 2)` array (if `return_gradients is false)
345///                  or to an `(ncharge_vecs, ntargets, 2 * 4) array (if `return_gradients is true) that stores the result
346///                  using a complex number memory layout.
347/// * `wavenumber_real` - Real part of the wavenumber parameter.
348/// * `wavenumber_imag` - Imaginary part of the wavenumber parameter.
349/// * `nsources`   - Number of sources.
350/// * `ntargets`   - Number of targets.
351/// * `ncharge_vecs` - Number of charge vectors.
352/// * `return_gradients` - If true return also the gradients.
353/// * `num_threads`   - Number of threads to use
354#[no_mangle]
355pub extern "C" fn evaluate_helmholtz_kernel_f32(
356    source_ptr: *const f32,
357    target_ptr: *const f32,
358    charge_ptr: *const f32,
359    result_ptr: *mut f32,
360    wavenumber_real: f64,
361    wavenumber_imag: f64,
362    nsources: usize,
363    ntargets: usize,
364    ncharge_vecs: usize,
365    return_gradients: bool,
366    num_threads: usize,
367) {
368
369    let eval_mode = match return_gradients {
370        true => EvalMode::ValueGrad,
371        false => EvalMode::Value,
372    };
373
374    let ncols: usize = match eval_mode {
375        EvalMode::Value => 1,
376        EvalMode::ValueGrad => 4,
377    };
378    let wavenumber = c64::new(wavenumber_real, wavenumber_imag);
379
380    let kernel_type = KernelType::Helmholtz(wavenumber);
381    
382    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
383    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
384    let charges = unsafe {
385        ndarray::ArrayView2::from_shape_ptr(
386            (ncharge_vecs, nsources),
387            charge_ptr as *mut c32,
388        )
389    };
390    
391    let result = unsafe {
392        ndarray::ArrayViewMut3::from_shape_ptr(
393            (ncharge_vecs, ntargets, ncols),
394            result_ptr as *mut c32,
395        )
396    };
397    
398    c32::evaluate_kernel_in_place(
399        sources,
400        targets,
401        charges,
402        result,
403        kernel_type,
404        eval_mode,
405        num_threads,
406    );
407}
408
409/// Assemble the modified Helmholtz kernel (double precision version).
410///
411///
412/// # Arguments
413///
414/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
415/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
416/// * `result_ptr` - Pointer to an existing `(ntargets, nsources)` array that stores the result.
417/// * `omega`      - The omega parameter of the kernel.
418/// * `nsources`   - Number of sources.
419/// * `ntargets`   - Number of targets.
420/// * `num_threads`   - Number of threads to use
421#[no_mangle]
422pub extern "C" fn assemble_modified_helmholtz_kernel_f64(
423    source_ptr: *const f64,
424    target_ptr: *const f64,
425    result_ptr: *mut f64,
426    omega: f64,
427    nsources: usize,
428    ntargets: usize,
429    num_threads: usize,
430) {
431
432    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
433    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
434    let result =
435        unsafe { ndarray::ArrayViewMut2::from_shape_ptr((ntargets, nsources), result_ptr) };
436
437    f64::assemble_kernel_in_place(sources, targets, result, KernelType::ModifiedHelmholtz(omega), num_threads);
438}
439
440/// Assemble the modified Helmholtz kernel (single precision version).
441///
442///
443/// # Arguments
444///
445/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
446/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
447/// * `result_ptr` - Pointer to an existing `(ntargets, nsources)` array that stores the result.
448/// * `omega`      - The omega parameter of the kernel.
449/// * `nsources`   - Number of sources.
450/// * `ntargets`   - Number of targets.
451/// * `num_threads`   - Number of threads to use
452#[no_mangle]
453pub extern "C" fn assemble_modified_helmholtz_kernel_f32(
454    source_ptr: *const f32,
455    target_ptr: *const f32,
456    result_ptr: *mut f32,
457    omega: f64,
458    nsources: usize,
459    ntargets: usize,
460    num_threads: usize,
461) {
462
463    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
464    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
465    let result =
466        unsafe { ndarray::ArrayViewMut2::from_shape_ptr((ntargets, nsources), result_ptr) };
467
468    f32::assemble_kernel_in_place(sources, targets, result, KernelType::ModifiedHelmholtz(omega), num_threads);
469}
470
471/// Evaluate the modified Helmholtz potential sum (double precision version).
472///
473///
474/// # Arguments
475///
476/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
477/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
478/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
479/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 1)` array (if `return_gradients is false)
480///                  or to an `(ncharge_vecs, ntargets, 4) array (if `return_gradients is true) that stores the result.
481/// * `omega`      - The omega parameter of the kernel.
482/// * `nsources`   - Number of sources.
483/// * `ntargets`   - Number of targets.
484/// * `ncharge_vecs` - Number of charge vectors.
485/// * `return_gradients` - If true return also the gradients.
486/// * `num_threads`   - Number of threads to use
487#[no_mangle]
488pub extern "C" fn evaluate_modified_helmholtz_kernel_f64(
489    source_ptr: *const f64,
490    target_ptr: *const f64,
491    charge_ptr: *const f64,
492    result_ptr: *mut f64,
493    omega: f64,
494    nsources: usize,
495    ntargets: usize,
496    ncharge_vecs: usize,
497    return_gradients: bool,
498    num_threads: usize,
499) {
500
501    let kernel_type = KernelType::ModifiedHelmholtz(omega);
502
503    let eval_mode = match return_gradients {
504        true => EvalMode::ValueGrad,
505        false => EvalMode::Value,
506    };
507
508    let ncols: usize = match eval_mode {
509        EvalMode::Value => 1,
510        EvalMode::ValueGrad => 4,
511    };
512
513    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
514    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
515    let charges =
516        unsafe { ndarray::ArrayView2::from_shape_ptr((ncharge_vecs, nsources), charge_ptr) };
517    let result = unsafe {
518        ndarray::ArrayViewMut3::from_shape_ptr((ncharge_vecs, ntargets, ncols), result_ptr)
519    };
520
521    f64::evaluate_kernel_in_place(
522        sources,
523        targets,
524        charges,
525        result,
526        kernel_type,
527        eval_mode,
528        num_threads,
529    );
530}
531
532/// Evaluate the modified Helmholtz potential sum (single precision version).
533///
534///
535/// # Arguments
536///
537/// * `source_ptr` - Pointer to a `(3, nsources)` array of sources.
538/// * `target_ptr` - Pointer to a `(3, ntargets)` array of targets.
539/// * `charge_ptr` - Pointer to a `(ncharge_vecs, nsources)` array of `ncharge_vecs` charge vectors.
540/// * `result_ptr` - Pointer to an existing `(ncharge_vecs, ntargets, 1)` array (if `return_gradients is false)
541///                  or to an `(ncharge_vecs, ntargets, 4) array (if `return_gradients is true) that stores the result.
542/// * `omega`      - The omega parameter of the kernel.
543/// * `nsources`   - Number of sources.
544/// * `ntargets`   - Number of targets.
545/// * `ncharge_vecs` - Number of charge vectors.
546/// * `return_gradients` - If true return also the gradients.
547/// * `num_threads`   - Number of threads to use
548#[no_mangle]
549pub extern "C" fn evaluate_modified_helmholtz_kernel_f32(
550    source_ptr: *const f32,
551    target_ptr: *const f32,
552    charge_ptr: *const f32,
553    result_ptr: *mut f32,
554    omega: f64,
555    nsources: usize,
556    ntargets: usize,
557    ncharge_vecs: usize,
558    return_gradients: bool,
559    num_threads: usize,
560) {
561
562    let kernel_type = KernelType::ModifiedHelmholtz(omega);
563
564    let eval_mode = match return_gradients {
565        true => EvalMode::ValueGrad,
566        false => EvalMode::Value,
567    };
568
569    let ncols: usize = match eval_mode {
570        EvalMode::Value => 1,
571        EvalMode::ValueGrad => 4,
572    };
573
574    let targets = unsafe { ndarray::ArrayView2::from_shape_ptr((3, ntargets), target_ptr) };
575    let sources = unsafe { ndarray::ArrayView2::from_shape_ptr((3, nsources), source_ptr) };
576    let charges =
577        unsafe { ndarray::ArrayView2::from_shape_ptr((ncharge_vecs, nsources), charge_ptr) };
578    let result = unsafe {
579        ndarray::ArrayViewMut3::from_shape_ptr((ncharge_vecs, ntargets, ncols), result_ptr)
580    };
581
582    f32::evaluate_kernel_in_place(
583        sources,
584        targets,
585        charges,
586        result,
587        kernel_type,
588        eval_mode,
589        num_threads,
590    );
591}