roche 0.2.1__tar.gz

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.
roche-0.2.1/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /target
roche-0.2.1/Cargo.lock ADDED
@@ -0,0 +1,218 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "autocfg"
7
+ version = "1.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
10
+
11
+ [[package]]
12
+ name = "bulirsch"
13
+ version = "0.1.12"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "cdbb964461d0f1217e0dcfd69c2879c4318524c6650d149b410b962bbf0f7c87"
16
+ dependencies = [
17
+ "ndarray",
18
+ "num-traits",
19
+ ]
20
+
21
+ [[package]]
22
+ name = "heck"
23
+ version = "0.5.0"
24
+ source = "registry+https://github.com/rust-lang/crates.io-index"
25
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
26
+
27
+ [[package]]
28
+ name = "libc"
29
+ version = "0.2.183"
30
+ source = "registry+https://github.com/rust-lang/crates.io-index"
31
+ checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
32
+
33
+ [[package]]
34
+ name = "matrixmultiply"
35
+ version = "0.3.10"
36
+ source = "registry+https://github.com/rust-lang/crates.io-index"
37
+ checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
38
+ dependencies = [
39
+ "autocfg",
40
+ "rawpointer",
41
+ ]
42
+
43
+ [[package]]
44
+ name = "ndarray"
45
+ version = "0.16.1"
46
+ source = "registry+https://github.com/rust-lang/crates.io-index"
47
+ checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841"
48
+ dependencies = [
49
+ "matrixmultiply",
50
+ "num-complex",
51
+ "num-integer",
52
+ "num-traits",
53
+ "portable-atomic",
54
+ "portable-atomic-util",
55
+ "rawpointer",
56
+ ]
57
+
58
+ [[package]]
59
+ name = "num-complex"
60
+ version = "0.4.6"
61
+ source = "registry+https://github.com/rust-lang/crates.io-index"
62
+ checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
63
+ dependencies = [
64
+ "num-traits",
65
+ ]
66
+
67
+ [[package]]
68
+ name = "num-integer"
69
+ version = "0.1.46"
70
+ source = "registry+https://github.com/rust-lang/crates.io-index"
71
+ checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
72
+ dependencies = [
73
+ "num-traits",
74
+ ]
75
+
76
+ [[package]]
77
+ name = "num-traits"
78
+ version = "0.2.19"
79
+ source = "registry+https://github.com/rust-lang/crates.io-index"
80
+ checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
81
+ dependencies = [
82
+ "autocfg",
83
+ ]
84
+
85
+ [[package]]
86
+ name = "once_cell"
87
+ version = "1.21.4"
88
+ source = "registry+https://github.com/rust-lang/crates.io-index"
89
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
90
+
91
+ [[package]]
92
+ name = "portable-atomic"
93
+ version = "1.13.1"
94
+ source = "registry+https://github.com/rust-lang/crates.io-index"
95
+ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
96
+
97
+ [[package]]
98
+ name = "portable-atomic-util"
99
+ version = "0.2.6"
100
+ source = "registry+https://github.com/rust-lang/crates.io-index"
101
+ checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3"
102
+ dependencies = [
103
+ "portable-atomic",
104
+ ]
105
+
106
+ [[package]]
107
+ name = "proc-macro2"
108
+ version = "1.0.106"
109
+ source = "registry+https://github.com/rust-lang/crates.io-index"
110
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
111
+ dependencies = [
112
+ "unicode-ident",
113
+ ]
114
+
115
+ [[package]]
116
+ name = "pyo3"
117
+ version = "0.28.2"
118
+ source = "registry+https://github.com/rust-lang/crates.io-index"
119
+ checksum = "cf85e27e86080aafd5a22eae58a162e133a589551542b3e5cee4beb27e54f8e1"
120
+ dependencies = [
121
+ "libc",
122
+ "once_cell",
123
+ "portable-atomic",
124
+ "pyo3-build-config",
125
+ "pyo3-ffi",
126
+ "pyo3-macros",
127
+ ]
128
+
129
+ [[package]]
130
+ name = "pyo3-build-config"
131
+ version = "0.28.2"
132
+ source = "registry+https://github.com/rust-lang/crates.io-index"
133
+ checksum = "8bf94ee265674bf76c09fa430b0e99c26e319c945d96ca0d5a8215f31bf81cf7"
134
+ dependencies = [
135
+ "target-lexicon",
136
+ ]
137
+
138
+ [[package]]
139
+ name = "pyo3-ffi"
140
+ version = "0.28.2"
141
+ source = "registry+https://github.com/rust-lang/crates.io-index"
142
+ checksum = "491aa5fc66d8059dd44a75f4580a2962c1862a1c2945359db36f6c2818b748dc"
143
+ dependencies = [
144
+ "libc",
145
+ "pyo3-build-config",
146
+ ]
147
+
148
+ [[package]]
149
+ name = "pyo3-macros"
150
+ version = "0.28.2"
151
+ source = "registry+https://github.com/rust-lang/crates.io-index"
152
+ checksum = "f5d671734e9d7a43449f8480f8b38115df67bef8d21f76837fa75ee7aaa5e52e"
153
+ dependencies = [
154
+ "proc-macro2",
155
+ "pyo3-macros-backend",
156
+ "quote",
157
+ "syn",
158
+ ]
159
+
160
+ [[package]]
161
+ name = "pyo3-macros-backend"
162
+ version = "0.28.2"
163
+ source = "registry+https://github.com/rust-lang/crates.io-index"
164
+ checksum = "22faaa1ce6c430a1f71658760497291065e6450d7b5dc2bcf254d49f66ee700a"
165
+ dependencies = [
166
+ "heck",
167
+ "proc-macro2",
168
+ "pyo3-build-config",
169
+ "quote",
170
+ "syn",
171
+ ]
172
+
173
+ [[package]]
174
+ name = "quote"
175
+ version = "1.0.45"
176
+ source = "registry+https://github.com/rust-lang/crates.io-index"
177
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
178
+ dependencies = [
179
+ "proc-macro2",
180
+ ]
181
+
182
+ [[package]]
183
+ name = "rawpointer"
184
+ version = "0.2.1"
185
+ source = "registry+https://github.com/rust-lang/crates.io-index"
186
+ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
187
+
188
+ [[package]]
189
+ name = "rust-roche"
190
+ version = "0.2.1"
191
+ dependencies = [
192
+ "bulirsch",
193
+ "ndarray",
194
+ "pyo3",
195
+ ]
196
+
197
+ [[package]]
198
+ name = "syn"
199
+ version = "2.0.117"
200
+ source = "registry+https://github.com/rust-lang/crates.io-index"
201
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
202
+ dependencies = [
203
+ "proc-macro2",
204
+ "quote",
205
+ "unicode-ident",
206
+ ]
207
+
208
+ [[package]]
209
+ name = "target-lexicon"
210
+ version = "0.13.5"
211
+ source = "registry+https://github.com/rust-lang/crates.io-index"
212
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
213
+
214
+ [[package]]
215
+ name = "unicode-ident"
216
+ version = "1.0.24"
217
+ source = "registry+https://github.com/rust-lang/crates.io-index"
218
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
roche-0.2.1/Cargo.toml ADDED
@@ -0,0 +1,21 @@
1
+ [package]
2
+ name = "rust-roche"
3
+ version = "0.2.1"
4
+ edition = "2024"
5
+ description = "Rust translation of Tom Marsh's cpp-roche package for modelling Roche distorted stars/binary systems."
6
+ license = "MIT"
7
+ readme = "README.md"
8
+
9
+ [lib]
10
+ name = "roche"
11
+ # "cdylib" is necessary to produce a shared library for Python to import from.
12
+ crate-type = ["cdylib", "rlib"]
13
+
14
+ [dependencies]
15
+ ndarray = "0.16.1"
16
+ bulirsch = "0.1.12"
17
+
18
+ [dependencies.pyo3]
19
+ version = "0.28.2"
20
+ # "abi3-py38" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.8
21
+ features = ["abi3-py38"]
roche-0.2.1/PKG-INFO ADDED
@@ -0,0 +1,4 @@
1
+ Metadata-Version: 2.4
2
+ Name: roche
3
+ Version: 0.2.1
4
+ Requires-Python: >=3.8
roche-0.2.1/README.md ADDED
@@ -0,0 +1,3 @@
1
+ rust-roche is a translation of Tom Marsh's C++ [cpp-roche](https://github.com/trmrsh/cpp-roche) package for modelling Roche-distorted binary systems. As of the current version, not all functions from cpp-roche have been translated.
2
+
3
+ This is very much a first go at it with only a small amount of testing and so expect bugs.
@@ -0,0 +1,12 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.8,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "roche"
7
+ version = "0.2.1"
8
+ requires-python = ">=3.8"
9
+
10
+ [tool.maturin]
11
+ features = ["pyo3/extension-module"]
12
+ cargo-extra-args = "--features extension-module"
@@ -0,0 +1,211 @@
1
+ use crate::Vec3;
2
+ use crate::errors::RocheError;
3
+ use crate::x_l1;
4
+
5
+ ///
6
+ /// blink tests for the occultation of a point in a semi-detached
7
+ /// binary. blink = true when point is eclipsed, otherwise = false. It works
8
+ /// by first trying to eliminate as many paths that go nowhere near the
9
+ /// Roche lobe before getting down to the hard work of stepping
10
+ /// along the path.
11
+ ///
12
+ /// NB Note that this version of !!emph{blink} works in units of binary separation
13
+ /// NOT the inner lagrangian point distance.
14
+ ///
15
+ /// Arguments:
16
+ ///
17
+ /// * `q`: the mass ratio = M2/M1.
18
+ /// * `r`: the position vector (in units of binary separation)
19
+ /// * `e`: unit vector pointing towards Earth. Standardly this is (sini(i)*cos(phi),-sin(i)*sin(phi),cos(i))
20
+ /// * `acc`: step size parameter. acc specifies the size of steps taken when trying to see if the
21
+ /// photon path goes inside the Roche lobe. The step size is roughly acc times the radius of the lobe filling star.
22
+ /// This means that the photon path could mistakenly not be occulted if it passed less than about (acc**2)/8 of
23
+ /// the radius below the surface of the Roche lobe. acc of order 0.1 should therefore do the job.
24
+ /// Returns:
25
+ ///
26
+ /// * false = not eclipsed; true = eclipsed.
27
+ ///
28
+ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
29
+
30
+ let mut x_cofm: f64;
31
+ let c1: f64;
32
+ let c2: f64;
33
+ let step: f64;
34
+ let pp: f64;
35
+ let crit: f64;
36
+ let mut p: f64;
37
+ let p1: f64;
38
+ let p2: f64;
39
+
40
+
41
+ let mut r1: f64;
42
+ let mut r2: f64;
43
+ // Compute q dependent quantities
44
+ if q <= 0. {
45
+ let message = format!("q = {} <= 0", q);
46
+ return Err(RocheError::ParameterError(message));
47
+ }
48
+
49
+ if acc <= 0.0 {
50
+ let message = format!("Invalid accuracy parameter. {} <= 0.0.", acc);
51
+ return Err(RocheError::ParameterError(message));
52
+ }
53
+
54
+ x_cofm = 1.0 / (1.0 + q);
55
+ c1 = 2.0 * x_cofm;
56
+ x_cofm *= q;
57
+ c2 = 2.0 * x_cofm;
58
+
59
+ // Locate the inner Lagrangian point (L1)
60
+ let rl1: f64 = x_l1(q)?;
61
+
62
+ // Evaluate Roche potential at L1 point.
63
+ r1 = rl1;
64
+ r2 = 1.0 - rl1;
65
+ let xc: f64 = rl1 - x_cofm;
66
+ crit = c1/r1 + c2/r2 + xc*xc;
67
+
68
+ // The red star lies entirely within the sphere centred on its
69
+ // centre of mass and reaching the inner Lagrangian point.
70
+
71
+ let rsphere: f64 = 1.0 - rl1;
72
+ pp = rsphere*rsphere;
73
+ step = rsphere*acc;
74
+
75
+ // From now on computations are done every call. Main point is
76
+ // to try to bail out as soon as possible to save time
77
+
78
+ // evaluate closest approach distance to sphere.
79
+
80
+ let xt: f64 = r.x - 1.0;
81
+ let mut b: f64 = e.x*xt + e.y*r.y + e.z*r.z;
82
+ let mut c: f64 = xt*xt + r.y*r.y + r.z*r.z - pp;
83
+
84
+ // Photon path crosses sphere at two points given by quadratic
85
+ // equation l*l + 2*b*l + c = 0. First check that this has
86
+ // real roots. If not, there is no eclipse. This test should
87
+ // eliminate most cases.
88
+
89
+ let mut fac: f64 = b*b - c;
90
+
91
+ if fac <= 0.0 {
92
+ return Ok(false);
93
+ }
94
+
95
+ fac = fac.sqrt();
96
+
97
+ // If the larger root is negative, the photon starts after the sphere.
98
+ // This should get rid of another whole stack
99
+
100
+
101
+ let par2: f64 = -b + fac;
102
+
103
+ if par2 <= 0.0 {
104
+ return Ok(false);
105
+ }
106
+
107
+ // Now for the hard work. The photon's path does go
108
+ // inside the sphere ... groan. First evaluate smaller root
109
+ // but limit to >= 0 to ensure that only photon path
110
+ // and not its extrapolation backwards in included.
111
+
112
+ let mut par1: f64 = -b - fac;
113
+ par1 = if par1 > 0.0 {
114
+ par1
115
+ } else {
116
+ 0.0
117
+ };
118
+
119
+ // Now follow the photon's path in finite steps to see if
120
+ // it intercepts the red star. We start off at closest
121
+ // approach point to increase chance of only needing one
122
+ // computation of the roche potential
123
+
124
+ let par: f64 = if b < 0.0 {
125
+ -b
126
+ } else {
127
+ 0.0
128
+ };
129
+
130
+ let mut x1: f64 = r.x + par*e.x;
131
+ let mut x2: f64 = r.y + par*e.y;
132
+ let mut x3: f64 = r.z + par*e.z;
133
+
134
+ // Test roche potential for an occultation
135
+ let mut xm: f64 = x1 - 1.0;
136
+ let mut yy: f64 = x2*x2;
137
+ let mut rr: f64 = yy + x3*x3;
138
+ let rs2: f64 = xm*xm + rr;
139
+
140
+ // Point at c of m of red star. Definitely eclipsed, avoids
141
+ // division by 0 later
142
+
143
+ if rs2 <= 0.0 {
144
+ return Ok(true);
145
+ }
146
+
147
+ let rs1: f64 = x1*x1 + rr;
148
+ r1 = rs1.sqrt();
149
+ r2 = rs2.sqrt();
150
+
151
+ // Deeper in well than inner Lagrangian, therefore eclipsed.
152
+
153
+ let mut xc: f64 = x1 - x_cofm;
154
+ c = c1/r1 + c2/r2 + xc*xc + yy;
155
+
156
+ if c > crit {
157
+ return Ok(true);
158
+ }
159
+
160
+ // Now we need to step. Determine step direction by
161
+ // evaluating the first derivative
162
+
163
+ let a: f64 = x1*e.x + x2*e.y;
164
+ b = a + x3*e.z;
165
+
166
+ if -c1*b/(rs1*r1) - c2*(b - e.x)/(rs2*r2) + 2.0*(a - x_cofm*e.x) > 0.0 {
167
+ p1 = par;
168
+ p2 = par2;
169
+ } else {
170
+ p1 = par;
171
+ p2 = par1;
172
+ }
173
+
174
+ // Loop while the Roche potential increases in depth
175
+
176
+ let mut nstep: i32 = ((p2-p1).abs() / step + 0.5).floor() as i32;
177
+
178
+ nstep = nstep.max(2);
179
+
180
+ let dp: f64 = (p2-p1)/(nstep as f64);
181
+ let mut cmax: f64 = c - 1.0;
182
+ let mut i: i32 = 0;
183
+ while c > cmax && i < nstep {
184
+ i += 1;
185
+ cmax = c;
186
+ p = p1 + dp*(i as f64);
187
+ x1 = r.x + p*e.x;
188
+ x2 = r.y + p*e.y;
189
+ x3 = r.z + p*e.z;
190
+
191
+ // test roche potential for an occultation, again guarding
192
+ // against division by 0
193
+
194
+ xm = x1 - 1.0;
195
+ yy = x2*x2;
196
+ rr = yy + x3*x3;
197
+ r2 = (xm*xm + rr).sqrt();
198
+ if r2 <= 0.0 {
199
+ return Ok(true);
200
+ }
201
+ r1 = (x1*x1 + rr).sqrt();
202
+ xc = x1 - x_cofm;
203
+ c = c1/r1 + c2/r2 + xc*xc + yy;
204
+ if c > crit {
205
+ return Ok(true);
206
+ }
207
+ }
208
+
209
+ return Ok(false)
210
+
211
+ }