1   /* Copyright 2022-2025 Thales Alenia Space
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.time;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.orekit.utils.ImmutableTimeStampedCache;
22  
23  import java.util.List;
24  import java.util.stream.Stream;
25  
26  /** Offset clock model backed up by a sample.
27   * @author Luc Maisonobe
28   * @since 12.1
29   */
30  public class SampledClockModel implements ClockModel {
31  
32      /** sample. */
33      private final ImmutableTimeStampedCache<ClockOffset> sample;
34  
35      /** Simple constructor.
36       * @param sample clock offsets sample
37       * @param nbInterpolationPoints number of points to use in interpolation
38       */
39      public SampledClockModel(final List<ClockOffset> sample, final int nbInterpolationPoints) {
40          this.sample = new ImmutableTimeStampedCache<>(nbInterpolationPoints, sample);
41      }
42  
43      /** Get the clock offsets cache.
44       * @return clock offsets cache
45       */
46      public ImmutableTimeStampedCache<ClockOffset> getCache() {
47          return sample;
48      }
49  
50      /** {@inheritDoc} */
51      @Override
52      public AbsoluteDate getValidityStart() {
53          return sample.getEarliest().getDate();
54      }
55  
56      /** {@inheritDoc} */
57      @Override
58      public AbsoluteDate getValidityEnd() {
59          return sample.getLatest().getDate();
60      }
61  
62      /** {@inheritDoc} */
63      @Override
64      public ClockOffset getOffset(final AbsoluteDate date) {
65          return new ClockOffsetHermiteInterpolator(sample.getMaxNeighborsSize()).
66              interpolate(date, sample.getNeighbors(date));
67      }
68  
69      /** {@inheritDoc} */
70      @Override
71      public <T extends CalculusFieldElement<T>> FieldClockOffset<T> getOffset(final FieldAbsoluteDate<T> date) {
72  
73          // convert the neighbors to field
74          final Field<T> field = date.getField();
75          final T        zero  = field.getZero();
76          final Stream<FieldClockOffset<T>> fieldSample =
77              sample.
78                  getNeighbors(date.toAbsoluteDate()).
79                  map(c -> {
80                      final FieldAbsoluteDate<T> dateF   = new FieldAbsoluteDate<>(field, c.getDate());
81                      final T                    offsetF = zero.newInstance(c.getOffset());
82                      final T rateF;
83                      final T accelerationF;
84                      if (Double.isNaN(c.getRate())) {
85                          // no rate available
86                          rateF         = null;
87                          accelerationF = null;
88                      } else {
89                          // rate available
90                          rateF = zero.newInstance(c.getRate());
91                          accelerationF = Double.isNaN(c.getAcceleration()) ?
92                                          null :
93                                          zero.newInstance(c.getAcceleration());
94                      }
95                      return new FieldClockOffset<>(dateF, offsetF, rateF, accelerationF);
96                  });
97  
98          // perform interpolation
99          final FieldClockOffsetHermiteInterpolator<T> interpolator =
100             new FieldClockOffsetHermiteInterpolator<>(sample.getMaxNeighborsSize());
101         return interpolator.interpolate(date, fieldSample);
102 
103     }
104 
105 }