Oh, I didn't know that. Then it seems my alternative is not actually an improvement but just a compromising for speed by scarifying some accuracy.
Any possible to achieve the same speedup but keep the accuracy in `FastMath.pow`

?

After some profilings, I found we can increase greatly the speed of Taylor propagation of TLE sets using SGP4 model. This is helpful in a Monte-Carlo simulation like a particle filter. I didn't test on other numerical Taylor propagators, but I GUESS the improvement will be similar. There may also be other operations that can be optimized for integers but I didn't dig into that much.

Modifications are made to `org.hipparchus.analysis.differentiation.DSCompiler#taylor(double[], int, double...)`

, I'm not sure if it's proper to submit an issue here since it's mainly related to TLE propagation...

```
* By replacing the `FastMath.pow` calling by a naive power for-loop, we can increase the speed of DSCompiler greatly.
* In my case: 6.14s --> 1.46s
*
* Specific modifications are:
* Modify `org.hipparchus.analysis.differentiation.DSCompiler#taylor(double[], int, double...)`:
* Change this (line 3316 in commit-ea873ba0df8c7a3705f251a27711ac4696aae84b):
* term *= FastMath.pow(delta[k], orders[k]) /
* CombinatoricsUtils.factorial(orders[k]);
* To:
* for (int jj = orders[k]; jj > 0; jj--) term *= delta[k];
* term /= CombinatoricsUtils.factorial(orders[k]);
```

Attached is an example I used to test the performance. Work_05_speedup_taylor.java

Sorry for the late reply, was busy catching the SciTech2022 deadline...

@bryan Thanks for the quick fixing. It works at my end now.

@luc @bryan Thanks for explanations of serialization in JAVA. I'm still kinda new to this but learnt a lot from your insights and sources. My situation is that I need to save data in MATLAB simply using the `save`

MATLAB command, which requires serialization being implemented. For this situation, I'm not sure if there is an alternative or workaround if all serialization support has been removed in the future, but for now everything just works smoothly!

Hi @bryan ,

Thanks for the quick fix.

Based on your explanation, I suppose the bug I reported has been solved.

I'm new to these two methods: `writeReplace`

and `readResolve`

during the serialization. I've got two further questions:

- This fix will re-create the TLE object every time it gets deserialized. Will this have an impact on the performance, technically? If any, is there any way to avoid this additional cost?
- If I extended the built-in
`TLE`

class to a`ExtendedTLE`

class. I guess I need to write my own write and read methods, correct?

After I serialize a group of TLE sets to a file, when I try to load back the data, it gives the error that `null`

encountered.
The following line seems to be the problem, where the `bStarParameterDriver`

doesn't have a meaningful default value during the deserialization process.

```
// org/orekit/propagation/analytical/tle/TLE.java:192
private final transient ParameterDriver bStarParameterDriver;
```

After defining my own `TLENoBStarDriver`

class by only overriding the original `getBStar()`

method, the error had gone.

```
// add a private field
private final double bstar;
// include this in the constructor
public TLENoBStarDriver(String line1, String line2) throws OrekitException {
super(line1, line2);
this.bstar = this.getBStar();
}
// then override the super().getBStar()
@Override
public double getBStar() {
return this.bstar;
}
```

Is there any more "formal" way to fix it? And I don't need to adjust bStar in my work.

Wow... That sounds interesting but is far beyond my current knowledge...

But my suggestion is to keep the current tutorial as for beginners

Note also that the velocity to use for along track direction (from which we deduce across track direction) should also be replaced by using the velocity given by

`projectToGround`

.

@luc Interesting fact and very clear explanation! I should have thought of this!

After a second thought, I deleted my comments about an alternative way to define the line using directions because it also depends on the frame used to define azimuth and elevation.

~~Additionally, I found it is clearer to define the line using ~~`Line.fromDirection(p, Vector3D(azi, ele))`

by specifying the azimuth and elevation angles. Any comments on this alternative? Thanks.

But you can still do the following once the frame is well defined by `nadir`

and `crossTrack`

, which avoids `self.deltaR`

:

```
leftLine = Line.fromDirection(p,
Vector3D(math.cos(math.radians(ANGULAR_OFFSET)), nadir,
math.sin(math.radians(ANGULAR_OFFSET)), crossTrack),
1.0)
```

Would you mind proposing a patch?

In fact I'm very interested in contribution. But I don't know yet how to propose a patch or a pull request. I'm still very new to software development but I can learn. I'm kinda too busy to catch up several deadlines. Should have time about late January. If you haven't patched it by then, I will learn to contribute. Thanks for the offering.

Happy holiday

Additionally, I found it is clearer to define the line using `Line.fromDirection(p, Vector3D(azi, ele))`

by specifying the azimuth and elevation angles.
Any comments on this alternative? Thanks.

I think there is a mistake or at least an inconsistency in the `Track_Corridor`

tutorial

Particularly, in the `handleStep`

method of `class CorridorHandler(PythonOrekitFixedStepHandler)`

(In [10]).
I describe the problem as comments starting with `PH: `

as following:

```
def handleStep(self, currentState, isLast):
# compute sub-satellite track
date = currentState.getDate()
pvInert = currentState.getPVCoordinates()
t = currentState.getFrame().getTransformTo(self.earth.getBodyFrame(), date)
p = t.transformPosition(pvInert.getPosition()) # Hao: here `p` is a Cartesian coordinate in ITRF
v = t.transformVector(pvInert.getVelocity())
center = self.earth.transform(p, self.earth.getBodyFrame(), date) # Hao: here `center` is defined as a geocentric ground track point.
# compute left and right corridor points
# Hao: here `-p` points to geocentric, so `nadir` is defined as a geocentric direction but not a **geocentric** one.
# This is inconsistent with `center` above.
# The geocentric `left` and `right` will then not centered at the geodetic `center`.
nadir = p.normalize().negate()
crossTrack = p.crossProduct(v).normalize()
leftLine = Line(p, Vector3D(1.0, p, self.deltaR, nadir, self.deltaC, crossTrack), 1.0) # PH: line is defined w.r.t. the geocentric nadir
left = self.earth.getIntersectionPoint(leftLine, p, self.earth.getBodyFrame(), date)
rightLine = Line(p, Vector3D(1.0, p, self.deltaR, nadir, -self.deltaC, crossTrack), 1.0)
right = self.earth.getIntersectionPoint(rightLine, p, self.earth.getBodyFrame(), date)
```

My understanding about geodetic or geocentric nadir is based on this post: https://space.stackexchange.com/a/19729/28220

Based on your codes, my way to calculate the geodetic `nadir`

direction is to construct a `center`

point with 0 altitude, then calculate the normalized vector from `center`

to `p`

directly in ITRF, as following:

```
center = GeodeticPoint(center.latitude, center.longitude, 0.0)
center_cartesian= t.inverse.transformPosition(self.earth.transform(center))
nadir_geodetic = t.transformPosition(center_cartesian).subtract(p).normalize()
```

An alternative simplification is to use `self.earth.projectToGround`

directly (not getting exactly identical results but within tolerance of about 10^-6 m):

```
center_cartesian = self.earth.projectToGround(pvInert.getPosition(), date, currentState.frame)
nadir_geodetic = t.transformPosition(center_cartesian).subtract(p).normalize()
```

I'm only about 80% sure about this clarification. So, I wish you could spend some time on further validating the issue.

Thanks, and happy holiday!