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 inte **ip. For the example of a
00048       two-dimensional integration ip[0] is called first with limits a[0]
00049       and b[0] and performs the integral of the integral given by ip[1]
00050       of the function from a[1] to b[1]. In other words, the integral
00051       performed is:
00052       \f[ 
00053       \int_{x_0=a_0}^{x_0=b_0} \int_{x_1=a_1}^{x_1=b_1} ...
00054       \int_{x_{\mathrm{n}-1}=a_{\mathrm{n}-1}}^
00055       {x_{\mathrm{n}-1}=b_{\mathrm{n}-1}} 
00056       f(x_0,x_1,...,x_{\mathrm{n}})
00057       \f]
00058 
00059       No error estimate is performed.
00060 
00061   */
00062   template<class param_t, class func_t, class vec_t,
00063     class alloc_vec_t, class alloc_t> class composite_inte : 
00064   public multi_inte<param_t,func_t,vec_t> {
00065     
00066   public:
00067     
00068     /** 
00069         \brief Parameters to send to the 1-d integration functions
00070 
00071         This structure is not intended to be frequently used 
00072         directly by the class-user, but must be public so 
00073         that the 1-d integration objects can be specified.
00074      */
00075     typedef struct {
00076       /// The user-specified upper limits
00077       const vec_t *ax;
00078       /// The user-specified lower limits
00079       const vec_t *bx;
00080       /// The independent variable vector
00081       alloc_vec_t *cx;
00082       /// The user-specified function
00083       func_t *mf;
00084       /// The user-specified number of dimensions
00085       int ndim;
00086       /// The present recursion level
00087       int idim;
00088       /// The user-specified parameter
00089       param_t *vp;
00090     } od_parms;
00091       
00092     composite_inte() {
00093       ptrs_set=false;
00094       ndim=0;
00095       fmn=new funct_mfptr_noerr<composite_inte<param_t,func_t,
00096         vec_t,alloc_vec_t,alloc_t>,od_parms>
00097         (this,&composite_inte<param_t,func_t,vec_t,
00098          alloc_vec_t,alloc_t>::odfunc);
00099     }
00100     
00101     virtual ~composite_inte() {
00102       delete fmn;
00103     }
00104     
00105     /** 
00106         \brief Designate the pointers to the integration routines
00107         
00108         This function allows duplicate objects in this list in order
00109         to allow the user to use only one object for more than one of
00110         the integrations.
00111         
00112         If more 1-d integration routines than necessary are given,
00113         the extras will be unused.
00114     */
00115     int set_ptrs(inte<od_parms,funct<od_parms> > **ip, int n) {
00116       if (n<1) {
00117         set_err_ret("Number of dimensions less than 1 in set_ptrs().",
00118                     gsl_einval);
00119       }
00120       iptrs=ip;
00121       ndim=n;
00122       ptrs_set=true;
00123       return 0;
00124     }
00125       
00126     /* \brief Integrate function \c func over the hypercube from 
00127         \f$ x_i=a_i \f$ to \f$ x_i=b_i \f$ for 
00128         \f$ 0<i< \f$ ndim-1  
00129 
00130         The function set_ptrs() must be used first to set the 
00131         one-dimensional routines to use.
00132     */
00133     virtual double minteg(func_t &func, size_t n, const vec_t &a, 
00134                           const vec_t &b, param_t &pa) 
00135     {
00136       if (ptrs_set==false || n>ndim) {
00137         set_err("Too few objects specified with set_ptrs() in minteg().",
00138                 gsl_einval);
00139         return 0.0;
00140       }
00141 
00142       alloc_vec_t cx;
00143       ao.allocate(cx,n);
00144 
00145       od_parms op={&a,&b,&cx,&func,n,0,&pa};
00146         
00147       double res=iptrs[0]->integ(*fmn,a[0],b[0],op);
00148         
00149       ao.free(cx);
00150 
00151       return res;
00152 
00153     }
00154     
00155     /// Return string denoting type ("composite_inte")
00156     virtual const char *type() { return "composite_inte"; }
00157 
00158   protected:
00159 
00160 #ifndef DOXYGEN_INTERNAL
00161 
00162     /// Memory allocator for objects of type \c alloc_vec_t
00163     alloc_t ao;
00164 
00165     /// The one-dimensional integration function
00166     double odfunc(double x, od_parms &od) {
00167 
00168       double res;
00169         
00170       (*od.cx)[od.idim]=x;
00171       if (od.idim==od.ndim-1) {
00172         (*od.mf)(od.ndim,(*od.cx),res,*od.vp);
00173       } else {
00174         od_parms op2={od.ax,od.bx,od.cx,od.mf,od.ndim,od.idim+1,od.vp};
00175         res=iptrs[od.idim]->integ(*fmn,(*od.ax)[od.idim+1],
00176                                   (*od.bx)[od.idim+1],op2);
00177       }
00178       return res;
00179     }
00180     
00181     /// This function to send to the integrators
00182     funct_mfptr_noerr<composite_inte<param_t,func_t,vec_t,
00183       alloc_vec_t,alloc_t>,od_parms> *fmn;
00184 
00185     /// The number of dimensions
00186     size_t ndim;
00187 
00188     /// Pointers to the integration objects
00189     inte<od_parms,funct<od_parms> > **iptrs;
00190 
00191     /// True if the integration objects have been specified
00192     bool ptrs_set;
00193 
00194 #endif
00195 
00196   };
00197 
00198 #ifndef DOXYGENP
00199 }
00200 #endif
00201 
00202 #endif
00203 

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