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