Simbody

Function.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_FUNCTION_H_
00002 #define SimTK_SimTKCOMMON_FUNCTION_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                         SimTK Core: SimTKcommon                            *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2008-10 Stanford University and the Authors.        *
00013  * Authors: Peter Eastman                                                     *
00014  * Contributors: Michael Sherman                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00035 // Note: this file was moved from Simmath to SimTKcommon 20100601; see the
00036 // Simmath repository for earlier history.
00037 
00038 #include "SimTKcommon/basics.h"
00039 #include "SimTKcommon/Simmatrix.h"
00040 #include <cassert>
00041 
00042 namespace SimTK {
00043 
00058 template <class T>
00059 class Function_ {
00060 public:
00061     class Constant;
00062     class Linear;
00063     class Polynomial;
00064     class Step;
00065     virtual ~Function_() {
00066     }
00073     virtual T calcValue(const Vector& x) const = 0;
00093     virtual T calcDerivative(const Array_<int>& derivComponents, 
00094                              const Vector&      x) const = 0;
00095 
00098     T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const 
00099     {   return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00100 
00104     virtual int getArgumentSize() const = 0;
00108     virtual int getMaxDerivativeOrder() const = 0;
00109 };
00110 
00113 typedef Function_<Real> Function;
00114 
00115 
00116 
00121 template <class T>
00122 class Function_<T>::Constant : public Function_<T> {
00123 public:
00131     explicit Constant(T value, int argumentSize=1) 
00132     :   argumentSize(argumentSize), value(value) {
00133     }
00134     T calcValue(const Vector& x) const {
00135         assert(x.size() == argumentSize);
00136         return value;
00137     }
00138     T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00139         return static_cast<T>(0);
00140     }
00141     virtual int getArgumentSize() const {
00142         return argumentSize;
00143     }
00144     int getMaxDerivativeOrder() const {
00145         return std::numeric_limits<int>::max();
00146     }
00147 
00150     T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const 
00151     {   return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00152 
00153 private:
00154     const int argumentSize;
00155     const T value;
00156 };
00157 
00162 template <class T>
00163 class Function_<T>::Linear : public Function_<T> {
00164 public:
00175     explicit Linear(const Vector_<T>& coefficients) : coefficients(coefficients) {
00176     }
00177     T calcValue(const Vector& x) const {
00178         assert(x.size() == coefficients.size()-1);
00179         T value = static_cast<T>(0);
00180         for (int i = 0; i < x.size(); ++i)
00181             value += x[i]*coefficients[i];
00182         value += coefficients[x.size()];
00183         return value;
00184     }
00185     T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00186         assert(x.size() == coefficients.size()-1);
00187         assert(derivComponents.size() > 0);
00188         if (derivComponents.size() == 1)
00189             return coefficients(derivComponents[0]);
00190         return static_cast<T>(0);
00191     }
00192     virtual int getArgumentSize() const {
00193         return coefficients.size()-1;
00194     }
00195     int getMaxDerivativeOrder() const {
00196         return std::numeric_limits<int>::max();
00197     }
00198 
00201     T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const 
00202     {   return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00203 private:
00204     const Vector_<T> coefficients;
00205 };
00206 
00207 
00212 template <class T>
00213 class Function_<T>::Polynomial : public Function_<T> {
00214 public:
00221     Polynomial(const Vector_<T>& coefficients) : coefficients(coefficients) {
00222     }
00223     T calcValue(const Vector& x) const {
00224         assert(x.size() == 1);
00225         Real arg = x[0];
00226         T value = static_cast<T>(0);
00227         for (int i = 0; i < coefficients.size(); ++i)
00228             value = value*arg + coefficients[i];
00229         return value;
00230     }
00231     T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00232         assert(x.size() == 1);
00233         assert(derivComponents.size() > 0);
00234         Real arg = x[0];
00235         T value = static_cast<T>(0);
00236         const int derivOrder = (int)derivComponents.size();
00237         const int polyOrder = coefficients.size()-1;
00238         for (int i = 0; i <= polyOrder-derivOrder; ++i) {
00239             T coeff = coefficients[i];
00240             for (int j = 0; j < derivOrder; ++j)
00241                 coeff *= polyOrder-i-j;
00242             value = value*arg + coeff;
00243         }
00244         return value;
00245     }
00246     virtual int getArgumentSize() const {
00247         return 1;
00248     }
00249     int getMaxDerivativeOrder() const {
00250         return std::numeric_limits<int>::max();
00251     }
00252 
00255     T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const 
00256     {   return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00257 private:
00258     const Vector_<T> coefficients;
00259 };
00260 
00268 template <class T>
00269 class Function_<T>::Step : public Function_<T> {
00270 public:
00288     Step(const T& y0, const T& y1, Real x0, Real x1) 
00289     :   m_y0(y0), m_y1(y1), m_yr(y1-y0), m_zero(Real(0)*y0),
00290         m_x0(x0), m_x1(x1), m_ooxr(1/(x1-x0)), m_sign(sign(m_ooxr)) 
00291     {   SimTK_ERRCHK1_ALWAYS(x0 != x1, "Function_<T>::Step::ctor()",
00292         "A zero-length switching interval is illegal; both ends were %g.", x0);
00293     }
00294 
00295     T calcValue(const Vector& xin) const {
00296         SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
00297             "Function_<T>::Step::calcValue()", 
00298             "Expected just one input argument but got %d.", xin.size());
00299 
00300         const Real x = xin[0];
00301         if ((x-m_x0)*m_sign <= 0) return m_y0;
00302         if ((x-m_x1)*m_sign >= 0) return m_y1;
00303         // f goes from 0 to 1 as x goes from x0 to x1.
00304         const Real f = stepAny(0,1,m_x0,m_ooxr, x);
00305         return m_y0 + f*m_yr;
00306     }
00307 
00308     T calcDerivative(const Array_<int>& derivComponents, const Vector& xin) const {
00309         SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
00310             "Function_<T>::Step::calcDerivative()", 
00311             "Expected just one input argument but got %d.", xin.size());
00312 
00313         const int derivOrder = (int)derivComponents.size();
00314         SimTK_ERRCHK1_ALWAYS(1 <= derivOrder && derivOrder <= 3,
00315             "Function_<T>::Step::calcDerivative()",
00316             "Only 1st, 2nd, and 3rd derivatives of the step are available,"
00317             " but derivative %d was requested.", derivOrder);
00318         const Real x = xin[0];
00319         if ((x-m_x0)*m_sign <= 0) return m_zero;
00320         if ((x-m_x1)*m_sign >= 0) return m_zero;
00321         switch(derivOrder) {
00322           case 1: return dstepAny (1,m_x0,m_ooxr, x) * m_yr;
00323           case 2: return d2stepAny(1,m_x0,m_ooxr, x) * m_yr;
00324           case 3: return d3stepAny(1,m_x0,m_ooxr, x) * m_yr;
00325           default: assert(!"impossible derivOrder");
00326         }
00327         return NaN*m_yr; /*NOTREACHED*/
00328     }
00329 
00330     virtual int getArgumentSize() const {return 1;}
00331     int getMaxDerivativeOrder() const {return 3;}
00332 
00335     T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const 
00336     {   return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00337 private:
00338     const T    m_y0, m_y1, m_yr;   // precalculate yr=(y1-y0)
00339     const T    m_zero;             // precalculate T(0)
00340     const Real m_x0, m_x1, m_ooxr; // precalculate ooxr=1/(x1-x0)
00341     const Real m_sign;             // sign(x1-x0) is 1 or -1
00342 };
00343 
00344 } // namespace SimTK
00345 
00346 #endif // SimTK_SimTKCOMMON_FUNCTION_H_
00347 
00348 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines