HarmonicOscillator.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF 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.apache.commons.math3.analysis.function;

  18. import org.apache.commons.math3.analysis.DifferentiableUnivariateFunction;
  19. import org.apache.commons.math3.analysis.FunctionUtils;
  20. import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
  21. import org.apache.commons.math3.analysis.UnivariateFunction;
  22. import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
  23. import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
  24. import org.apache.commons.math3.exception.DimensionMismatchException;
  25. import org.apache.commons.math3.exception.NullArgumentException;
  26. import org.apache.commons.math3.util.FastMath;

  27. /**
  28.  * <a href="http://en.wikipedia.org/wiki/Harmonic_oscillator">
  29.  *  simple harmonic oscillator</a> function.
  30.  *
  31.  * @since 3.0
  32.  */
  33. public class HarmonicOscillator implements UnivariateDifferentiableFunction, DifferentiableUnivariateFunction {
  34.     /** Amplitude. */
  35.     private final double amplitude;
  36.     /** Angular frequency. */
  37.     private final double omega;
  38.     /** Phase. */
  39.     private final double phase;

  40.     /**
  41.      * Harmonic oscillator function.
  42.      *
  43.      * @param amplitude Amplitude.
  44.      * @param omega Angular frequency.
  45.      * @param phase Phase.
  46.      */
  47.     public HarmonicOscillator(double amplitude,
  48.                               double omega,
  49.                               double phase) {
  50.         this.amplitude = amplitude;
  51.         this.omega = omega;
  52.         this.phase = phase;
  53.     }

  54.     /** {@inheritDoc} */
  55.     public double value(double x) {
  56.         return value(omega * x + phase, amplitude);
  57.     }

  58.     /** {@inheritDoc}
  59.      * @deprecated as of 3.1, replaced by {@link #value(DerivativeStructure)}
  60.      */
  61.     @Deprecated
  62.     public UnivariateFunction derivative() {
  63.         return FunctionUtils.toDifferentiableUnivariateFunction(this).derivative();
  64.     }

  65.     /**
  66.      * Parametric function where the input array contains the parameters of
  67.      * the harmonic oscillator function, ordered as follows:
  68.      * <ul>
  69.      *  <li>Amplitude</li>
  70.      *  <li>Angular frequency</li>
  71.      *  <li>Phase</li>
  72.      * </ul>
  73.      */
  74.     public static class Parametric implements ParametricUnivariateFunction {
  75.         /**
  76.          * Computes the value of the harmonic oscillator at {@code x}.
  77.          *
  78.          * @param x Value for which the function must be computed.
  79.          * @param param Values of norm, mean and standard deviation.
  80.          * @return the value of the function.
  81.          * @throws NullArgumentException if {@code param} is {@code null}.
  82.          * @throws DimensionMismatchException if the size of {@code param} is
  83.          * not 3.
  84.          */
  85.         public double value(double x, double ... param)
  86.             throws NullArgumentException,
  87.                    DimensionMismatchException {
  88.             validateParameters(param);
  89.             return HarmonicOscillator.value(x * param[1] + param[2], param[0]);
  90.         }

  91.         /**
  92.          * Computes the value of the gradient at {@code x}.
  93.          * The components of the gradient vector are the partial
  94.          * derivatives of the function with respect to each of the
  95.          * <em>parameters</em> (amplitude, angular frequency and phase).
  96.          *
  97.          * @param x Value at which the gradient must be computed.
  98.          * @param param Values of amplitude, angular frequency and phase.
  99.          * @return the gradient vector at {@code x}.
  100.          * @throws NullArgumentException if {@code param} is {@code null}.
  101.          * @throws DimensionMismatchException if the size of {@code param} is
  102.          * not 3.
  103.          */
  104.         public double[] gradient(double x, double ... param)
  105.             throws NullArgumentException,
  106.                    DimensionMismatchException {
  107.             validateParameters(param);

  108.             final double amplitude = param[0];
  109.             final double omega = param[1];
  110.             final double phase = param[2];

  111.             final double xTimesOmegaPlusPhase = omega * x + phase;
  112.             final double a = HarmonicOscillator.value(xTimesOmegaPlusPhase, 1);
  113.             final double p = -amplitude * FastMath.sin(xTimesOmegaPlusPhase);
  114.             final double w = p * x;

  115.             return new double[] { a, w, p };
  116.         }

  117.         /**
  118.          * Validates parameters to ensure they are appropriate for the evaluation of
  119.          * the {@link #value(double,double[])} and {@link #gradient(double,double[])}
  120.          * methods.
  121.          *
  122.          * @param param Values of norm, mean and standard deviation.
  123.          * @throws NullArgumentException if {@code param} is {@code null}.
  124.          * @throws DimensionMismatchException if the size of {@code param} is
  125.          * not 3.
  126.          */
  127.         private void validateParameters(double[] param)
  128.             throws NullArgumentException,
  129.                    DimensionMismatchException {
  130.             if (param == null) {
  131.                 throw new NullArgumentException();
  132.             }
  133.             if (param.length != 3) {
  134.                 throw new DimensionMismatchException(param.length, 3);
  135.             }
  136.         }
  137.     }

  138.     /**
  139.      * @param xTimesOmegaPlusPhase {@code omega * x + phase}.
  140.      * @param amplitude Amplitude.
  141.      * @return the value of the harmonic oscillator function at {@code x}.
  142.      */
  143.     private static double value(double xTimesOmegaPlusPhase,
  144.                                 double amplitude) {
  145.         return amplitude * FastMath.cos(xTimesOmegaPlusPhase);
  146.     }

  147.     /** {@inheritDoc}
  148.      * @since 3.1
  149.      */
  150.     public DerivativeStructure value(final DerivativeStructure t)
  151.         throws DimensionMismatchException {
  152.         final double x = t.getValue();
  153.         double[] f = new double[t.getOrder() + 1];

  154.         final double alpha = omega * x + phase;
  155.         f[0] = amplitude * FastMath.cos(alpha);
  156.         if (f.length > 1) {
  157.             f[1] = -amplitude * omega * FastMath.sin(alpha);
  158.             final double mo2 = - omega * omega;
  159.             for (int i = 2; i < f.length; ++i) {
  160.                 f[i] = mo2 * f[i - 2];
  161.             }
  162.         }

  163.         return t.compose(f);

  164.     }

  165. }