00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 #include <o2scl/multi_funct.h> 00031 00032 #ifndef DOXYGENP 00033 namespace o2scl { 00034 #endif 00035 00036 /** 00037 \brief Naive multi-dimensional integration over a hypercube 00038 00039 Naively combine several one-dimensional integration objects from 00040 class inte in order to perform a multi-dimensional integration 00041 over a region defined by constant limits. For more general regions 00042 of integration, use children of the class \ref gen_inte. 00043 00044 The 1-dimensional integration routines are specified in the function 00045 set_oned_inte(). 00046 00047 The integration routines are called in order of the index 00048 specified in the function set_oned_inte(). For 00049 <tt>n-</tt>dimensional integration, <tt>n</tt> one-dimensional 00050 integration objects should be specified, with indexes <tt>0</tt> 00051 through <tt>n-1</tt>. The integration routines are called in 00052 order of their index, so that the outermost integration is done 00053 by the routine specified with index 0. 00054 \f[ 00055 \int_{x_0=a_0}^{x_0=b_0} \int_{x_1=a_1}^{x_1=b_1} ... 00056 \int_{x_{\mathrm{n}-1}=a_{\mathrm{n}-1}}^ 00057 {x_{\mathrm{n}-1}=b_{\mathrm{n}-1}} 00058 f(x_0,x_1,...,x_{\mathrm{n}}) 00059 \f] 00060 00061 No error estimate is performed. Error estimation for multiple 00062 dimension integrals is provided by the Monte Carlo integration 00063 classes (see \ref mcarlo_inte). 00064 00065 \future Create a function to set an entire array of 00066 one-dimensional integration objects at once 00067 */ 00068 template<class param_t, class func_t=multi_funct<param_t>, 00069 class vec_t=ovector_base, class alloc_vec_t=ovector, 00070 class alloc_t=ovector_alloc> class composite_inte : 00071 public multi_inte<param_t,func_t,vec_t> { 00072 00073 #ifndef DOXYGEN_INTERNAL 00074 00075 protected: 00076 00077 /// The user-specified upper limits 00078 const vec_t *ax; 00079 /// The user-specified lower limits 00080 const vec_t *bx; 00081 /// The independent variable vector 00082 alloc_vec_t *cx; 00083 /// The user-specified function 00084 func_t *mf; 00085 /// The user-specified number of dimensions 00086 size_t ndim; 00087 /// The user-specified parameter 00088 param_t *vp; 00089 00090 #endif 00091 00092 public: 00093 00094 composite_inte() { 00095 nint=0; 00096 fmn=new funct_mfptr_noerr<composite_inte<param_t,func_t, 00097 vec_t,alloc_vec_t,alloc_t>,size_t> 00098 (this,&composite_inte<param_t,func_t,vec_t, 00099 alloc_vec_t,alloc_t>::odfunc); 00100 max_dim=100; 00101 } 00102 00103 virtual ~composite_inte() { 00104 if (nint>0) { 00105 delete[] iptrs; 00106 delete[] tptrs; 00107 } 00108 delete fmn; 00109 } 00110 00111 /** \brief Set the one-dimensional integration object with 00112 index \c i. 00113 */ 00114 int set_oned_inte(inte<size_t> &it, size_t i) { 00115 00116 if (i>=max_dim) { 00117 O2SCL_ERR_RET("Index >= max_dim in composite_inte::set_oned_inte().", 00118 gsl_einval); 00119 } 00120 00121 if (nint==0) { 00122 00123 // Create new space 00124 nint=i+1; 00125 iptrs=new inte<size_t > *[nint]; 00126 tptrs=new bool[nint]; 00127 00128 } else if (i>nint-1) { 00129 00130 // Create new space and copy old info over 00131 size_t nint_new=i+1; 00132 00133 inte<size_t > **iptrs_new= 00134 new inte<size_t > *[nint_new]; 00135 bool *tptrs_new=new bool[nint_new]; 00136 00137 for(size_t j=0;j<nint;j++) { 00138 iptrs_new[j]=iptrs[j]; 00139 tptrs_new[j]=tptrs[j]; 00140 } 00141 00142 delete[] iptrs; 00143 delete[] tptrs; 00144 00145 iptrs=iptrs_new; 00146 tptrs=tptrs_new; 00147 nint=nint_new; 00148 00149 } 00150 00151 iptrs[i]=⁢ 00152 tptrs[i]=true; 00153 00154 return gsl_success; 00155 } 00156 00157 /* \brief Integrate function \c func over the hypercube from 00158 \f$ x_i=a_i \f$ to \f$ x_i=b_i \f$ for 00159 \f$ 0<i< \f$ ndim-1 00160 00161 The function set_oned_inte() must be used first to set the 00162 one-dimensional routines to use. 00163 */ 00164 virtual int minteg_err(func_t &func, size_t n, const vec_t &a, 00165 const vec_t &b, param_t &pa, double &res, 00166 double &err) { 00167 err=0.0; 00168 00169 // Test to make sure the 1-d integrators were set 00170 bool enough_oned=true; 00171 if (n>nint) enough_oned=false; 00172 for(size_t i=0;i<n;i++) { 00173 if (tptrs[i]==false) enough_oned=false; 00174 } 00175 00176 if (enough_oned==false) { 00177 O2SCL_ERR_RET("Too few objects specified with set_ptrs() in minteg().", 00178 gsl_einval); 00179 } 00180 00181 // Perform integration 00182 alloc_vec_t c; 00183 ao.allocate(c,n); 00184 00185 ax=&a; 00186 bx=&b; 00187 cx=&c; 00188 mf=&func; 00189 ndim=n; 00190 vp=&pa; 00191 size_t ix=0; 00192 00193 res=iptrs[0]->integ(*fmn,a[0],b[0],ix); 00194 00195 ao.free(c); 00196 00197 return gsl_success; 00198 00199 } 00200 00201 /// Return string denoting type ("composite_inte") 00202 virtual const char *type() { return "composite_inte"; } 00203 00204 /// The maxiumum number of integration dimensions (default 100) 00205 size_t max_dim; 00206 00207 protected: 00208 00209 #ifndef DOXYGEN_INTERNAL 00210 00211 /// Memory allocator for objects of type \c alloc_vec_t 00212 alloc_t ao; 00213 00214 /// The one-dimensional integration function 00215 double odfunc(double x, size_t &ix) { 00216 00217 double res; 00218 00219 (*cx)[ix]=x; 00220 if (ix==ndim-1) { 00221 (*mf)(ndim,(*cx),res,*vp); 00222 } else { 00223 size_t ix_next=ix+1; 00224 res=iptrs[ix]->integ(*fmn,(*ax)[ix+1],(*bx)[ix+1],ix_next); 00225 } 00226 return res; 00227 } 00228 00229 /// This function to send to the integrators 00230 funct_mfptr_noerr<composite_inte<param_t,func_t,vec_t, 00231 alloc_vec_t,alloc_t>,size_t> *fmn; 00232 00233 /// The size of the integration object arrays 00234 size_t nint; 00235 00236 /// Pointers to the integration objects 00237 inte<size_t> **iptrs; 00238 00239 /// Flag indicating if integration object has been set 00240 bool *tptrs; 00241 00242 #endif 00243 00244 }; 00245 00246 #ifndef DOXYGENP 00247 } 00248 #endif 00249 00250 #endif 00251
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page