org.orekit.forces.gravity.AssociatedLegendreFunction.java Source code

Java tutorial

Introduction

Here is the source code for org.orekit.forces.gravity.AssociatedLegendreFunction.java

Source

/* Copyright 2002-2015 CS Systmes d'Information
 * Licensed to CS Systmes d'Information (CS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * CS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.orekit.forces.gravity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.dfp.Dfp;
import org.apache.commons.math3.dfp.DfpField;

/** Implementation of associated Legendre functions from defining formulas.
 * <p>
 * This implementation is for test purposes only! It is limited to low degrees
 * and order and is slow.
 * </p>
 * @author Luc Maisonobe
 */
class AssociatedLegendreFunction {

    static final Map<Integer, List<Dfp[]>> LEGENDRE_POLYNOMIALS = new HashMap<Integer, List<Dfp[]>>();
    final int m;
    final Dfp[] polynomial;
    final Dfp normalization;

    private Dfp[] getLegendrePolynomial(int n, DfpField dfpField) {

        // get (or create) the list of polynomials for the specified field
        List<Dfp[]> list = LEGENDRE_POLYNOMIALS.get(dfpField.getRadixDigits());
        if (list == null) {
            list = new ArrayList<Dfp[]>();
            list.add(new Dfp[] { dfpField.getOne() // P0(X) = 1
            });
            list.add(new Dfp[] { dfpField.getZero(), dfpField.getOne() // P1(X) = 0 + 1 * X
            });
        }

        while (list.size() <= n) {

            // build polynomial Pk+1 using recursion formula
            // (k+1) P<sub>k+1</sub>(X) = (2k+1) X P<sub>k</sub>(X) - k P<sub>k-1</sub>(X)
            int k = list.size() - 1;
            Dfp kDfp = dfpField.newDfp(k);
            Dfp kP1Dfp = kDfp.add(dfpField.getOne());
            Dfp ckDfp = kP1Dfp.add(kDfp).divide(kP1Dfp);
            Dfp[] pk = list.get(k);
            Dfp ckM1Dfp = kDfp.divide(kP1Dfp).negate();
            Dfp[] pkM1 = list.get(k - 1);

            Dfp[] pkP1 = new Dfp[k + 2];
            pkP1[0] = ckM1Dfp.multiply(pkM1[0]);
            for (int i = 0; i < k; ++i) {
                if ((k - i) % 2 == 1) {
                    pkP1[i + 1] = dfpField.getZero();
                } else {
                    pkP1[i + 1] = ckDfp.multiply(pk[i]).add(ckM1Dfp.multiply(pkM1[i + 1]));
                }
            }
            pkP1[k + 1] = ckDfp.multiply(pk[k]);

            list.add(pkP1);

        }

        // retrieve degree n polynomial
        return list.get(n);

    }

    private Dfp[] differentiateLegendrePolynomial(Dfp[] p, int m, DfpField dfpField) {
        Dfp[] dp = new Dfp[p.length - m];
        for (int i = 0; i < dp.length; ++i) {
            dp[i] = p[i + m];
            for (int j = m; j > 0; --j) {
                dp[i] = dp[i].multiply(dfpField.newDfp(i + j));
            }
        }
        return dp;
    }

    public AssociatedLegendreFunction(boolean normalized, int n, int m, DfpField dfpField) {

        this.m = m;

        // store mth derivative of the degree n Legendre polynomial
        polynomial = differentiateLegendrePolynomial(getLegendrePolynomial(n, dfpField), m, dfpField);

        if (normalized) {
            // compute normalization coefficient
            Dfp c = dfpField.newDfp(((m == 0) ? 1.0 : 2.0) * (2 * n + 1));
            for (int k = 0; k < m; ++k) {
                c = c.divide(dfpField.newDfp((n + 1 + k) * (n - k)));
            }
            this.normalization = c.sqrt();
        } else {
            this.normalization = dfpField.getOne();
        }

    }

    public DerivativeStructure value(DerivativeStructure t) {
        DerivativeStructure y1 = t.getField().getOne().multiply(polynomial[polynomial.length - 1].toDouble());
        for (int j = polynomial.length - 2; j >= 0; j--) {
            y1 = y1.multiply(t).add(polynomial[j].toDouble());
        }
        DerivativeStructure oneMinusT2 = t.getField().getOne().subtract(t.multiply(t));
        DerivativeStructure y2 = oneMinusT2.pow(m).sqrt();
        return y1.multiply(y2).multiply(normalization.toDouble());
    }

    public Dfp value(Dfp t) {
        Dfp y1 = polynomial[polynomial.length - 1];
        for (int j = polynomial.length - 2; j >= 0; j--) {
            y1 = y1.multiply(t).add(polynomial[j]);
        }
        Dfp oneMinusT2 = t.getField().getOne().subtract(t.multiply(t));
        Dfp y2 = t.getField().getOne();
        for (int j = 0; j < m; ++j) {
            y2 = y2.multiply(oneMinusT2);
        }
        y2 = y2.sqrt();
        return y1.multiply(y2).multiply(normalization);
    }

}