OceanTidesField.java

  1. /* Copyright 2002-2013 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.forces.gravity;

  18. import java.util.List;

  19. import org.apache.commons.math3.util.FastMath;
  20. import org.orekit.data.BodiesElements;
  21. import org.orekit.data.FundamentalNutationArguments;
  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
  24. import org.orekit.forces.gravity.potential.OceanTidesWave;
  25. import org.orekit.forces.gravity.potential.TideSystem;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.TimeFunction;

  28. /** Gravity field corresponding to ocean tides.
  29.  * <p>
  30.  * This ocean tides force model implementation corresponds to the method described
  31.  * in <a href="http://www.iers.org/nn_11216/IERS/EN/Publications/TechnicalNotes/tn36.html">
  32.  * IERS conventions (2010)</a>, chapter 6, section 6.3.
  33.  * </p>
  34.  * <p>
  35.  * Note that this class is <em>not</em> thread-safe, and that tides computation
  36.  * are computer intensive if repeated. So this class is really expected to
  37.  * be wrapped within a {@link
  38.  * org.orekit.forces.gravity.potential.CachedNormalizedSphericalHarmonicsProvider}
  39.  * that will both ensure thread safety and improve performances using caching.
  40.  * </p>
  41.  * @see OceanTides
  42.  * @author Luc Maisonobe
  43.  * @since 6.1
  44.  */
  45. class OceanTidesField implements NormalizedSphericalHarmonicsProvider {

  46.     /** Maximum degree. */
  47.     private final int degree;

  48.     /** Maximum order. */
  49.     private final int order;

  50.     /** Central body reference radius. */
  51.     private final double ae;

  52.     /** Central body attraction coefficient. */
  53.     private final double mu;

  54.     /** Tides model. */
  55.     private final List<OceanTidesWave> waves;

  56.     /** Object computing the fundamental arguments. */
  57.     private final FundamentalNutationArguments arguments;

  58.     /** Function computing pole tide terms (ΔC₂₁, ΔS₂₁). */
  59.     private final TimeFunction<double []> poleTideFunction;

  60.     /** Simple constructor.
  61.      * @param ae central body reference radius
  62.      * @param mu central body attraction coefficient
  63.      * @param waves ocean tides waves
  64.      * @param arguments object computing the fundamental arguments
  65.      * @param poleTideFunction function computing ocean pole tide terms (ΔC₂₁, ΔS₂₁), may be null
  66.      * @exception OrekitException if the Love numbers embedded in the
  67.      * library cannot be read
  68.      */
  69.     public OceanTidesField(final double ae, final double mu,
  70.                            final List<OceanTidesWave> waves,
  71.                            final FundamentalNutationArguments arguments,
  72.                            final TimeFunction<double []> poleTideFunction)
  73.         throws OrekitException {

  74.         // store mode parameters
  75.         this.ae  = ae;
  76.         this.mu  = mu;

  77.         // waves
  78.         this.waves = waves;
  79.         int m = 0;
  80.         int n = 0;
  81.         for (final OceanTidesWave wave : waves) {
  82.             m = FastMath.max(m, wave.getMaxDegree());
  83.             n = FastMath.max(n, wave.getMaxOrder());
  84.         }
  85.         degree = m;
  86.         order  = n;

  87.         this.arguments = arguments;

  88.         // pole tide
  89.         this.poleTideFunction = poleTideFunction;

  90.     }

  91.     /** {@inheritDoc} */
  92.     @Override
  93.     public int getMaxDegree() {
  94.         return degree;
  95.     }

  96.     /** {@inheritDoc} */
  97.     @Override
  98.     public int getMaxOrder() {
  99.         return order;
  100.     }

  101.     /** {@inheritDoc} */
  102.     @Override
  103.     public double getMu() {
  104.         return mu;
  105.     }

  106.     /** {@inheritDoc} */
  107.     @Override
  108.     public double getAe() {
  109.         return ae;
  110.     }

  111.     /** {@inheritDoc} */
  112.     @Override
  113.     public AbsoluteDate getReferenceDate() {
  114.         return AbsoluteDate.J2000_EPOCH;
  115.     }

  116.     /** {@inheritDoc} */
  117.     @Override
  118.     public double getOffset(final AbsoluteDate date) {
  119.         return date.durationFrom(AbsoluteDate.J2000_EPOCH);
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public TideSystem getTideSystem() {
  124.         // not really used here, but for consistency we can state that either
  125.         // we add the permanent tide or it was already in the central attraction
  126.         return TideSystem.ZERO_TIDE;
  127.     }

  128.     /** {@inheritDoc} */
  129.     @Override
  130.     @Deprecated
  131.     public double getNormalizedCnm(final double dateOffset, final int n, final int m)
  132.         throws OrekitException {
  133.         return onDate(getReferenceDate().shiftedBy(dateOffset)).getNormalizedCnm(n, m);
  134.     }

  135.     /** {@inheritDoc} */
  136.     @Override
  137.     @Deprecated
  138.     public double getNormalizedSnm(final double dateOffset, final int n, final int m)
  139.         throws OrekitException {
  140.         return onDate(getReferenceDate().shiftedBy(dateOffset)).getNormalizedSnm(n, m);
  141.     }

  142.     /** {@inheritDoc} */
  143.     @Override
  144.     public NormalizedSphericalHarmonics onDate(final AbsoluteDate date) throws OrekitException {

  145.         // computed Cnm and Snm coefficients
  146.         final double[][] cnm = new double[degree + 1][];
  147.         final double[][] snm = new double[degree + 1][];
  148.         for (int i = 0; i <= degree; ++i) {
  149.             final int m = FastMath.min(i, order) + 1;
  150.             cnm[i] = new double[m];
  151.             snm[i] = new double[m];
  152.         }

  153.         final BodiesElements bodiesElements = arguments.evaluateAll(date);
  154.         for (final OceanTidesWave wave : waves) {
  155.             wave.addContribution(bodiesElements, cnm, snm);
  156.         }

  157.         if (poleTideFunction != null && degree > 1 && order > 0) {
  158.             // add pole tide
  159.             poleTide(date, cnm, snm);
  160.         }

  161.         return new TideHarmonics(date, cnm, snm);

  162.     }

  163.     /** Update coefficients applying pole tide.
  164.      * @param date current date
  165.      * @param cnm the Cnm coefficients. Modified in place.
  166.      * @param snm the Snm coefficients. Modified in place.
  167.      */
  168.     private void poleTide(final AbsoluteDate date, final double[][] cnm, final double[][] snm) {
  169.         final double[] deltaCS = poleTideFunction.value(date);
  170.         cnm[2][1] += deltaCS[0]; // ΔC₂₁
  171.         snm[2][1] += deltaCS[1]; // ΔS₂₁
  172.     }

  173.     /** The Tidal geopotential evaluated on a specific date. */
  174.     private static class TideHarmonics implements NormalizedSphericalHarmonics {

  175.         /** evaluation date. */
  176.         private final AbsoluteDate date;

  177.         /** Cached cnm. */
  178.         private final double[][] cnm;

  179.         /** Cached snm. */
  180.         private final double[][] snm;

  181.         /** Construct the tidal harmonics on the given date.
  182.          *
  183.          * @param date of evaluation
  184.          * @param cnm the Cnm coefficients. Not copied.
  185.          * @param snm the Snm coeffiecients. Not copied.
  186.          */
  187.         private TideHarmonics(final AbsoluteDate date,
  188.                               final double[][] cnm,
  189.                               final double[][] snm) {
  190.             this.date = date;
  191.             this.cnm = cnm;
  192.             this.snm = snm;
  193.         }

  194.         /** {@inheritDoc} */
  195.         @Override
  196.         public AbsoluteDate getDate() {
  197.             return date;
  198.         }

  199.         /** {@inheritDoc} */
  200.         @Override
  201.         public double getNormalizedCnm(final int n, final int m)
  202.             throws OrekitException {
  203.             return cnm[n][m];
  204.         }

  205.         /** {@inheritDoc} */
  206.         @Override
  207.         public double getNormalizedSnm(final int n, final int m)
  208.             throws OrekitException {
  209.             return snm[n][m];
  210.         }

  211.     }

  212. }