lisaanalysistools 1.0.5__cp312-cp312-macosx_10_9_x86_64.whl → 1.0.6__cp312-cp312-macosx_10_9_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lisaanalysistools might be problematic. Click here for more details.

@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lisaanalysistools
3
- Version: 1.0.5
4
- Home-page: https://github.com/mikekatz04/lisa-on-gpu
3
+ Version: 1.0.6
4
+ Home-page: https://github.com/mikekatz04/LISAanalysistools
5
5
  Author: Michael Katz
6
6
  Author-email: mikekatz04@gmail.com
7
7
  Classifier: Programming Language :: Python :: 3
@@ -36,7 +36,9 @@ pip install lisaanalysistools
36
36
 
37
37
  If you want to install all of the tools associated with LISA Analysis Tools (Fast EMRI Waveforms, BBHx, GBGPU, fastlisaresponse, eryn), see the following instructions.
38
38
 
39
- LISA Analysis Tools leverages conda environments to install and use necessary packages. If you do not have [Anaconda](https://www.anaconda.com/download) or [miniconda](https://docs.anaconda.com/free/miniconda/index.html) installed, you must do this first and load your `base` conda environment.
39
+ LISA Analysis Tools leverages conda environments to install and use necessary packages. If you do not have [Anaconda](https://www.anaconda.com/download) or [miniconda](https://docs.anaconda.com/free/miniconda/index.html) installed, you must do this first and load your `base` conda environment. Recommended components for install in your conda environment are `lapack`, `gsl`, `hdf5`, which are needed for various waveform packages.
40
+
41
+ For an easy full install, follow these instructions.
40
42
 
41
43
  First, clone the repo and `cd` to the `LATW` directory.:
42
44
  ```
@@ -50,7 +52,11 @@ bash install.sh
50
52
  ```
51
53
  Running `bash install.sh -h` will also give you some basic install options.
52
54
 
53
- If you want more flexibility, you can install each package given above separately. If you do this, you will also need # TODO: add.
55
+ If you want more flexibility, you can install each package given above separately.
56
+
57
+ To install this software for use with NVIDIA GPUs (compute capability >5.0), you need the [CUDA toolkit](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html) and [CuPy](https://cupy.chainer.org/). The CUDA toolkit must have cuda version >8.0. Be sure to properly install CuPy within the correct CUDA toolkit version. Make sure the nvcc binary is on `$PATH` or set it as the `CUDA_HOME` environment variable.
58
+
59
+ We are currently working on building wheels and making the GPU version pip installable. For now, to work with GPUs, git clone the repository and install it from source.
54
60
 
55
61
  ## Contributing
56
62
 
@@ -58,9 +64,9 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduc
58
64
 
59
65
  ## Versioning
60
66
 
61
- We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/BlackHolePerturbationToolkit/FastEMRIWaveforms/tags).
67
+ We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/mikekatz04/LISAanalysistools/tags).
62
68
 
63
- Current Version: 1.0.5
69
+ Current Version: 1.0.6
64
70
 
65
71
  ## Authors/Developers
66
72
 
@@ -1,12 +1,20 @@
1
1
  lisatools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- lisatools/_version.py,sha256=QnhTB8xNwmBZijHj3vbB3rZZAVZJsQdBQ0N3zLG2pMY,123
2
+ lisatools/_version.py,sha256=14imVuUDlv1B9HhbSkkcqdP6lnMYhzyYQVjZiFvzp6k,123
3
3
  lisatools/analysiscontainer.py,sha256=ePwTBUTEBJn2TK93_afARate9SAqUKK8c8T6DcGUx1Y,15321
4
- lisatools/datacontainer.py,sha256=W89ErPJynfeioZwYqcpehHVorhKsb8FLKrj69zIsKKU,9187
5
- lisatools/detector.py,sha256=_S7fmtOaFLIzTfVnVTXjD58rvl7-DVy2WR4aG1V-CsE,13851
4
+ lisatools/datacontainer.py,sha256=m4gp8E2qOIFq1JPEid3jA450hdNo0yWQu770AVJdrDI,9809
5
+ lisatools/detector.py,sha256=4XYWi8bSdM_97IL1L0EKKInO1fjRM4-FuW3gE8xeEEM,15262
6
6
  lisatools/diagnostic.py,sha256=CfPpfvDys1XyZRWmmTqTSWb0SY2eH0G_8TRnt1OxBFo,34174
7
7
  lisatools/sensitivity.py,sha256=rckXeJ_5U3cRRgbYDmt0kaTyJRjkrYfgBwos12QJJfw,27297
8
- lisatools/stochastic.py,sha256=wdiToEj4nUpCDIb0j7vQ7netTPDDtPGPbUg8-RiFA9U,9421
9
- lisatools/cutils/detector.cpython-312-darwin.so,sha256=FguczB3QPZfL3CCSMEuIx3VP0jj240_Dh30anER84m8,121664
8
+ lisatools/stochastic.py,sha256=XL6ZbqprfcM1rsDw3PhrqdflpQiCnZ5x4y_k4QZ9YGg,9423
9
+ lisatools/cutils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ lisatools/cutils/detector_cpu.cpython-312-darwin.so,sha256=QQFxyuqx9L7HciApuIiw2tLkh-7Qqs4PRkiOWkqcClM,126912
11
+ lisatools/cutils/include/Detector.hpp,sha256=dzdo8QUrrcAnfrTyytlZkQrYmVk_QWXXTL68p4COpZ8,1926
12
+ lisatools/cutils/include/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ lisatools/cutils/include/global.hpp,sha256=3VPiqglTMRrIBXlEvDUJO2-CjKy_SLUXZt-9A1fH6lQ,572
14
+ lisatools/cutils/src/Detector.cpp,sha256=RbPYrK70m0heUZyFha-2_FJOW8Fg9vKfZQzNIXvOqUQ,5188
15
+ lisatools/cutils/src/Detector.cu,sha256=RbPYrK70m0heUZyFha-2_FJOW8Fg9vKfZQzNIXvOqUQ,5188
16
+ lisatools/cutils/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ lisatools/cutils/src/pycppdetector.pyx,sha256=N0AyF5YPPqmHaBKuj4gZVXOt67z9qKwzpB6jlh9zWRY,5581
10
18
  lisatools/sampling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
19
  lisatools/sampling/likelihood.py,sha256=G2kAQ43qlhAzIFWvYsrSmHXd7WKJAzcCN2o07vRE8vc,29585
12
20
  lisatools/sampling/prior.py,sha256=1K1PMStpwO9WT0qG0aotKSyoNjuehXNbzTDtlk8Q15M,21407
@@ -21,8 +29,8 @@ lisatools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
29
  lisatools/utils/constants.py,sha256=r1kVwkpbZS13JTOxj2iRxT5sMgTYX30y-S0JdVmD5Oo,1354
22
30
  lisatools/utils/pointeradjust.py,sha256=2sT-7qeYWr1pd_sHk9leVHUTSJ7jJgYIRoWQOtYqguE,2995
23
31
  lisatools/utils/utility.py,sha256=3mJoJKNGrm3KuNXIa2RUKi9WKd593V4q9XjjQZCQD0M,6831
24
- lisaanalysistools-1.0.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
25
- lisaanalysistools-1.0.5.dist-info/METADATA,sha256=zfuyj8R4brFWnqruMjtzkbTxmVQ5L9Lelh9zNrslfPs,3380
26
- lisaanalysistools-1.0.5.dist-info/WHEEL,sha256=KYtn_mzb_QwZSHwPlosUO3fDl70znfUFngLlrLVHeBY,111
27
- lisaanalysistools-1.0.5.dist-info/top_level.txt,sha256=oCQGY7qy66i_b9MCsK2fTRdbV1pcC9GsGgIDjN47Tyc,14
28
- lisaanalysistools-1.0.5.dist-info/RECORD,,
32
+ lisaanalysistools-1.0.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
33
+ lisaanalysistools-1.0.6.dist-info/METADATA,sha256=1T8XjHyoWcJMiuLG2DpQXqh181FMwc_K2adouVyiuO0,4109
34
+ lisaanalysistools-1.0.6.dist-info/WHEEL,sha256=wTFHiv6xiwExbw_CBGcw1b3hAKzFq_QaWIv4Plh5P0w,110
35
+ lisaanalysistools-1.0.6.dist-info/top_level.txt,sha256=qXUn8Xi8yvK0vr3QH0vvT5cmoccjSj-UPeKGLAxdYGo,10
36
+ lisaanalysistools-1.0.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (72.1.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp312-cp312-macosx_10_9_x86_64
5
5
 
lisatools/_version.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = '1.0.5'
1
+ __version__ = '1.0.6'
2
2
  __copyright__ = "Michael L. Katz 2024"
3
3
  __name__ = "lisaanalysistools"
4
4
  __author__ = "Michael L. Katz"
File without changes
@@ -0,0 +1,78 @@
1
+ #ifndef __DETECTOR_HPP__
2
+ #define __DETECTOR_HPP__
3
+
4
+ #include "global.hpp"
5
+ #include <iostream>
6
+
7
+ class Vec
8
+ {
9
+ public:
10
+ double x;
11
+ double y;
12
+ double z;
13
+
14
+ CUDA_DEVICE
15
+ Vec(double x_, double y_, double z_)
16
+ {
17
+ x = x_;
18
+ y = y_;
19
+ z = z_;
20
+ }
21
+ };
22
+
23
+ class Orbits
24
+ {
25
+ public:
26
+ double dt;
27
+ int N;
28
+ double *n_arr;
29
+ double *ltt_arr;
30
+ double *x_arr;
31
+ int nlinks;
32
+ int nspacecraft;
33
+ int *links;
34
+ int *sc_r;
35
+ int *sc_e;
36
+
37
+ Orbits(double dt_, int N_, double *n_arr_, double *ltt_arr_, double *x_arr_, int *links_, int *sc_r_, int *sc_e_)
38
+ {
39
+ dt = dt_;
40
+ N = N_;
41
+ n_arr = n_arr_;
42
+ ltt_arr = ltt_arr_;
43
+ x_arr = x_arr_;
44
+ nlinks = 6;
45
+ nspacecraft = 3;
46
+
47
+ sc_r = sc_r_;
48
+ sc_e = sc_e_;
49
+ links = links_;
50
+
51
+ // std::cout << " START " << std::endl;
52
+ // for (int i = 0; i < nlinks; i += 1)
53
+ // {
54
+ // sc_r[i] = sc_r_[i];
55
+ // sc_e[i] = sc_e_[i];
56
+ // links[i] = links_[i];
57
+ // // std::cout << i << " HAHAHAH " << sc_r_[i] << " " << sc_e_[i] << std::endl;
58
+ // }
59
+ };
60
+
61
+ CUDA_DEVICE int get_window(double t);
62
+ CUDA_DEVICE Vec get_normal_unit_vec(double t, int link);
63
+ CUDA_DEVICE double interpolate(double t, double *in_arr, int window, int major_ndim, int major_ind, int ndim, int pos);
64
+ CUDA_DEVICE int get_link_ind(int link);
65
+ CUDA_DEVICE int get_sc_ind(int sc);
66
+ CUDA_DEVICE double get_light_travel_time(double t, int link);
67
+ CUDA_DEVICE Vec get_pos(double t, int sc);
68
+ CUDA_DEVICE void get_normal_unit_vec_ptr(Vec *vec, double t, int link);
69
+ CUDA_DEVICE void get_pos_ptr(Vec *vec, double t, int sc);
70
+ void get_light_travel_time_arr(double *ltt, double *t, int *link, int num);
71
+ void dealloc(){
72
+ // delete[] links;
73
+ // delete[] sc_r;
74
+ // delete[] sc_e;
75
+ };
76
+ };
77
+
78
+ #endif // __DETECTOR_HPP__
File without changes
@@ -0,0 +1,28 @@
1
+ #ifndef __GLOBAL_HPP__
2
+ #define __GLOBAL_HPP__
3
+
4
+ #ifdef __CUDACC__
5
+ #define CUDA_KERNEL __global__
6
+ #define CUDA_DEVICE __device__
7
+
8
+ #else // __CUDACC__
9
+ #define CUDA_KERNEL
10
+ #define CUDA_DEVICE
11
+
12
+ #endif // __CUDACC__
13
+
14
+ #ifdef __CUDACC__
15
+ #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
16
+ inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
17
+ {
18
+ if (code != cudaSuccess)
19
+ {
20
+ fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
21
+ if (abort) exit(code);
22
+ }
23
+ }
24
+
25
+ #endif
26
+
27
+
28
+ #endif // __GLOBAL_HPP__
@@ -0,0 +1,210 @@
1
+ #include "stdio.h"
2
+ #include "global.hpp"
3
+ #include "Detector.hpp"
4
+ #include <iostream>
5
+ #include <stdexcept>
6
+ #include <string>
7
+ #include <sstream>
8
+
9
+ CUDA_DEVICE
10
+ int Orbits::get_window(double t)
11
+ {
12
+ int out = int(t / dt);
13
+ if ((out < 0) || (out >= N))
14
+ return -1;
15
+ else
16
+ return out;
17
+ }
18
+
19
+ CUDA_DEVICE
20
+ int Orbits::get_link_ind(int link)
21
+ {
22
+ if (link == 12)
23
+ return 0;
24
+ else if (link == 23)
25
+ return 1;
26
+ else if (link == 31)
27
+ return 2;
28
+ else if (link == 13)
29
+ return 3;
30
+ else if (link == 32)
31
+ return 4;
32
+ else if (link == 21)
33
+ return 5;
34
+ else
35
+ #ifdef __CUDACC__
36
+ printf("BAD link ind. Must be 12, 23, 31, 13, 32, 21.");
37
+ #else
38
+ throw std::invalid_argument("Bad link ind. Must be 12, 23, 31, 13, 32, 21.");
39
+ #endif // __CUDACC__
40
+ return -1;
41
+ }
42
+
43
+ CUDA_DEVICE
44
+ int Orbits::get_sc_ind(int sc)
45
+ {
46
+ if (sc == 1)
47
+ return 0;
48
+ else if (sc == 2)
49
+ return 1;
50
+ else if (sc == 3)
51
+ return 2;
52
+ else
53
+ {
54
+ #ifdef __CUDACC__
55
+ printf("BAD sc ind. Must be 1,2,3. %d\n", sc);
56
+ #else
57
+ std::ostringstream oss;
58
+ int xxxx = 1;
59
+ oss << "Bad sc ind. Must be 1,2,3. Input sc is " << sc << " " << xxxx;
60
+ std::string var = oss.str();
61
+ throw std::invalid_argument(var);
62
+ #endif // __CUDACC__
63
+ }
64
+ return 0;
65
+ }
66
+
67
+ CUDA_DEVICE
68
+ double Orbits::interpolate(double t, double *in_arr, int window, int major_ndim, int major_ind, int ndim, int pos)
69
+ {
70
+ double up = in_arr[((window + 1) * major_ndim + major_ind) * ndim + pos]; // down_ind * ndim + pos];
71
+ double down = in_arr[(window * major_ndim + major_ind) * ndim + pos];
72
+
73
+ // m *(x - x0) + y0
74
+ double fin = ((up - down) / dt) * (t - (dt * window)) + down;
75
+ // if ((ndim == 1))
76
+ // printf("%d %e %e %e %e \n", window, fin, down, up, (t - (dt * window)));
77
+
78
+ return fin;
79
+ }
80
+
81
+ CUDA_DEVICE
82
+ void Orbits::get_normal_unit_vec_ptr(Vec *vec, double t, int link)
83
+ {
84
+ Vec _tmp = get_normal_unit_vec(t, link);
85
+ vec->x = _tmp.x;
86
+ vec->y = _tmp.y;
87
+ vec->z = _tmp.z;
88
+ }
89
+
90
+ CUDA_DEVICE
91
+ Vec Orbits::get_normal_unit_vec(double t, int link)
92
+ {
93
+ int window = get_window(t);
94
+ if (window == -1)
95
+ {
96
+ // out of bounds
97
+ return Vec(0.0, 0.0, 0.0);
98
+ }
99
+
100
+ int link_ind = get_link_ind(link);
101
+
102
+ int up_ind = (window + 1) * nlinks + link_ind;
103
+ int down_ind = window * nlinks + link_ind;
104
+
105
+ // x (pos = 0) ndim = 3
106
+ double x_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 0);
107
+ // y (pos = 1)
108
+ double y_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 1);
109
+ // z (pos = 2)
110
+ double z_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 2);
111
+
112
+ return Vec(x_out, y_out, z_out);
113
+ }
114
+
115
+ CUDA_DEVICE
116
+ double Orbits::get_light_travel_time(double t, int link)
117
+ {
118
+ int window = get_window(t);
119
+ if (window == -1)
120
+ {
121
+ // out of bounds
122
+ return 0.0;
123
+ }
124
+
125
+ int link_ind = get_link_ind(link);
126
+ if ((link_ind < 0) || (link_ind >= 6))
127
+ printf("BAD %d\n", link_ind);
128
+ int up_ind = (window + 1) * (nlinks + link_ind);
129
+ int down_ind = window * (nlinks + link_ind);
130
+
131
+ // x (pos = 0), ndim = 1
132
+ double ltt_out = interpolate(t, ltt_arr, window, nlinks, link_ind, 1, 0);
133
+
134
+ return ltt_out;
135
+ }
136
+
137
+ CUDA_DEVICE
138
+ Vec Orbits::get_pos(double t, int sc)
139
+ {
140
+ int window = get_window(t);
141
+ if (window == -1)
142
+ {
143
+ // out of bounds
144
+ return Vec(0.0, 0.0, 0.0);
145
+ }
146
+
147
+ int sc_ind = get_sc_ind(sc);
148
+
149
+ // x (pos = 0), ndim = 3
150
+ double x_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 0);
151
+ // y (pos = 1), ndim = 3
152
+ double y_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 1);
153
+ // z (pos = 2), ndim = 3
154
+ double z_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 2);
155
+ return Vec(x_out, y_out, z_out);
156
+ }
157
+
158
+ CUDA_DEVICE
159
+ void Orbits::get_pos_ptr(Vec *vec, double t, int sc)
160
+ {
161
+ Vec _tmp = get_pos(t, sc);
162
+ vec->x = _tmp.x;
163
+ vec->y = _tmp.y;
164
+ vec->z = _tmp.z;
165
+ }
166
+
167
+ #define NUM_THREADS 64
168
+
169
+ CUDA_KERNEL
170
+ void get_light_travel_time_kernel(double *ltt, double *t, int *link, int num, Orbits& orbits)
171
+ {
172
+ int start, end, increment;
173
+ #ifdef __CUDACC__
174
+ start = blockIdx.x * blockDim.x + threadIdx.x;
175
+ end = num;
176
+ increment = gridDim.x * blockDim.x;
177
+ #else // __CUDACC__
178
+ start = 0;
179
+ end = num;
180
+ increment = 1;
181
+ #endif // __CUDACC__
182
+
183
+ for (int i = start; i < end; i += increment)
184
+ {
185
+ ltt[i] = orbits.get_light_travel_time(t[i], link[i]);
186
+ }
187
+ }
188
+
189
+ void Orbits::get_light_travel_time_arr(double *ltt, double *t, int *link, int num)
190
+ {
191
+ #ifdef __CUDACC__
192
+ int num_blocks = std::ceil((num + NUM_THREADS - 1) / NUM_THREADS);
193
+
194
+ // copy self to GPU
195
+ Orbits *orbits_gpu;
196
+ gpuErrchk(cudaMalloc(&orbits_gpu, sizeof(Orbits)));
197
+ gpuErrchk(cudaMemcpy(orbits_gpu, this, sizeof(Orbits), cudaMemcpyHostToDevice));
198
+
199
+ get_light_travel_time_kernel<<<num_blocks, NUM_THREADS>>>(ltt, t, link, num, *orbits_gpu);
200
+ cudaDeviceSynchronize();
201
+ gpuErrchk(cudaGetLastError());
202
+
203
+ gpuErrchk(cudaFree(orbits_gpu));
204
+
205
+ #else // __CUDACC__
206
+
207
+ get_light_travel_time_kernel(ltt, t, link, num, *this);
208
+
209
+ #endif // __CUDACC__
210
+ }
@@ -0,0 +1,210 @@
1
+ #include "stdio.h"
2
+ #include "global.hpp"
3
+ #include "Detector.hpp"
4
+ #include <iostream>
5
+ #include <stdexcept>
6
+ #include <string>
7
+ #include <sstream>
8
+
9
+ CUDA_DEVICE
10
+ int Orbits::get_window(double t)
11
+ {
12
+ int out = int(t / dt);
13
+ if ((out < 0) || (out >= N))
14
+ return -1;
15
+ else
16
+ return out;
17
+ }
18
+
19
+ CUDA_DEVICE
20
+ int Orbits::get_link_ind(int link)
21
+ {
22
+ if (link == 12)
23
+ return 0;
24
+ else if (link == 23)
25
+ return 1;
26
+ else if (link == 31)
27
+ return 2;
28
+ else if (link == 13)
29
+ return 3;
30
+ else if (link == 32)
31
+ return 4;
32
+ else if (link == 21)
33
+ return 5;
34
+ else
35
+ #ifdef __CUDACC__
36
+ printf("BAD link ind. Must be 12, 23, 31, 13, 32, 21.");
37
+ #else
38
+ throw std::invalid_argument("Bad link ind. Must be 12, 23, 31, 13, 32, 21.");
39
+ #endif // __CUDACC__
40
+ return -1;
41
+ }
42
+
43
+ CUDA_DEVICE
44
+ int Orbits::get_sc_ind(int sc)
45
+ {
46
+ if (sc == 1)
47
+ return 0;
48
+ else if (sc == 2)
49
+ return 1;
50
+ else if (sc == 3)
51
+ return 2;
52
+ else
53
+ {
54
+ #ifdef __CUDACC__
55
+ printf("BAD sc ind. Must be 1,2,3. %d\n", sc);
56
+ #else
57
+ std::ostringstream oss;
58
+ int xxxx = 1;
59
+ oss << "Bad sc ind. Must be 1,2,3. Input sc is " << sc << " " << xxxx;
60
+ std::string var = oss.str();
61
+ throw std::invalid_argument(var);
62
+ #endif // __CUDACC__
63
+ }
64
+ return 0;
65
+ }
66
+
67
+ CUDA_DEVICE
68
+ double Orbits::interpolate(double t, double *in_arr, int window, int major_ndim, int major_ind, int ndim, int pos)
69
+ {
70
+ double up = in_arr[((window + 1) * major_ndim + major_ind) * ndim + pos]; // down_ind * ndim + pos];
71
+ double down = in_arr[(window * major_ndim + major_ind) * ndim + pos];
72
+
73
+ // m *(x - x0) + y0
74
+ double fin = ((up - down) / dt) * (t - (dt * window)) + down;
75
+ // if ((ndim == 1))
76
+ // printf("%d %e %e %e %e \n", window, fin, down, up, (t - (dt * window)));
77
+
78
+ return fin;
79
+ }
80
+
81
+ CUDA_DEVICE
82
+ void Orbits::get_normal_unit_vec_ptr(Vec *vec, double t, int link)
83
+ {
84
+ Vec _tmp = get_normal_unit_vec(t, link);
85
+ vec->x = _tmp.x;
86
+ vec->y = _tmp.y;
87
+ vec->z = _tmp.z;
88
+ }
89
+
90
+ CUDA_DEVICE
91
+ Vec Orbits::get_normal_unit_vec(double t, int link)
92
+ {
93
+ int window = get_window(t);
94
+ if (window == -1)
95
+ {
96
+ // out of bounds
97
+ return Vec(0.0, 0.0, 0.0);
98
+ }
99
+
100
+ int link_ind = get_link_ind(link);
101
+
102
+ int up_ind = (window + 1) * nlinks + link_ind;
103
+ int down_ind = window * nlinks + link_ind;
104
+
105
+ // x (pos = 0) ndim = 3
106
+ double x_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 0);
107
+ // y (pos = 1)
108
+ double y_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 1);
109
+ // z (pos = 2)
110
+ double z_out = interpolate(t, n_arr, window, nlinks, link_ind, 3, 2);
111
+
112
+ return Vec(x_out, y_out, z_out);
113
+ }
114
+
115
+ CUDA_DEVICE
116
+ double Orbits::get_light_travel_time(double t, int link)
117
+ {
118
+ int window = get_window(t);
119
+ if (window == -1)
120
+ {
121
+ // out of bounds
122
+ return 0.0;
123
+ }
124
+
125
+ int link_ind = get_link_ind(link);
126
+ if ((link_ind < 0) || (link_ind >= 6))
127
+ printf("BAD %d\n", link_ind);
128
+ int up_ind = (window + 1) * (nlinks + link_ind);
129
+ int down_ind = window * (nlinks + link_ind);
130
+
131
+ // x (pos = 0), ndim = 1
132
+ double ltt_out = interpolate(t, ltt_arr, window, nlinks, link_ind, 1, 0);
133
+
134
+ return ltt_out;
135
+ }
136
+
137
+ CUDA_DEVICE
138
+ Vec Orbits::get_pos(double t, int sc)
139
+ {
140
+ int window = get_window(t);
141
+ if (window == -1)
142
+ {
143
+ // out of bounds
144
+ return Vec(0.0, 0.0, 0.0);
145
+ }
146
+
147
+ int sc_ind = get_sc_ind(sc);
148
+
149
+ // x (pos = 0), ndim = 3
150
+ double x_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 0);
151
+ // y (pos = 1), ndim = 3
152
+ double y_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 1);
153
+ // z (pos = 2), ndim = 3
154
+ double z_out = interpolate(t, x_arr, window, nspacecraft, sc_ind, 3, 2);
155
+ return Vec(x_out, y_out, z_out);
156
+ }
157
+
158
+ CUDA_DEVICE
159
+ void Orbits::get_pos_ptr(Vec *vec, double t, int sc)
160
+ {
161
+ Vec _tmp = get_pos(t, sc);
162
+ vec->x = _tmp.x;
163
+ vec->y = _tmp.y;
164
+ vec->z = _tmp.z;
165
+ }
166
+
167
+ #define NUM_THREADS 64
168
+
169
+ CUDA_KERNEL
170
+ void get_light_travel_time_kernel(double *ltt, double *t, int *link, int num, Orbits& orbits)
171
+ {
172
+ int start, end, increment;
173
+ #ifdef __CUDACC__
174
+ start = blockIdx.x * blockDim.x + threadIdx.x;
175
+ end = num;
176
+ increment = gridDim.x * blockDim.x;
177
+ #else // __CUDACC__
178
+ start = 0;
179
+ end = num;
180
+ increment = 1;
181
+ #endif // __CUDACC__
182
+
183
+ for (int i = start; i < end; i += increment)
184
+ {
185
+ ltt[i] = orbits.get_light_travel_time(t[i], link[i]);
186
+ }
187
+ }
188
+
189
+ void Orbits::get_light_travel_time_arr(double *ltt, double *t, int *link, int num)
190
+ {
191
+ #ifdef __CUDACC__
192
+ int num_blocks = std::ceil((num + NUM_THREADS - 1) / NUM_THREADS);
193
+
194
+ // copy self to GPU
195
+ Orbits *orbits_gpu;
196
+ gpuErrchk(cudaMalloc(&orbits_gpu, sizeof(Orbits)));
197
+ gpuErrchk(cudaMemcpy(orbits_gpu, this, sizeof(Orbits), cudaMemcpyHostToDevice));
198
+
199
+ get_light_travel_time_kernel<<<num_blocks, NUM_THREADS>>>(ltt, t, link, num, *orbits_gpu);
200
+ cudaDeviceSynchronize();
201
+ gpuErrchk(cudaGetLastError());
202
+
203
+ gpuErrchk(cudaFree(orbits_gpu));
204
+
205
+ #else // __CUDACC__
206
+
207
+ get_light_travel_time_kernel(ltt, t, link, num, *this);
208
+
209
+ #endif // __CUDACC__
210
+ }
File without changes
@@ -0,0 +1,199 @@
1
+ import numpy as np
2
+ cimport numpy as np
3
+ from libcpp.string cimport string
4
+ from libcpp cimport bool
5
+ from lisatools.utils.pointeradjust import wrapper
6
+ from libc.stdint cimport uintptr_t
7
+
8
+
9
+ cdef extern from "../include/Detector.hpp":
10
+ cdef cppclass VecWrap "Vec":
11
+ double x
12
+ double y
13
+ double z
14
+ VecWrap(double x_, double y_, double z_) except+
15
+
16
+ cdef cppclass OrbitsWrap "Orbits":
17
+ OrbitsWrap(double dt_, int N_, double *n_arr_, double *L_arr_, double *x_arr_, int *links_, int *sc_r_, int *sc_e_) except+
18
+ int get_window(double t) except+
19
+ void get_normal_unit_vec_ptr(VecWrap *vec, double t, int link)
20
+ int get_link_ind(int link) except+
21
+ int get_sc_ind(int sc) except+
22
+ double get_light_travel_time(double t, int link) except+
23
+ VecWrap get_pos_ptr(VecWrap* out, double t, int sc) except+
24
+ void get_light_travel_time_arr(double *ltt, double *t, int *link, int num) except+
25
+ void dealloc();
26
+
27
+
28
+ cdef class pycppDetector:
29
+ cdef OrbitsWrap *g
30
+ cdef double dt
31
+ cdef int N
32
+ cdef size_t n_arr
33
+ cdef size_t L_arr
34
+ cdef size_t x_arr
35
+ cdef size_t links
36
+ cdef size_t sc_r
37
+ cdef size_t sc_e
38
+
39
+ def __cinit__(self,
40
+ *args,
41
+ **kwargs
42
+ ):
43
+ (
44
+ dt,
45
+ N,
46
+ n_arr,
47
+ L_arr,
48
+ x_arr,
49
+ links,
50
+ sc_r,
51
+ sc_e
52
+ ), tkwargs = wrapper(*args, **kwargs)
53
+
54
+ self.dt = dt
55
+ self.N = N
56
+ self.n_arr = n_arr
57
+ self.L_arr = L_arr
58
+ self.x_arr = x_arr
59
+ self.links = links
60
+ self.sc_r = sc_r
61
+ self.sc_e = sc_e
62
+
63
+ cdef size_t n_arr_in = n_arr
64
+ cdef size_t L_arr_in = L_arr
65
+ cdef size_t x_arr_in = x_arr
66
+ cdef size_t links_in = links
67
+ cdef size_t sc_r_in = sc_r
68
+ cdef size_t sc_e_in = sc_e
69
+
70
+ self.g = new OrbitsWrap(
71
+ dt,
72
+ N,
73
+ <double*> n_arr_in,
74
+ <double*> L_arr_in,
75
+ <double*> x_arr_in,
76
+ <int*> links_in,
77
+ <int*> sc_r_in,
78
+ <int*> sc_e_in
79
+ )
80
+
81
+ def __dealloc__(self):
82
+ self.g.dealloc()
83
+ if self.g:
84
+ del self.g
85
+
86
+ def __reduce__(self):
87
+ return (rebuild, (self.dt, self.N, self.n_arr, self.L_arr, self.x_arr, self.links, self.sc_r, self.sc_e,))
88
+
89
+ def get_window(self, t: float) -> int:
90
+ return self.g.get_window(t)
91
+
92
+ def get_normal_unit_vec_single(self, t: float, link: int) -> np.ndarray:
93
+ cdef VecWrap *out = new VecWrap(0.0, 0.0, 0.0)
94
+ self.g.get_normal_unit_vec_ptr(out, t, link)
95
+
96
+ return np.array([out.x, out.y, out.z])
97
+
98
+ def get_normal_unit_vec_arr(self, t: np.ndarray, link: int) -> np.ndarray:
99
+ output = np.zeros((len(t), 3), dtype=float)
100
+ assert t.ndim == 1
101
+ for i in range(len(t)):
102
+ output[i] = self.get_normal_unit_vec_single(t[i], link)
103
+
104
+ return output
105
+
106
+ def get_normal_unit_vec(self, t: np.ndarray | float, link: int) -> np.ndarray:
107
+
108
+ if isinstance(t, float):
109
+ return self.get_normal_unit_vec_single(t, link)
110
+ elif isinstance(t, np.ndarray):
111
+ return self.get_normal_unit_vec_arr(t, link)
112
+
113
+ def get_link_ind(self, link: int) -> int:
114
+ return self.g.get_link_ind(link)
115
+
116
+ def get_sc_ind(self, sc: int) -> int:
117
+ return self.g.get_sc_ind(sc)
118
+
119
+ def get_light_travel_time_single(self, t: float, link: int) -> float:
120
+ return self.g.get_light_travel_time(t, link)
121
+
122
+ def get_light_travel_time_arr(self, t: np.ndarray, link: int) -> np.ndarray:
123
+ output = np.zeros((len(t),), dtype=float)
124
+ assert t.ndim == 1
125
+ for i in range(len(t)):
126
+ output[i] = self.get_light_travel_time_single(t[i], link)
127
+
128
+ return output
129
+
130
+ def get_light_travel_time(self, t: np.ndarray | float, link: int) -> np.ndarray:
131
+
132
+ if isinstance(t, float):
133
+ print("t", t)
134
+ return self.get_light_travel_time_single(t, link)
135
+ elif isinstance(t, np.ndarray):
136
+ return self.get_light_travel_time_arr(t, link)
137
+
138
+ def get_pos_single(self, t: float, sc: int) -> np.ndarray:
139
+
140
+ cdef VecWrap *out = new VecWrap(0.0, 0.0, 0.0)
141
+ self.g.get_pos_ptr(out, t, sc)
142
+
143
+ return np.array([out.x, out.y, out.z])
144
+
145
+ def get_pos_arr(self, t: np.ndarray, sc: int) -> np.ndarray:
146
+ output = np.zeros((len(t), 3), dtype=float)
147
+ assert t.ndim == 1
148
+ for i in range(len(t)):
149
+ output[i] = self.get_pos_single(t[i], sc)
150
+
151
+ return output
152
+
153
+ def get_pos(self, t: np.ndarray | float, sc: int) -> np.ndarray:
154
+
155
+ if isinstance(t, float):
156
+ return self.get_pos_single(t, sc)
157
+ elif isinstance(t, np.ndarray):
158
+ return self.get_pos_arr(t, sc)
159
+
160
+ def get_light_travel_time_arr_wrap(self, *args, **kwargs):
161
+ (ltt, t, link, num), tkwargs = wrapper(*args, **kwargs)
162
+
163
+ cdef size_t ltt_in = ltt
164
+ cdef size_t t_in = t
165
+ cdef size_t link_in = link
166
+
167
+ self.g.get_light_travel_time_arr(
168
+ <double *>ltt_in,
169
+ <double *>t_in,
170
+ <int *>link_in,
171
+ num
172
+ )
173
+
174
+
175
+ @property
176
+ def ptr(self) -> long:
177
+ return <uintptr_t>self.g
178
+
179
+
180
+ def rebuild(dt,
181
+ N,
182
+ n_arr,
183
+ L_arr,
184
+ x_arr,
185
+ links,
186
+ sc_r,
187
+ sc_e
188
+ ):
189
+ c = pycppDetector(
190
+ dt,
191
+ N,
192
+ n_arr,
193
+ L_arr,
194
+ x_arr,
195
+ links,
196
+ sc_r,
197
+ sc_e
198
+ )
199
+ return c
@@ -28,14 +28,19 @@ class DataResidualArray:
28
28
 
29
29
 
30
30
  class DataResidualArray:
31
- """Container to hold sensitivity information.
31
+ """Container to hold Data, residual, or template information.
32
+
33
+ This class abstracts the connection with the sensitivity matrices to make this analysis
34
+ as generic as possible for the user frontend, while handling
35
+ special computations in the backend.
32
36
 
33
37
  Args:
34
- f: Frequency array.
35
- sens_mat: Input sensitivity list. The shape of the nested lists should represent the shape of the
36
- desired matrix. Each entry in the list must be an array, :class:`Sensitivity`-derived object,
37
- or a string corresponding to the :class:`Sensitivity` object.
38
- **sens_kwargs: Keyword arguments to pass to :func:`Sensitivity.get_Sn`.
38
+ data_res_in: Data, residual, or template input information. Can be a list, numpy array
39
+ or another :class:`DataResidualArray`.
40
+ dt: Timestep in seconds.
41
+ f_arr: Frequency array.
42
+ df: Delta f in frequency domain.
43
+ **kwargs: For future compatibility.
39
44
 
40
45
  """
41
46
 
@@ -145,14 +150,17 @@ class DataResidualArray:
145
150
 
146
151
  @property
147
152
  def fmax(self):
153
+ """Maximum frequency."""
148
154
  return self._fmax
149
155
 
150
156
  @property
151
157
  def f_arr(self):
158
+ """Frequency array."""
152
159
  return self._f_arr
153
160
 
154
161
  @property
155
162
  def dt(self):
163
+ """Time step in seconds."""
156
164
  if self._dt is None:
157
165
  raise ValueError("dt cannot be determined from this f_arr input.")
158
166
 
@@ -160,6 +168,7 @@ class DataResidualArray:
160
168
 
161
169
  @property
162
170
  def Tobs(self):
171
+ """Observation time in seconds"""
163
172
  if self._Tobs is None:
164
173
  raise ValueError("Tobs cannot be determined from this f_arr input.")
165
174
 
@@ -167,6 +176,7 @@ class DataResidualArray:
167
176
 
168
177
  @property
169
178
  def df(self):
179
+ """Delta f in the frequency domain."""
170
180
  if self._df is None:
171
181
  raise ValueError("df cannot be determined from this f_arr input.")
172
182
 
@@ -174,14 +184,17 @@ class DataResidualArray:
174
184
 
175
185
  @property
176
186
  def frequency_arr(self) -> np.ndarray:
187
+ """Frequency array"""
177
188
  return self._f_arr
178
189
 
179
190
  @property
180
191
  def data_res_arr(self) -> np.ndarray:
192
+ """Actual data residual array"""
181
193
  return self._data_res_arr
182
194
 
183
195
  @data_res_arr.setter
184
196
  def data_res_arr(self, data_res_arr: List[np.ndarray] | np.ndarray) -> None:
197
+ """Set ``data_res_arr``."""
185
198
  self._data_res_arr_input = data_res_arr
186
199
 
187
200
  if (
@@ -214,17 +227,21 @@ class DataResidualArray:
214
227
  self._data_res_arr = np.asarray(list(new_out), dtype=complex)
215
228
 
216
229
  def __getitem__(self, index: tuple) -> np.ndarray:
230
+ """Index this class directly in ``self.data_res_arr``."""
217
231
  return self.data_res_arr[index]
218
232
 
219
233
  @property
220
234
  def ndim(self) -> int:
235
+ """Number of dimensions in the `data_res_arr`."""
221
236
  return self.data_res_arr.ndim
222
237
 
223
238
  def flatten(self) -> np.ndarray:
239
+ """Flatten the ``data_res_arr``."""
224
240
  return self.data_res_arr.flatten()
225
241
 
226
242
  @property
227
243
  def shape(self) -> tuple:
244
+ """Shape of ``data_res_arr``."""
228
245
  return self.data_res_arr.shape
229
246
 
230
247
  def loglog(
lisatools/detector.py CHANGED
@@ -5,10 +5,20 @@ from dataclasses import dataclass
5
5
  import requests
6
6
 
7
7
  import numpy as np
8
+
9
+ # import for cpu/gpu
10
+ from lisatools.cutils.detector_cpu import pycppDetector as pycppDetector_cpu
11
+
12
+ try:
13
+ import cupy as cp
14
+ from lisatools.cutils.detector_gpu import pycppDetector as pycppDetector_gpu
15
+
16
+ except (ImportError, ModuleNotFoundError) as e:
17
+ pass
18
+
8
19
  import h5py
9
20
  from scipy import interpolate
10
21
 
11
- from lisatools.cutils.detector import pycppDetector
12
22
 
13
23
  SC = [1, 2, 3]
14
24
  LINKS = [12, 23, 31, 13, 32, 21]
@@ -21,14 +31,22 @@ class Orbits(ABC):
21
31
 
22
32
  Args:
23
33
  filename: File name. File should be in the style of LISAOrbits
34
+ use_gpu: If ``True``, use a gpu.
24
35
 
25
36
  """
26
37
 
27
- def __init__(self, filename: str) -> None:
38
+ def __init__(self, filename: str, use_gpu: bool = False) -> None:
39
+ self.use_gpu = use_gpu
28
40
  self.filename = filename
29
41
  self._setup()
30
42
  self.configured = False
31
43
 
44
+ @property
45
+ def xp(self):
46
+ """numpy or cupy based on self.use_gpu"""
47
+ xp = np if not self.use_gpu else cp
48
+ return xp
49
+
32
50
  @property
33
51
  def LINKS(self) -> List[int]:
34
52
  """Link order."""
@@ -229,6 +247,8 @@ class Orbits(ABC):
229
247
  t_arr = np.concatenate([t_arr, self.t_base[-1:]])
230
248
  elif t_arr is not None:
231
249
  assert np.all(t_arr >= self.t_base[0]) and np.all(t_arr <= self.t_base[-1])
250
+ make_cpp = True
251
+ dt = abs(t_arr[1] - t_arr[0])
232
252
 
233
253
  elif dt is not None:
234
254
  make_cpp = True
@@ -266,12 +286,12 @@ class Orbits(ABC):
266
286
  self.pycppdetector_args = (
267
287
  dt,
268
288
  len(self.t),
269
- self.n.flatten().copy(),
270
- self.ltt.flatten().copy(),
271
- self.x.flatten().copy(),
272
- ll,
273
- lsr,
274
- lse,
289
+ self.xp.asarray(self.n.flatten().copy()),
290
+ self.xp.asarray(self.ltt.flatten().copy()),
291
+ self.xp.asarray(self.x.flatten().copy()),
292
+ self.xp.asarray(ll),
293
+ self.xp.asarray(lsr),
294
+ self.xp.asarray(lse),
275
295
  )
276
296
  self.dt = dt
277
297
  else:
@@ -290,12 +310,13 @@ class Orbits(ABC):
290
310
  self._dt = dt
291
311
 
292
312
  @property
293
- def pycppdetector(self) -> pycppDetector:
313
+ def pycppdetector(self) -> pycppDetector_cpu | pycppDetector_gpu:
294
314
  """C++ class"""
295
315
  if self._pycppdetector_args is None:
296
316
  raise ValueError(
297
317
  "Asking for c++ class. Need to set linear_interp_setup = True when configuring."
298
318
  )
319
+ pycppDetector = pycppDetector_cpu if not self.use_gpu else pycppDetector_gpu
299
320
  self._pycppdetector = pycppDetector(*self._pycppdetector_args)
300
321
  return self._pycppdetector
301
322
 
@@ -335,7 +356,24 @@ class Orbits(ABC):
335
356
  Light travel times.
336
357
 
337
358
  """
338
- return self.pycppdetector.get_light_travel_time(t, link)
359
+ if isinstance(t, float) and isinstance(link, int):
360
+ squeeze = True
361
+ t = self.xp.atleast_1d(t)
362
+ link = self.xp.atleast_1d(link).astype(np.int32)
363
+
364
+ else:
365
+ squeeze = False
366
+ t = self.xp.asarray(t)
367
+ link = self.xp.asarray(link).astype(np.int32)
368
+
369
+ ltt_out = self.xp.zeros_like(t)
370
+ self.pycppdetector.get_light_travel_time_arr_wrap(
371
+ ltt_out, t, link, len(ltt_out)
372
+ )
373
+
374
+ if squeeze:
375
+ return ltt_out[0]
376
+ return ltt_out
339
377
 
340
378
  def get_normal_unit_vec(self, t: float | np.ndarray, link: int) -> np.ndarray:
341
379
  """Compute link normal vector as a function of time.
@@ -378,10 +416,13 @@ class EqualArmlengthOrbits(Orbits):
378
416
 
379
417
  Orbit file: equalarmlength-orbits.h5
380
418
 
419
+ Args:
420
+ *args, **kwargs: for :class:`Orbits`.
421
+
381
422
  """
382
423
 
383
- def __init__(self):
384
- super().__init__("equalarmlength-orbits.h5")
424
+ def __init__(self, *args: Any, **kwargs: Any):
425
+ super().__init__("equalarmlength-orbits.h5", *args, **kwargs)
385
426
 
386
427
 
387
428
  class ESAOrbits(Orbits):
@@ -389,11 +430,14 @@ class ESAOrbits(Orbits):
389
430
 
390
431
  Orbit file: esa-trailing-orbits.h5
391
432
 
433
+ Args:
434
+ *args, **kwargs: for :class:`Orbits`.
435
+
392
436
  """
393
437
 
394
- def __init__(self):
438
+ def __init__(self, *args, **kwargs):
395
439
  # TODO: fix this up
396
- super().__init__("esa-trailing-orbits.h5")
440
+ super().__init__("esa-trailing-orbits.h5", *args, **kwargs)
397
441
 
398
442
 
399
443
  class DefaultOrbits(EqualArmlengthOrbits):
lisatools/stochastic.py CHANGED
@@ -249,7 +249,7 @@ class FittedHyperbolicTangentGalacticForeground(HyperbolicTangentGalacticForegro
249
249
 
250
250
  Args:
251
251
  f: Frequency array.
252
- Tobs: Observation time in years.
252
+ Tobs: Observation time in seconds.
253
253
 
254
254
  Returns:
255
255
  PSD of the Galaxy foreground noise