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.
- {roche-0.2.3 → roche-0.2.8}/.github/workflows/python-publish.yml +25 -0
- {roche-0.2.3 → roche-0.2.8}/Cargo.lock +1 -1
- {roche-0.2.3 → roche-0.2.8}/Cargo.toml +1 -1
- roche-0.2.8/PKG-INFO +29 -0
- {roche-0.2.3 → roche-0.2.8}/README.md +13 -1
- {roche-0.2.3 → roche-0.2.8}/pyproject.toml +2 -1
- {roche-0.2.3 → roche-0.2.8}/src/blink.rs +50 -66
- {roche-0.2.3 → roche-0.2.8}/src/disc_eclipse.rs +55 -58
- {roche-0.2.3 → roche-0.2.8}/src/errors.rs +5 -5
- {roche-0.2.3 → roche-0.2.8}/src/face.rs +40 -25
- {roche-0.2.3 → roche-0.2.8}/src/fblink.rs +21 -20
- {roche-0.2.3 → roche-0.2.8}/src/ingress_egress.rs +65 -35
- {roche-0.2.3 → roche-0.2.8}/src/jacobi.rs +12 -16
- {roche-0.2.3 → roche-0.2.8}/src/lib.rs +10 -4
- roche-0.2.8/src/lobes.rs +261 -0
- {roche-0.2.3 → roche-0.2.8}/src/phases.rs +138 -54
- {roche-0.2.3 → roche-0.2.8}/src/planck.rs +22 -24
- {roche-0.2.3 → roche-0.2.8}/src/point.rs +11 -16
- {roche-0.2.3 → roche-0.2.8}/src/pot_min.rs +135 -106
- {roche-0.2.3 → roche-0.2.8}/src/potential.rs +140 -125
- {roche-0.2.3 → roche-0.2.8}/src/ref_sphere.rs +37 -20
- {roche-0.2.3 → roche-0.2.8}/src/roche_context.rs +152 -87
- {roche-0.2.3 → roche-0.2.8}/src/set_earth.rs +17 -19
- {roche-0.2.3 → roche-0.2.8}/src/solve_triads.rs +52 -34
- {roche-0.2.3 → roche-0.2.8}/src/sphere_eclipse.rs +72 -48
- {roche-0.2.3 → roche-0.2.8}/src/star_eclipse.rs +42 -10
- {roche-0.2.3 → roche-0.2.8}/src/stream_physics.rs +138 -126
- {roche-0.2.3 → roche-0.2.8}/src/vec3.rs +46 -43
- {roche-0.2.3 → roche-0.2.8}/src/vel_transform.rs +28 -20
- roche-0.2.8/src/vstream_physics.rs +179 -0
- {roche-0.2.3 → roche-0.2.8}/src/x_lagrange.rs +103 -117
- {roche-0.2.3 → roche-0.2.8}/src/zeta_rlobe_eggleton.rs +23 -21
- roche-0.2.3/PKG-INFO +0 -4
- roche-0.2.3/src/lobes.rs +0 -190
- {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 }}
|
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
|
+
[](https://pypi.org/project/roche)
|
|
8
|
+
[](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
|
+
[](https://pypi.org/project/roche)
|
|
2
|
+
[](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,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
|
-
///
|
|
22
|
-
///
|
|
23
|
-
///
|
|
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 =
|
|
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
|
-
|
|
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
|
-
///
|
|
38
|
-
///
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
285
|
-
|
|
280
|
+
Ok(temp)
|
|
286
281
|
}
|
|
287
282
|
|
|
288
|
-
|
|
289
|
-
|
|
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
|
+
}
|