roche 0.2.3__tar.gz → 0.2.8__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.
Files changed (35) hide show
  1. {roche-0.2.3 → roche-0.2.8}/.github/workflows/python-publish.yml +25 -0
  2. {roche-0.2.3 → roche-0.2.8}/Cargo.lock +1 -1
  3. {roche-0.2.3 → roche-0.2.8}/Cargo.toml +1 -1
  4. roche-0.2.8/PKG-INFO +29 -0
  5. {roche-0.2.3 → roche-0.2.8}/README.md +13 -1
  6. {roche-0.2.3 → roche-0.2.8}/pyproject.toml +2 -1
  7. {roche-0.2.3 → roche-0.2.8}/src/blink.rs +50 -66
  8. {roche-0.2.3 → roche-0.2.8}/src/disc_eclipse.rs +55 -58
  9. {roche-0.2.3 → roche-0.2.8}/src/errors.rs +5 -5
  10. {roche-0.2.3 → roche-0.2.8}/src/face.rs +40 -25
  11. {roche-0.2.3 → roche-0.2.8}/src/fblink.rs +21 -20
  12. {roche-0.2.3 → roche-0.2.8}/src/ingress_egress.rs +65 -35
  13. {roche-0.2.3 → roche-0.2.8}/src/jacobi.rs +12 -16
  14. {roche-0.2.3 → roche-0.2.8}/src/lib.rs +10 -4
  15. roche-0.2.8/src/lobes.rs +261 -0
  16. {roche-0.2.3 → roche-0.2.8}/src/phases.rs +138 -54
  17. {roche-0.2.3 → roche-0.2.8}/src/planck.rs +22 -24
  18. {roche-0.2.3 → roche-0.2.8}/src/point.rs +11 -16
  19. {roche-0.2.3 → roche-0.2.8}/src/pot_min.rs +135 -106
  20. {roche-0.2.3 → roche-0.2.8}/src/potential.rs +140 -125
  21. {roche-0.2.3 → roche-0.2.8}/src/ref_sphere.rs +37 -20
  22. {roche-0.2.3 → roche-0.2.8}/src/roche_context.rs +152 -87
  23. {roche-0.2.3 → roche-0.2.8}/src/set_earth.rs +17 -19
  24. {roche-0.2.3 → roche-0.2.8}/src/solve_triads.rs +52 -34
  25. {roche-0.2.3 → roche-0.2.8}/src/sphere_eclipse.rs +72 -48
  26. {roche-0.2.3 → roche-0.2.8}/src/star_eclipse.rs +42 -10
  27. {roche-0.2.3 → roche-0.2.8}/src/stream_physics.rs +138 -126
  28. {roche-0.2.3 → roche-0.2.8}/src/vec3.rs +46 -43
  29. {roche-0.2.3 → roche-0.2.8}/src/vel_transform.rs +28 -20
  30. roche-0.2.8/src/vstream_physics.rs +179 -0
  31. {roche-0.2.3 → roche-0.2.8}/src/x_lagrange.rs +103 -117
  32. {roche-0.2.3 → roche-0.2.8}/src/zeta_rlobe_eggleton.rs +23 -21
  33. roche-0.2.3/PKG-INFO +0 -4
  34. roche-0.2.3/src/lobes.rs +0 -190
  35. {roche-0.2.3 → roche-0.2.8}/.gitignore +0 -0
@@ -80,3 +80,28 @@ jobs:
80
80
  with:
81
81
  command: upload
82
82
  args: --non-interactive final_dist/*
83
+
84
+
85
+ build_rust:
86
+ runs-on: ubuntu-latest
87
+
88
+ steps:
89
+ - name: Checkout code
90
+ uses: actions/checkout@v1
91
+
92
+ - name: Set up Rust
93
+ uses: actions-rs/toolchain@v1
94
+ with:
95
+ toolchain: stable
96
+ override: true
97
+
98
+ - name: Build
99
+ run: cargo build --release
100
+
101
+ - name: Run Tests
102
+ run: cargo test --release
103
+
104
+ - name: Publish
105
+ run: cargo publish --token ${{ secrets.CRATES_TOKEN }}
106
+ env:
107
+ CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_TOKEN }}
@@ -187,7 +187,7 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
187
187
 
188
188
  [[package]]
189
189
  name = "rust-roche"
190
- version = "0.2.3"
190
+ version = "0.2.8"
191
191
  dependencies = [
192
192
  "bulirsch",
193
193
  "ndarray",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rust-roche"
3
- version = "0.2.3"
3
+ version = "0.2.8"
4
4
  edition = "2024"
5
5
  description = "Rust translation of Tom Marsh's cpp-roche package for modelling Roche distorted stars/binary systems."
6
6
  license = "MIT"
roche-0.2.8/PKG-INFO ADDED
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: roche
3
+ Version: 0.2.8
4
+ Requires-Python: >=3.8
5
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
6
+
7
+ [![PyPi version](https://badgen.net/pypi/v/roche/)](https://pypi.org/project/roche)
8
+ [![crates.io](https://badgen.net/crates/v/rust-roche)](https://crates.io/crates/rust-roche)
9
+
10
+ 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. It also has a few useful functions and types from [cpp-subs](https://github.com/trmrsh/cpp-subs) such as Vec3 and Point.
11
+
12
+
13
+ ### Rust
14
+ The latest version of rust-roche can be viewed at [rust-roche](https://crates.io/crates/rust-roche) and can be added to a rust project with
15
+
16
+ ```
17
+ cargo add rust-roche
18
+ ```
19
+
20
+ Some functions from cpp-roche have not been translated yet so this is still a work-in-progress. Please add an issue on the Github repo if there's a specific function from cpp-roche that you'd like adding.
21
+
22
+ ### Python
23
+ This package has also been wrapped for python to replicate [trm-roche](https://github.com/trmrsh/trm-roche/tree/master) and can be installed with pip from PyPI
24
+
25
+ ```
26
+ pip install roche
27
+ ```
28
+
29
+ This is very much a first go at it. Most functions have been tested against their trm.roche counterparts however not all functions have been tested as of yet and some bugs may remain. Please add an issue on the Github repo if you find any.
@@ -1,7 +1,19 @@
1
+ [![PyPi version](https://badgen.net/pypi/v/roche/)](https://pypi.org/project/roche)
2
+ [![crates.io](https://badgen.net/crates/v/rust-roche)](https://crates.io/crates/rust-roche)
3
+
1
4
  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. It also has a few useful functions and types from [cpp-subs](https://github.com/trmrsh/cpp-subs) such as Vec3 and Point.
2
5
 
3
- Some functions from cpp-roche have not been translated yet so this is still a work-in-progress. Please add an issue on the Github repo if there's a specific function from cpp-roche that you'd like adding.
4
6
 
7
+ ### Rust
8
+ The latest version of rust-roche can be viewed at [rust-roche](https://crates.io/crates/rust-roche) and can be added to a rust project with
9
+
10
+ ```
11
+ cargo add rust-roche
12
+ ```
13
+
14
+ Some functions from cpp-roche have not been translated yet so this is still a work-in-progress. Please add an issue on the Github repo if there's a specific function from cpp-roche that you'd like adding.
15
+
16
+ ### Python
5
17
  This package has also been wrapped for python to replicate [trm-roche](https://github.com/trmrsh/trm-roche/tree/master) and can be installed with pip from PyPI
6
18
 
7
19
  ```
@@ -4,8 +4,9 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "roche"
7
- version = "0.2.3"
7
+ version = "0.2.8"
8
8
  requires-python = ">=3.8"
9
+ readme = "README.md"
9
10
 
10
11
  [tool.maturin]
11
12
  features = ["pyo3/extension-module", "pyo3/abi3-py38"]
@@ -4,8 +4,8 @@ use crate::x_l1;
4
4
 
5
5
  ///
6
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
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
9
  /// Roche lobe before getting down to the hard work of stepping
10
10
  /// along the path.
11
11
  ///
@@ -13,31 +13,25 @@ use crate::x_l1;
13
13
  /// NOT the inner lagrangian point distance.
14
14
  ///
15
15
  /// Arguments:
16
- ///
16
+ ///
17
17
  /// * `q`: the mass ratio = M2/M1.
18
18
  /// * `r`: the position vector (in units of binary separation)
19
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:
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.
25
24
  ///
25
+ /// Returns:
26
+ ///
26
27
  /// * false = not eclipsed; true = eclipsed.
27
28
  ///
28
29
  pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
29
-
30
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
31
  let mut p: f64;
37
32
  let p1: f64;
38
33
  let p2: f64;
39
34
 
40
-
41
35
  let mut r1: f64;
42
36
  let mut r2: f64;
43
37
  // Compute q dependent quantities
@@ -50,11 +44,11 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
50
44
  let message = format!("Invalid accuracy parameter. {} <= 0.0.", acc);
51
45
  return Err(RocheError::ParameterError(message));
52
46
  }
53
-
47
+
54
48
  x_cofm = 1.0 / (1.0 + q);
55
- c1 = 2.0 * x_cofm;
49
+ let c1: f64 = 2.0 * x_cofm;
56
50
  x_cofm *= q;
57
- c2 = 2.0 * x_cofm;
51
+ let c2: f64 = 2.0 * x_cofm;
58
52
 
59
53
  // Locate the inner Lagrangian point (L1)
60
54
  let rl1: f64 = x_l1(q)?;
@@ -63,30 +57,30 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
63
57
  r1 = rl1;
64
58
  r2 = 1.0 - rl1;
65
59
  let xc: f64 = rl1 - x_cofm;
66
- crit = c1/r1 + c2/r2 + xc*xc;
60
+ let crit: f64 = c1 / r1 + c2 / r2 + xc * xc;
67
61
 
68
62
  // The red star lies entirely within the sphere centred on its
69
63
  // centre of mass and reaching the inner Lagrangian point.
70
64
 
71
65
  let rsphere: f64 = 1.0 - rl1;
72
- pp = rsphere*rsphere;
73
- step = rsphere*acc;
66
+ let pp: f64 = rsphere * rsphere;
67
+ let step: f64 = rsphere * acc;
74
68
 
75
69
  // From now on computations are done every call. Main point is
76
- // to try to bail out as soon as possible to save time
70
+ // to try to bail out as soon as possible to save time
77
71
 
78
72
  // evaluate closest approach distance to sphere.
79
73
 
80
74
  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;
75
+ let mut b: f64 = e.x * xt + e.y * r.y + e.z * r.z;
76
+ let mut c: f64 = xt * xt + r.y * r.y + r.z * r.z - pp;
83
77
 
84
78
  // Photon path crosses sphere at two points given by quadratic
85
79
  // equation l*l + 2*b*l + c = 0. First check that this has
86
80
  // real roots. If not, there is no eclipse. This test should
87
81
  // eliminate most cases.
88
82
 
89
- let mut fac: f64 = b*b - c;
83
+ let mut fac: f64 = b * b - c;
90
84
 
91
85
  if fac <= 0.0 {
92
86
  return Ok(false);
@@ -96,7 +90,6 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
96
90
 
97
91
  // If the larger root is negative, the photon starts after the sphere.
98
92
  // This should get rid of another whole stack
99
-
100
93
 
101
94
  let par2: f64 = -b + fac;
102
95
 
@@ -105,37 +98,29 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
105
98
  }
106
99
 
107
100
  // Now for the hard work. The photon's path does go
108
- // inside the sphere ... groan. First evaluate smaller root
101
+ // inside the sphere ... groan. First evaluate smaller root
109
102
  // but limit to >= 0 to ensure that only photon path
110
103
  // and not its extrapolation backwards in included.
111
104
 
112
105
  let mut par1: f64 = -b - fac;
113
- par1 = if par1 > 0.0 {
114
- par1
115
- } else {
116
- 0.0
117
- };
106
+ par1 = if par1 > 0.0 { par1 } else { 0.0 };
118
107
 
119
- // Now follow the photon's path in finite steps to see if
108
+ // Now follow the photon's path in finite steps to see if
120
109
  // it intercepts the red star. We start off at closest
121
- // approach point to increase chance of only needing one
110
+ // approach point to increase chance of only needing one
122
111
  // computation of the roche potential
123
112
 
124
- let par: f64 = if b < 0.0 {
125
- -b
126
- } else {
127
- 0.0
128
- };
113
+ let par: f64 = if b < 0.0 { -b } else { 0.0 };
129
114
 
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;
115
+ let mut x1: f64 = r.x + par * e.x;
116
+ let mut x2: f64 = r.y + par * e.y;
117
+ let mut x3: f64 = r.z + par * e.z;
133
118
 
134
119
  // Test roche potential for an occultation
135
120
  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;
121
+ let mut yy: f64 = x2 * x2;
122
+ let mut rr: f64 = yy + x3 * x3;
123
+ let rs2: f64 = xm * xm + rr;
139
124
 
140
125
  // Point at c of m of red star. Definitely eclipsed, avoids
141
126
  // division by 0 later
@@ -144,26 +129,26 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
144
129
  return Ok(true);
145
130
  }
146
131
 
147
- let rs1: f64 = x1*x1 + rr;
132
+ let rs1: f64 = x1 * x1 + rr;
148
133
  r1 = rs1.sqrt();
149
134
  r2 = rs2.sqrt();
150
135
 
151
136
  // Deeper in well than inner Lagrangian, therefore eclipsed.
152
137
 
153
138
  let mut xc: f64 = x1 - x_cofm;
154
- c = c1/r1 + c2/r2 + xc*xc + yy;
139
+ c = c1 / r1 + c2 / r2 + xc * xc + yy;
155
140
 
156
141
  if c > crit {
157
142
  return Ok(true);
158
143
  }
159
144
 
160
- // Now we need to step. Determine step direction by
145
+ // Now we need to step. Determine step direction by
161
146
  // evaluating the first derivative
162
147
 
163
- let a: f64 = x1*e.x + x2*e.y;
164
- b = a + x3*e.z;
148
+ let a: f64 = x1 * e.x + x2 * e.y;
149
+ b = a + x3 * e.z;
165
150
 
166
- if -c1*b/(rs1*r1) - c2*(b - e.x)/(rs2*r2) + 2.0*(a - x_cofm*e.x) > 0.0 {
151
+ if -c1 * b / (rs1 * r1) - c2 * (b - e.x) / (rs2 * r2) + 2.0 * (a - x_cofm * e.x) > 0.0 {
167
152
  p1 = par;
168
153
  p2 = par2;
169
154
  } else {
@@ -173,39 +158,38 @@ pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
173
158
 
174
159
  // Loop while the Roche potential increases in depth
175
160
 
176
- let mut nstep: i32 = ((p2-p1).abs() / step + 0.5).floor() as i32;
161
+ let mut nstep: i32 = ((p2 - p1).abs() / step + 0.5).floor() as i32;
177
162
 
178
163
  nstep = nstep.max(2);
179
-
180
- let dp: f64 = (p2-p1)/(nstep as f64);
164
+
165
+ let dp: f64 = (p2 - p1) / (nstep as f64);
181
166
  let mut cmax: f64 = c - 1.0;
182
167
  let mut i: i32 = 0;
183
168
  while c > cmax && i < nstep {
184
169
  i += 1;
185
170
  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;
171
+ p = p1 + dp * (i as f64);
172
+ x1 = r.x + p * e.x;
173
+ x2 = r.y + p * e.y;
174
+ x3 = r.z + p * e.z;
190
175
 
191
176
  // test roche potential for an occultation, again guarding
192
177
  // against division by 0
193
178
 
194
179
  xm = x1 - 1.0;
195
- yy = x2*x2;
196
- rr = yy + x3*x3;
197
- r2 = (xm*xm + rr).sqrt();
180
+ yy = x2 * x2;
181
+ rr = yy + x3 * x3;
182
+ r2 = (xm * xm + rr).sqrt();
198
183
  if r2 <= 0.0 {
199
184
  return Ok(true);
200
185
  }
201
- r1 = (x1*x1 + rr).sqrt();
186
+ r1 = (x1 * x1 + rr).sqrt();
202
187
  xc = x1 - x_cofm;
203
- c = c1/r1 + c2/r2 + xc*xc + yy;
188
+ c = c1 / r1 + c2 / r2 + xc * xc + yy;
204
189
  if c > crit {
205
190
  return Ok(true);
206
191
  }
207
192
  }
208
193
 
209
- return Ok(false)
210
-
211
- }
194
+ Ok(false)
195
+ }
@@ -1,7 +1,6 @@
1
- use std::f64::consts::TAU;
2
- use crate::{Etype, Vec3};
3
1
  use crate::errors::RocheError;
4
-
2
+ use crate::{Etype, Vec3};
3
+ use std::f64::consts::TAU;
5
4
 
6
5
  #[derive(Debug, PartialEq, Eq, Clone, Copy)]
7
6
  // This enumerates the 5 possible outcomes of the LOSC intersection with a circle.
@@ -19,36 +18,42 @@ pub enum Circle {
19
18
  }
20
19
 
21
20
  ///
22
- /// disc_eclipse works out phase ranges during which a cylindrically symmetric, flared disc
23
- /// running between a pair of radii eclipses a given point.
21
+ /// disc_eclipse works out phase ranges during which a cylindrically symmetric, flared disc
22
+ /// running between a pair of radii eclipses a given point.
24
23
  ///
25
24
  /// Arguments:
26
- ///
25
+ ///
27
26
  /// * `iangle`: the orbital inclination, degrees. 90 = edge on.
28
27
  /// * `r`: the position vector of the point in question (units of binary separation)
29
28
  /// * `rdisc1`: inner disc radius, units of separation
30
29
  /// * `rdisc2`: outer disc radius, units of separation
31
30
  /// * `beta`: exponent of flaring, so that the height scales as r**beta. beta should be >= 1
32
31
  /// * `height disc`: height at unit radius in disc (even if it does not exist)
33
- ///
32
+ ///
34
33
  /// Returns:
35
- ///
34
+ ///
36
35
  /// * a vector of ingress and egress phase pairs during which the point in question is eclipsed.
37
- /// The ingress phase will always be between 0 and 1 while the egress phase will be larger than this, but
38
- /// by no more than 1 cycle. If the vector is null, no eclipse takes place.
36
+ /// The ingress phase will always be between 0 and 1 while the egress phase will be larger than this, but
37
+ /// by no more than 1 cycle. If the vector is null, no eclipse takes place.
39
38
  ///
40
- pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f64, r: &Vec3) -> Result<Etype, RocheError> {
41
-
39
+ pub fn disc_eclipse(
40
+ iangle: f64,
41
+ rdisc1: f64,
42
+ rdisc2: f64,
43
+ beta: f64,
44
+ height: f64,
45
+ r: &Vec3,
46
+ ) -> Result<Etype, RocheError> {
42
47
  if beta <= 1.0 {
43
- return Err(RocheError::ParameterError("beta must be >= 1.0".to_string()));
48
+ return Err(RocheError::ParameterError(
49
+ "beta must be >= 1.0".to_string(),
50
+ ));
44
51
  }
45
52
 
46
53
  // Compute and store cosine and sine of inclination if need be.
47
54
  // let mut iangle_old: f64 = -1.0e30;
48
55
  let sini: f64;
49
56
  let cosi: f64;
50
- // if iangle != iangle_old {
51
- // iangle_old = iangle;
52
57
  (sini, cosi) = iangle.to_radians().sin_cos();
53
58
  // }
54
59
 
@@ -65,7 +70,7 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
65
70
  // Special case of exactly edge-on, only curved outer edge matters.
66
71
  if cosi == 0.0 {
67
72
  if r.z.abs() < h_out {
68
- let rxy: f64 = (r.x*r.x + r.y*r.y).sqrt();
73
+ let rxy: f64 = (r.x * r.x + r.y * r.y).sqrt();
69
74
  if rxy <= rdisc2 {
70
75
  temp.push((0.0, 1.0));
71
76
  }
@@ -74,23 +79,22 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
74
79
  }
75
80
 
76
81
  // Work out distance from axis
77
- let rxy: f64 = (r.x*r.x + r.y*r.y).sqrt();
82
+ let rxy: f64 = (r.x * r.x + r.y * r.y).sqrt();
78
83
 
79
- if rdisc1 < rxy && rxy < rdisc2 && r.z.abs() < height*rxy.powf(beta) {
84
+ if rdisc1 < rxy && rxy < rdisc2 && r.z.abs() < height * rxy.powf(beta) {
80
85
  // Point is inside disc and so is eclipsed
81
86
  temp.push((0.0, 1.1));
82
87
  return Ok(temp);
83
88
  }
84
89
 
85
- let tani: f64 = sini/cosi;
90
+ let tani: f64 = sini / cosi;
86
91
  let mut result: Circle;
87
92
 
88
93
  let mut phase: f64 = 0.0;
89
94
  let mut ingress: f64;
90
95
  let mut egress: f64;
91
96
 
92
- if rxy < rdisc2 && r.z >= height*rdisc1.max(rxy).powf(beta) {
93
-
97
+ if rxy < rdisc2 && r.z >= height * rdisc1.max(rxy).powf(beta) {
94
98
  // Point is in approximately conical region above the disc. Just need to check whether
95
99
  // it is not occulted by the edge of the disc
96
100
  result = circle_eclipse(rxy, r.z, h_out, rdisc2, tani, &mut phase);
@@ -100,27 +104,27 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
100
104
  temp.push((0.0, 1.1));
101
105
  } else if result == Circle::Crossing {
102
106
  // point partially occulted by disc edge; work out phases
103
- let phi0: f64 = r.y.atan2(r.x)/TAU;
107
+ let phi0: f64 = r.y.atan2(r.x) / TAU;
104
108
  ingress = phi0 + phase;
105
109
  ingress -= ingress.floor();
106
- egress = ingress + 1.0 - 2.0*phase;
110
+ egress = ingress + 1.0 - 2.0 * phase;
107
111
  temp.push((ingress, egress));
108
112
  }
109
113
  return Ok(temp);
110
114
  }
111
115
 
112
- // Compute the radius of circle formed by LOSC in the plane of
116
+ // Compute the radius of circle formed by LOSC in the plane of
113
117
  // the lower outer rim of the disc
114
- let rcone_lo: f64 = 0.0_f64.max(tani*(-h_out - r.z));
118
+ let rcone_lo: f64 = 0.0_f64.max(tani * (-h_out - r.z));
115
119
 
116
120
  // Circle encloses rim, so no intersection
117
121
  if rcone_lo >= rxy + rdisc2 {
118
122
  return Ok(temp);
119
123
  }
120
124
 
121
- // Compute the radius of circle formed by LOSC in the plane of
125
+ // Compute the radius of circle formed by LOSC in the plane of
122
126
  // the upper outer rim of the disc
123
- let rcone_hi: f64 = tani*(h_out - r.z);
127
+ let rcone_hi: f64 = tani * (h_out - r.z);
124
128
 
125
129
  // Circle disjoint from rim, so no intersection
126
130
  if rxy >= rcone_hi + rdisc2 {
@@ -128,7 +132,7 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
128
132
  }
129
133
 
130
134
  // For the moment we pretend that the disc has no hole at its centre, so
131
- // that we are simply interested in the phases over which eclipse occurs.
135
+ // that we are simply interested in the phases over which eclipse occurs.
132
136
  // At this point we are guaranteed that this will happen. All events are
133
137
  // symmetrically located around a phase defined by x and y only which will
134
138
  // be calculated at the end. We therefore just find the half range which
@@ -136,30 +140,25 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
136
140
 
137
141
  let eclipse_phase: f64;
138
142
  if rxy + rcone_lo <= rdisc2 {
139
-
140
143
  // Cone swept out by line of sight always inside lower face so total eclipse
141
144
  eclipse_phase = 0.5;
142
145
  } else if rxy <= rdisc2 {
143
-
144
- // Points that project close to the z axis which are only
146
+ // Points that project close to the z axis which are only
145
147
  // partially obscured by the disc hovering above them.
146
- // this means they must be below -HOUT
148
+ // this means they must be below -HOUT
147
149
  eclipse_phase = cut_phase(rxy, rcone_lo, rdisc2);
148
150
  } else {
149
-
150
151
  // Points further from the z axis than the outer rim of the disc that
151
152
  // will be eclipsed.
152
- if rcone_hi*rcone_hi + rdisc2*rdisc2 >= rxy*rxy
153
- && rcone_lo*rcone_lo + rdisc2*rdisc2 <= rxy*rxy {
154
-
153
+ if rcone_hi * rcone_hi + rdisc2 * rdisc2 >= rxy * rxy
154
+ && rcone_lo * rcone_lo + rdisc2 * rdisc2 <= rxy * rxy
155
+ {
155
156
  // In this case it is the curved outer disc rim that sets the limit
156
- eclipse_phase = (rdisc2/rxy).asin()/TAU;
157
- } else if rcone_hi*rcone_hi + rdisc2*rdisc2 < rxy*rxy {
158
-
157
+ eclipse_phase = (rdisc2 / rxy).asin() / TAU;
158
+ } else if rcone_hi * rcone_hi + rdisc2 * rdisc2 < rxy * rxy {
159
159
  // In this case it is upper outer rim that sets the limit
160
160
  eclipse_phase = cut_phase(rxy, rcone_hi, rdisc2);
161
161
  } else {
162
-
163
162
  // In this case it is lower outer rim that sets the limit
164
163
  eclipse_phase = cut_phase(rxy, rcone_lo, rdisc2);
165
164
  }
@@ -170,7 +169,7 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
170
169
  // Now let's calculate the 'appear_phase' if any.
171
170
 
172
171
  // First compute height of disc at inner boundary
173
- let h_in: f64 = height*rdisc1.powf(beta);
172
+ let h_in: f64 = height * rdisc1.powf(beta);
174
173
 
175
174
  let mut appear_phase: f64 = -1.0;
176
175
 
@@ -206,11 +205,9 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
206
205
  }
207
206
  }
208
207
  } else if rxy < rdisc1 {
209
-
210
208
  if r.z < -h_in {
211
-
212
209
  // Points hovering around underside of disc. Have to consider just three circles
213
-
210
+
214
211
  // First, the lower inner rim
215
212
  result = circle_eclipse(rxy, r.z, -h_in, rdisc1, tani, &mut phase);
216
213
  if result == Circle::Inside {
@@ -239,7 +236,6 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
239
236
  }
240
237
  }
241
238
  } else if r.z < h_in {
242
-
243
239
  // Points inside hole in middle of disc. Have to consider just two circles
244
240
 
245
241
  // First, the upper inner rim
@@ -263,12 +259,12 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
263
259
  }
264
260
 
265
261
  // Here is the central phase
266
- let phi0: f64 = r.y.atan2(-r.x/TAU);
262
+ let phi0: f64 = r.y.atan2(-r.x / TAU);
267
263
 
268
264
  if appear_phase <= 0.0 {
269
265
  ingress = phi0 - eclipse_phase;
270
266
  ingress -= ingress.floor();
271
- egress = ingress + 2.0*eclipse_phase;
267
+ egress = ingress + 2.0 * eclipse_phase;
272
268
  temp.push((ingress, egress));
273
269
  } else if appear_phase < eclipse_phase {
274
270
  ingress = phi0 - eclipse_phase;
@@ -281,23 +277,27 @@ pub fn disc_eclipse(iangle: f64, rdisc1: f64, rdisc2: f64, beta: f64, height: f6
281
277
  temp.push((ingress, egress));
282
278
  }
283
279
 
284
- return Ok(temp)
285
-
280
+ Ok(temp)
286
281
  }
287
282
 
288
-
289
- pub fn circle_eclipse(rxy: f64, z: f64, zcirc: f64, radius: f64, tani: f64, phase: &mut f64) -> Circle {
290
-
283
+ pub fn circle_eclipse(
284
+ rxy: f64,
285
+ z: f64,
286
+ zcirc: f64,
287
+ radius: f64,
288
+ tani: f64,
289
+ phase: &mut f64,
290
+ ) -> Circle {
291
291
  // point above circle
292
292
  if z >= zcirc {
293
293
  return Circle::Above;
294
294
  }
295
- let rcone: f64 = tani*(zcirc - z);
295
+ let rcone: f64 = tani * (zcirc - z);
296
296
 
297
297
  // line-of-sight always outside the circle
298
298
  if rcone >= rxy + radius {
299
299
  return Circle::Outside;
300
- }
300
+ }
301
301
 
302
302
  // line-of-sight circle separate from the circle
303
303
  if rxy >= rcone + radius {
@@ -313,12 +313,9 @@ pub fn circle_eclipse(rxy: f64, z: f64, zcirc: f64, radius: f64, tani: f64, phas
313
313
  *phase = cut_phase(rxy, rcone, radius);
314
314
 
315
315
  Circle::Crossing
316
-
317
316
  }
318
317
 
319
-
320
318
  pub fn cut_phase(rxy: f64, rcone: f64, radius: f64) -> f64 {
321
-
322
319
  // Temporary checks
323
320
  if rxy + rcone <= radius {
324
321
  panic!("rxy + rcone <= radius");
@@ -330,5 +327,5 @@ pub fn cut_phase(rxy: f64, rcone: f64, radius: f64) -> f64 {
330
327
  panic!("rcone >= radius + rxy");
331
328
  }
332
329
 
333
- ((rxy*rxy + rcone*rcone - radius*radius)/(2.0*rcone*rxy)).acos()/TAU
330
+ ((rxy * rxy + rcone * rcone - radius * radius) / (2.0 * rcone * rxy)).acos() / TAU
334
331
  }
@@ -1,5 +1,5 @@
1
- use pyo3::prelude::*;
2
1
  use pyo3::exceptions::{PyRuntimeError, PyValueError};
2
+ use pyo3::prelude::*;
3
3
  use std::fmt;
4
4
 
5
5
  #[derive(Debug)]
@@ -17,7 +17,7 @@ pub enum RocheError {
17
17
  // error in rtsafe function
18
18
  RtsafeError(String),
19
19
  // error in wd_phases function
20
- WdphasesError(String)
20
+ WdphasesError(String),
21
21
  }
22
22
 
23
23
  impl std::error::Error for RocheError {}
@@ -44,8 +44,8 @@ impl std::convert::From<RocheError> for PyErr {
44
44
  RocheError::PotminError(_) => PyRuntimeError::new_err(err.to_string()),
45
45
  RocheError::ParameterError(_) => PyValueError::new_err(err.to_string()),
46
46
  RocheError::FaceError(_) => PyRuntimeError::new_err(err.to_string()),
47
- RocheError::RtsafeError(_) => PyRuntimeError::new_err(err.to_string()),
48
- RocheError::WdphasesError(_) => PyRuntimeError::new_err(err.to_string()),
47
+ RocheError::RtsafeError(_) => PyRuntimeError::new_err(err.to_string()),
48
+ RocheError::WdphasesError(_) => PyRuntimeError::new_err(err.to_string()),
49
49
  }
50
50
  }
51
- }
51
+ }