composite_inte.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_COMPOSITE_INTE_H
00024 #define O2SCL_COMPOSITE_INTE_H
00025 
00026 #include <iostream>
00027 #include <o2scl/multi_inte.h>
00028 #include <o2scl/inte.h>
00029 #include <o2scl/funct.h>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034 
00035   /** 
00036       \brief Naive multi-dimensional integration over a hypercube
00037 
00038       Naively combine several one-dimensional integration objects from
00039       class inte in order to perform a multi-dimensional integration
00040       over a region defined by constant limits. For more general regions
00041       of integration, use children of the class \ref gen_inte.
00042 
00043       The integration routines are specified in the function
00044       set_ptrs().
00045 
00046       The integration routines are called in order of their
00047       specification in the list <tt>inte **ip</tt>. For the example of
00048       a two-dimensional integration <tt>ip[0]</tt> is called first
00049       with limits <tt>a[0]</tt> and <tt>b[0]</tt> and performs the
00050       integral of the integral given by <tt>ip[1]</tt> of the function
00051       from <tt>a[1]</tt> to <tt>b[1]</tt>. In other words, the
00052       integral performed is:
00053       \f[ 
00054       \int_{x_0=a_0}^{x_0=b_0} \int_{x_1=a_1}^{x_1=b_1} ...
00055       \int_{x_{\mathrm{n}-1}=a_{\mathrm{n}-1}}^
00056       {x_{\mathrm{n}-1}=b_{\mathrm{n}-1}} 
00057       f(x_0,x_1,...,x_{\mathrm{n}})
00058       \f]
00059       
00060       No error estimate is performed. Error estimation for multiple
00061       dimension integrals is provided by the Monte Carlo integration
00062       classes (see \ref mcarlo_inte).
00063   */
00064   template<class param_t, class func_t, class vec_t,
00065     class alloc_vec_t, class alloc_t> class composite_inte : 
00066   public multi_inte<param_t,func_t,vec_t> {
00067     
00068   public:
00069     
00070     /** 
00071         \brief Parameters to send to the 1-d integration functions
00072 
00073         This structure is not intended to be frequently used 
00074         directly by the class-user, but must be public so 
00075         that the 1-d integration objects can be specified.
00076      */
00077     typedef struct {
00078       /// The user-specified upper limits
00079       const vec_t *ax;
00080       /// The user-specified lower limits
00081       const vec_t *bx;
00082       /// The independent variable vector
00083       alloc_vec_t *cx;
00084       /// The user-specified function
00085       func_t *mf;
00086       /// The user-specified number of dimensions
00087       int ndim;
00088       /// The present recursion level
00089       int idim;
00090       /// The user-specified parameter
00091       param_t *vp;
00092     } od_parms;
00093       
00094     composite_inte() {
00095       ptrs_set=false;
00096       ndim=0;
00097       fmn=new funct_mfptr_noerr<composite_inte<param_t,func_t,
00098         vec_t,alloc_vec_t,alloc_t>,od_parms>
00099         (this,&composite_inte<param_t,func_t,vec_t,
00100          alloc_vec_t,alloc_t>::odfunc);
00101     }
00102     
00103     virtual ~composite_inte() {
00104       delete fmn;
00105     }
00106     
00107     /** 
00108         \brief Designate the pointers to the integration routines
00109         
00110         This function allows duplicate objects in this list in order
00111         to allow the user to use only one object for more than one of
00112         the integrations.
00113         
00114         If more 1-d integration routines than necessary are given,
00115         the extras will be unused.
00116     */
00117     int set_ptrs(inte<od_parms,funct<od_parms> > **ip, int n) {
00118       if (n<1) {
00119         set_err_ret("Number of dimensions less than 1 in set_ptrs().",
00120                     gsl_einval);
00121       }
00122       iptrs=ip;
00123       ndim=n;
00124       ptrs_set=true;
00125       return 0;
00126     }
00127       
00128     /* \brief Integrate function \c func over the hypercube from 
00129         \f$ x_i=a_i \f$ to \f$ x_i=b_i \f$ for 
00130         \f$ 0<i< \f$ ndim-1  
00131 
00132         The function set_ptrs() must be used first to set the 
00133         one-dimensional routines to use.
00134     */
00135     virtual double minteg(func_t &func, size_t n, const vec_t &a, 
00136                           const vec_t &b, param_t &pa) 
00137     {
00138       if (ptrs_set==false || n>ndim) {
00139         set_err("Too few objects specified with set_ptrs() in minteg().",
00140                 gsl_einval);
00141         return 0.0;
00142       }
00143 
00144       alloc_vec_t cx;
00145       ao.allocate(cx,n);
00146 
00147       od_parms op={&a,&b,&cx,&func,n,0,&pa};
00148         
00149       double res=iptrs[0]->integ(*fmn,a[0],b[0],op);
00150         
00151       ao.free(cx);
00152 
00153       return res;
00154 
00155     }
00156     
00157     /// Return string denoting type ("composite_inte")
00158     virtual const char *type() { return "composite_inte"; }
00159 
00160   protected:
00161 
00162 #ifndef DOXYGEN_INTERNAL
00163 
00164     /// Memory allocator for objects of type \c alloc_vec_t
00165     alloc_t ao;
00166 
00167     /// The one-dimensional integration function
00168     double odfunc(double x, od_parms &od) {
00169 
00170       double res;
00171         
00172       (*od.cx)[od.idim]=x;
00173       if (od.idim==od.ndim-1) {
00174         (*od.mf)(od.ndim,(*od.cx),res,*od.vp);
00175       } else {
00176         od_parms op2={od.ax,od.bx,od.cx,od.mf,od.ndim,od.idim+1,od.vp};
00177         res=iptrs[od.idim]->integ(*fmn,(*od.ax)[od.idim+1],
00178                                   (*od.bx)[od.idim+1],op2);
00179       }
00180       return res;
00181     }
00182     
00183     /// This function to send to the integrators
00184     funct_mfptr_noerr<composite_inte<param_t,func_t,vec_t,
00185       alloc_vec_t,alloc_t>,od_parms> *fmn;
00186 
00187     /// The number of dimensions
00188     size_t ndim;
00189 
00190     /// Pointers to the integration objects
00191     inte<od_parms,funct<od_parms> > **iptrs;
00192 
00193     /// True if the integration objects have been specified
00194     bool ptrs_set;
00195 
00196 #endif
00197 
00198   };
00199 
00200 #ifndef DOXYGENP
00201 }
00202 #endif
00203 
00204 #endif
00205 

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page