1   /* Copyright 2022-2026 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.clocks;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.orekit.time.AbsoluteDate;
22  import org.orekit.time.FieldAbsoluteDate;
23  import org.orekit.utils.ImmutableTimeStampedCache;
24  
25  import java.util.List;
26  import java.util.stream.Stream;
27  
28  /** Offset clock model backed up by a sample.
29   * @author Luc Maisonobe
30   * @since 12.1
31   */
32  public class SampledClockModel implements ClockModel {
33  
34      /** sample. */
35      private final ImmutableTimeStampedCache<ClockOffset> sample;
36  
37      /** Simple constructor.
38       * @param sample clock offsets sample
39       * @param nbInterpolationPoints number of points to use in interpolation
40       */
41      public SampledClockModel(final List<ClockOffset> sample, final int nbInterpolationPoints) {
42          this.sample = new ImmutableTimeStampedCache<>(nbInterpolationPoints, sample);
43      }
44  
45      /** Get the clock offsets cache.
46       * @return clock offsets cache
47       */
48      public ImmutableTimeStampedCache<ClockOffset> getCache() {
49          return sample;
50      }
51  
52      /** {@inheritDoc} */
53      @Override
54      public AbsoluteDate getValidityStart() {
55          return sample.getEarliest().getDate();
56      }
57  
58      /** {@inheritDoc} */
59      @Override
60      public AbsoluteDate getValidityEnd() {
61          return sample.getLatest().getDate();
62      }
63  
64      /** {@inheritDoc} */
65      @Override
66      public ClockOffset getOffset(final AbsoluteDate date) {
67          return new ClockOffsetHermiteInterpolator(sample.getMaxNeighborsSize()).
68              interpolate(date, sample.getNeighbors(date));
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public <T extends CalculusFieldElement<T>> FieldClockOffset<T> getOffset(final FieldAbsoluteDate<T> date) {
74  
75          // convert the neighbors to field
76          final Field<T> field = date.getField();
77          final T        zero  = field.getZero();
78          final Stream<FieldClockOffset<T>> fieldSample =
79              sample.
80                  getNeighbors(date.toAbsoluteDate()).
81                  map(c -> {
82                      final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, c.getDate());
83                      final T                    biasF = zero.newInstance(c.getBias());
84                      final T rateF;
85                      final T accelerationF;
86                      if (Double.isNaN(c.getRate())) {
87                          // no rate available
88                          rateF         = null;
89                          accelerationF = null;
90                      } else {
91                          // rate available
92                          rateF = zero.newInstance(c.getRate());
93                          accelerationF = Double.isNaN(c.getAcceleration()) ?
94                                          null :
95                                          zero.newInstance(c.getAcceleration());
96                      }
97                      return new FieldClockOffset<>(dateF, biasF, rateF, accelerationF);
98                  });
99  
100         // perform interpolation
101         final FieldClockOffsetHermiteInterpolator<T> interpolator =
102             new FieldClockOffsetHermiteInterpolator<>(sample.getMaxNeighborsSize());
103         return interpolator.interpolate(date, fieldSample);
104 
105     }
106 
107 }