Skip to content

Commit 09b95fb

Browse files
committed
Updates for recent heyoka changes.
1 parent 0f82fb2 commit 09b95fb

16 files changed

+96
-189
lines changed

doc/notebooks/sgp4_propagator.ipynb

+3-13
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,7 @@
123123
"id": "1e3ec1fa-1c09-46f7-a8fe-f6da4c33edb2",
124124
"metadata": {},
125125
"source": [
126-
"{py:func}`~heyoka.model.sgp4_propagator()` takes as only mandatory input argument the list of satellites, here represented as ``Satrec`` objects from the [sgp4 Python module](https://pypi.org/project/sgp4/). The list of satellites can alternatively be passed as a NumPy 2D array containing the GPE data for all satellites (see the documentation). {py:func}`~heyoka.model.sgp4_propagator()` returns a propagator object, by default of type {py:func}`~heyoka.model.sgp4_propagator_dbl()` (i.e., a double-precision propagator). You can also request a single-precision propagator via the {ref}`fp_type keyword argument <api_common_kwargs_fp_type>`.\n",
127-
"\n",
128-
"(tut_sgp4_propagator_epochs)=\n",
129-
"\n",
130-
"## A caveat on epochs and scales of time\n",
131-
"\n",
132-
"When an {py:func}`~heyoka.model.sgp4_propagator()` is constructed from a list of ``Satrec`` objects, the satellite epochs are represented as UTC Julian dates. Consequently, UTC Julian dates must also be used when specifying the {ref}`propagation epochs <tut_sgp4_scalar_propagation>`. The use of UTC Julian dates comes with an important caveat: UTC days do not constitute a uniform scale of time due to the potential presence of [leap seconds](https://en.wikipedia.org/wiki/Leap_second). As a consequence, if the time interval between the satellite epoch and the propagation epoch includes a leap second, the result of the propagation will be slightly wrong.\n",
133-
"\n",
134-
"Considering that the last leap second was added in 2016 and that leap seconds may be phased out altogether by 2035, this quirk should not manifest itself when using contemporary GPE data. For the purpose of this tutorial we will thus ignore the leap seconds issue altogether.\n",
135-
"\n",
136-
"If precise propagation across leap seconds is required, one should construct an {py:func}`~heyoka.model.sgp4_propagator()` not via a list of ``Satrec`` objects, but instead using the second overload which takes as input the GPE data as a NumPy 2D array. The GPE epochs in the array should be represented as Julian dates in a continuous scale of time such as [TAI](https://en.wikipedia.org/wiki/International_Atomic_Time). Similarly, the propagation epochs should be provided as Julian dates in the same scale of time. We recommend to use of a library such as [Astropy](https://docs.astropy.org/en/stable/time/index.html) to convert between UTC epochs and TAI Julian dates."
126+
"{py:func}`~heyoka.model.sgp4_propagator()` takes as only mandatory input argument the list of satellites, here represented as ``Satrec`` objects from the [sgp4 Python module](https://pypi.org/project/sgp4/). The list of satellites can alternatively be passed as a NumPy 2D array containing the GPE data for all satellites (see the documentation). {py:func}`~heyoka.model.sgp4_propagator()` returns a propagator object, by default of type {py:func}`~heyoka.model.sgp4_propagator_dbl()` (i.e., a double-precision propagator). You can also request a single-precision propagator via the {ref}`fp_type keyword argument <api_common_kwargs_fp_type>`."
137127
]
138128
},
139129
{
@@ -263,7 +253,7 @@
263253
"source": [
264254
"Julian dates are represented via the {py:attr}`~heyoka.model.sgp4_propagator_dbl.jdtype` type, which is a {ref}`structured NumPy datatype<numpy:defining-structured-types>` consisting of\n",
265255
"two floating-point fields, the first one called ``jd`` and representing a Julian date, the second one called ``frac`` representing a fractional correction to ``jd`` (so that the full\n",
266-
"Julian date is ``jd + frac``). Remember that, since we constructed the propagator from a list of ``Satrec`` objects, the Julian dates are to be provided in the UTC time scale.\n",
256+
"Julian date is ``jd + frac``). Julian dates must be provided in the UTC scale of time, following the [SOFA](http://www.iausofa.org/)/[ERFA](https://github.com/liberfa/erfa/) convention of handling leap seconds via slightly longer/shorter days. We highly recommend the use of a library such as [Astropy](https://docs.astropy.org/en/stable/time/index.html) to convert between calendar days and UTC Julian dates.\n",
267257
"\n",
268258
"Although in principle we could propagate each satellite to a different date, here we will be propagating *all* satellites to the same Julian date:"
269259
]
@@ -1206,7 +1196,7 @@
12061196
"name": "python",
12071197
"nbconvert_exporter": "python",
12081198
"pygments_lexer": "ipython3",
1209-
"version": "3.12.4"
1199+
"version": "3.13.1"
12101200
}
12111201
},
12121202
"nbformat": 4,

heyoka/__init__.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ def from_sympy(ex, s_dict={}):
153153

154154
if not isinstance(ex, Basic):
155155
raise TypeError(
156-
"The 'ex' parameter must be a sympy expression but it is of type {} instead"
157-
.format(type(ex))
156+
"The 'ex' parameter must be a sympy expression but it is of type {} instead".format(
157+
type(ex)
158+
)
158159
)
159160

160161
if not isinstance(s_dict, dict):
@@ -215,8 +216,9 @@ def set_serialization_backend(name):
215216

216217
if not name in _s11n_backend_map:
217218
raise ValueError(
218-
"The serialization backend '{}' is not valid. The valid backends are: {}"
219-
.format(name, list(_s11n_backend_map.keys()))
219+
"The serialization backend '{}' is not valid. The valid backends are: {}".format(
220+
name, list(_s11n_backend_map.keys())
221+
)
220222
)
221223

222224
new_backend = _s11n_backend_map[name]
@@ -289,8 +291,9 @@ def is_iterable(x):
289291
return _ensemble_propagate_process(tp, ta, arg, n_iter, gen, **kwargs)
290292

291293
raise ValueError(
292-
"The parallelisation algorithm must be one of {}, but '{}' was provided instead"
293-
.format(allowed_algos, algo)
294+
"The parallelisation algorithm must be one of {}, but '{}' was provided instead".format(
295+
allowed_algos, algo
296+
)
294297
)
295298

296299

heyoka/_test_batch_integrator.py

+6-11
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,7 @@ def __call__(self, ta):
214214
ta.propagate_for(fp_t(10.0), callback=broken_cb())
215215
self.assertTrue(
216216
"The call operator of a step callback is expected to return a boolean,"
217-
" but a value of type"
218-
in str(cm.exception)
217+
" but a value of type" in str(cm.exception)
219218
)
220219

221220
# Callback with pre_hook().
@@ -321,8 +320,7 @@ def __call__(self, ta):
321320
ta.propagate_until(fp_t(10.0), callback=broken_cb())
322321
self.assertTrue(
323322
"The call operator of a step callback is expected to return a boolean,"
324-
" but a value of type"
325-
in str(cm.exception)
323+
" but a value of type" in str(cm.exception)
326324
)
327325

328326
# Callback with pre_hook().
@@ -713,17 +711,15 @@ def test_propagate_grid(self):
713711
self.assertTrue(
714712
"Invalid grid passed to the propagate_grid() method of a batch"
715713
" integrator: the expected number of dimensions is 2, but the input"
716-
" array has a dimension of 1"
717-
in str(cm.exception)
714+
" array has a dimension of 1" in str(cm.exception)
718715
)
719716

720717
with self.assertRaises(ValueError) as cm:
721718
ta.propagate_grid(np.array([[1, 2], [3, 4]], dtype=fp_t))
722719
self.assertTrue(
723720
"Invalid grid passed to the propagate_grid() method of a batch"
724721
" integrator: the shape must be (n, 4) but the number of columns is 2"
725-
" instead"
726-
in str(cm.exception)
722+
" instead" in str(cm.exception)
727723
)
728724

729725
# Run a simple scalar/batch comparison.
@@ -747,7 +743,7 @@ def test_propagate_grid(self):
747743
self.assertTrue(bres[0] is None)
748744

749745
for idx, cur_ta in enumerate(tas):
750-
cur_ta.propagate_until(grid[0, idx]),
746+
(cur_ta.propagate_until(grid[0, idx]),)
751747

752748
sres = [
753749
tas[0].propagate_grid(grid[:, 0]),
@@ -842,8 +838,7 @@ def __call__(self, ta):
842838
ta.propagate_grid(grid, callback=broken_cb())
843839
self.assertTrue(
844840
"The call operator of a step callback is expected to return a boolean,"
845-
" but a value of type"
846-
in str(cm.exception)
841+
" but a value of type" in str(cm.exception)
847842
)
848843

849844
# Callback with pre_hook().

heyoka/_test_cfunc.py

+23-46
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ def test_multi(self):
144144
cfunc(func, vars=[y, x], fp_type=fp_t, batch_size=2)
145145
self.assertTrue(
146146
"Batch sizes greater than 1 are not supported for this"
147-
" floating-point type"
148-
in str(cm.exception)
147+
" floating-point type" in str(cm.exception)
149148
)
150149

151150
fn = cfunc(func, vars=[y, x], fp_type=fp_t)
@@ -176,8 +175,7 @@ def test_multi(self):
176175
self.assertTrue(
177176
"The array of parameter values provided for the evaluation of a"
178177
" compiled function has 4 column(s), but the expected number of columns"
179-
" deduced from the outputs array is 5"
180-
in str(cm.exception)
178+
" deduced from the outputs array is 5" in str(cm.exception)
181179
)
182180

183181
nw_arr = np.zeros((3, 5), dtype=fp_t)
@@ -191,8 +189,7 @@ def test_multi(self):
191189
)
192190
self.assertTrue(
193191
"The array of outputs provided for the evaluation of a compiled"
194-
" function is not writeable"
195-
in str(cm.exception)
192+
" function is not writeable" in str(cm.exception)
196193
)
197194

198195
with self.assertRaises(ValueError) as cm:
@@ -202,8 +199,7 @@ def test_multi(self):
202199
)
203200
self.assertTrue(
204201
"An array of time values must be provided in order to evaluate a"
205-
" time-dependent function"
206-
in str(cm.exception)
202+
" time-dependent function" in str(cm.exception)
207203
)
208204

209205
with self.assertRaises(TypeError) as cm:
@@ -239,8 +235,7 @@ def test_multi(self):
239235
self.assertTrue(
240236
"The array of time values provided for the evaluation of a compiled"
241237
" function has a size of 6, but the expected size deduced from the"
242-
" outputs array is 5"
243-
in str(cm.exception)
238+
" outputs array is 5" in str(cm.exception)
244239
)
245240

246241
# Check with wrong dtypes.
@@ -253,8 +248,7 @@ def test_multi(self):
253248
)
254249
self.assertTrue(
255250
"Invalid dtype detected for the inputs of a compiled function: the"
256-
" expected dtype "
257-
in str(cm.exception)
251+
" expected dtype " in str(cm.exception)
258252
)
259253

260254
with self.assertRaises(TypeError) as cm:
@@ -265,8 +259,7 @@ def test_multi(self):
265259
)
266260
self.assertTrue(
267261
"Invalid dtype detected for the parameters of a compiled function:"
268-
" the expected dtype "
269-
in str(cm.exception)
262+
" the expected dtype " in str(cm.exception)
270263
)
271264

272265
with self.assertRaises(TypeError) as cm:
@@ -278,8 +271,7 @@ def test_multi(self):
278271
)
279272
self.assertTrue(
280273
"Invalid dtype detected for the outputs of a compiled function: the"
281-
" expected dtype "
282-
in str(cm.exception)
274+
" expected dtype " in str(cm.exception)
283275
)
284276

285277
with self.assertRaises(TypeError) as cm:
@@ -290,8 +282,7 @@ def test_multi(self):
290282
)
291283
self.assertTrue(
292284
"Invalid dtype detected for the time values of a compiled function:"
293-
" the expected dtype "
294-
in str(cm.exception)
285+
" the expected dtype " in str(cm.exception)
295286
)
296287

297288
# Non-contiguous time array.
@@ -527,16 +518,14 @@ def test_multi(self):
527518
self.assertTrue(
528519
"Potential memory overlaps detected when attempting to evaluate"
529520
" a compiled function: please make sure that all input arrays"
530-
" are distinct"
531-
in str(cm.exception)
521+
" are distinct" in str(cm.exception)
532522
)
533523
with self.assertRaises(ValueError) as cm:
534524
fn(inputs=inputs, pars=pars, time=pars[0, :])
535525
self.assertTrue(
536526
"Potential memory overlaps detected when attempting to evaluate"
537527
" a compiled function: please make sure that all input arrays"
538-
" are distinct"
539-
in str(cm.exception)
528+
" are distinct" in str(cm.exception)
540529
)
541530

542531
# Test with arrays which are not C style.
@@ -604,8 +593,7 @@ def test_multi(self):
604593
self.assertTrue(
605594
"Invalid inputs array detected: the array is not C-style"
606595
" contiguous, please consider using numpy.ascontiguousarray()"
607-
" to turn it into one"
608-
in str(cm.exception)
596+
" to turn it into one" in str(cm.exception)
609597
)
610598

611599
pars = rng.random((4, nevals), dtype=float).astype(fp_t)
@@ -615,8 +603,7 @@ def test_multi(self):
615603
self.assertTrue(
616604
"Invalid inputs array detected: the array is not C-style"
617605
" contiguous, please consider using numpy.ascontiguousarray()"
618-
" to turn it into one"
619-
in str(cm.exception)
606+
" to turn it into one" in str(cm.exception)
620607
)
621608

622609
# Tests with no inputs.
@@ -784,8 +771,7 @@ def test_single(self):
784771
self.assertTrue(
785772
"The array of parameter values provided for the evaluation of a"
786773
" compiled function has 0 element(s), but the number of parameters in"
787-
" the function is 2"
788-
in str(cm.exception)
774+
" the function is 2" in str(cm.exception)
789775
)
790776

791777
with self.assertRaises(ValueError) as cm:
@@ -800,8 +786,7 @@ def test_single(self):
800786
fn([fp_t(0)], pars=[fp_t(0)], time=fp_t(0))
801787
self.assertTrue(
802788
"Invalid inputs array passed to a cfunc: the number of function inputs"
803-
" is 2, but the inputs array has a size of 1"
804-
in str(cm.exception)
789+
" is 2, but the inputs array has a size of 1" in str(cm.exception)
805790
)
806791

807792
with self.assertRaises(ValueError) as cm:
@@ -826,8 +811,7 @@ def test_single(self):
826811
self.assertTrue(
827812
"The array of parameter values provided for the evaluation of a"
828813
" compiled function has 0 element(s), but the number of parameters in"
829-
" the function is 2"
830-
in str(cm.exception)
814+
" the function is 2" in str(cm.exception)
831815
)
832816

833817
with self.assertRaises(ValueError) as cm:
@@ -837,8 +821,7 @@ def test_single(self):
837821
)
838822
self.assertTrue(
839823
"A time value must be provided in order to evaluate a time-dependent"
840-
" function"
841-
in str(cm.exception)
824+
" function" in str(cm.exception)
842825
)
843826

844827
eval_arr = fn([fp_t(1), fp_t(2)], pars=[fp_t(-5), fp_t(1)], time=fp_t(3))
@@ -916,17 +899,15 @@ def test_single(self):
916899
self.assertTrue(
917900
"Potential memory overlaps detected when attempting to evaluate a"
918901
" compiled function: please make sure that all input arrays are"
919-
" distinct"
920-
in str(cm.exception)
902+
" distinct" in str(cm.exception)
921903
)
922904

923905
with self.assertRaises(ValueError) as cm:
924906
fn(inputs=inputs, pars=pars, time=fp_t(3), outputs=inputs)
925907
self.assertTrue(
926908
"Potential memory overlaps detected when attempting to evaluate a"
927909
" compiled function: please make sure that all input arrays are"
928-
" distinct"
929-
in str(cm.exception)
910+
" distinct" in str(cm.exception)
930911
)
931912

932913
# Test with arrays which are not C style.
@@ -948,8 +929,7 @@ def test_single(self):
948929
self.assertTrue(
949930
"Invalid parameters array detected: the array is not C-style"
950931
" contiguous, please consider using numpy.ascontiguousarray() to turn"
951-
" it into one"
952-
in str(cm.exception)
932+
" it into one" in str(cm.exception)
953933
)
954934

955935
inputs = np.array([fp_t(1), fp_t(2)])
@@ -973,8 +953,7 @@ def test_single(self):
973953
)
974954
self.assertTrue(
975955
"Invalid dtype detected for the inputs of a compiled function: the"
976-
" expected dtype "
977-
in str(cm.exception)
956+
" expected dtype " in str(cm.exception)
978957
)
979958

980959
with self.assertRaises(TypeError) as cm:
@@ -985,8 +964,7 @@ def test_single(self):
985964
)
986965
self.assertTrue(
987966
"Invalid dtype detected for the parameters of a compiled function:"
988-
" the expected dtype "
989-
in str(cm.exception)
967+
" the expected dtype " in str(cm.exception)
990968
)
991969

992970
with self.assertRaises(TypeError) as cm:
@@ -998,8 +976,7 @@ def test_single(self):
998976
)
999977
self.assertTrue(
1000978
"Invalid dtype detected for the outputs of a compiled function: the"
1001-
" expected dtype "
1002-
in str(cm.exception)
979+
" expected dtype " in str(cm.exception)
1003980
)
1004981

1005982
# Time as an array instead of scalar.

heyoka/_test_dtens.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ def test_basic(self):
9393
dt[1]
9494
self.assertTrue(
9595
"The derivative at index 1 was requested, but the total number of"
96-
" derivatives is 0"
97-
in str(cm.exception)
96+
" derivatives is 0" in str(cm.exception)
9897
)
9998
self.assertFalse([1, 2, 3] in dt)
10099
self.assertFalse((1, [(0, 2), (1, 3)]) in dt)

0 commit comments

Comments
 (0)