![]() |
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_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 /** \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 1-dimensional integration routines are specified in the function 00044 set_oned_inte(). 00045 00046 The integration routines are called in order of the index 00047 specified in the function set_oned_inte(). For 00048 <tt>n-</tt>dimensional integration, <tt>n</tt> one-dimensional 00049 integration objects should be specified, with indexes <tt>0</tt> 00050 through <tt>n-1</tt>. The integration routines are called in 00051 order of their index, so that the outermost integration is done 00052 by the routine specified with index 0. 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 \future Create a function to set an entire array of 00065 one-dimensional integration objects at once 00066 */ 00067 template<class func_t=multi_funct<>, 00068 class vec_t=ovector_base, class alloc_vec_t=ovector, 00069 class alloc_t=ovector_alloc> class composite_inte : 00070 public multi_inte<func_t,vec_t> { 00071 00072 #ifndef DOXYGEN_INTERNAL 00073 00074 protected: 00075 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 size_t ndim; 00086 00087 #endif 00088 00089 public: 00090 00091 composite_inte() { 00092 nint=0; 00093 max_dim=100; 00094 } 00095 00096 virtual ~composite_inte() { 00097 if (nint>0) { 00098 delete[] iptrs; 00099 delete[] tptrs; 00100 } 00101 } 00102 00103 /** \brief Set the one-dimensional integration object with 00104 index \c i. 00105 */ 00106 int set_oned_inte(inte<funct> &it, size_t i) { 00107 00108 if (i>=max_dim) { 00109 O2SCL_ERR_RET("Index >= max_dim in composite_inte::set_oned_inte().", 00110 gsl_einval); 00111 } 00112 00113 if (nint==0) { 00114 00115 // Create new space 00116 nint=i+1; 00117 iptrs=new inte<funct> *[nint]; 00118 tptrs=new bool[nint]; 00119 00120 } else if (i>nint-1) { 00121 00122 // Create new space and copy old info over 00123 size_t nint_new=i+1; 00124 00125 inte<funct> **iptrs_new=new inte<funct> *[nint_new]; 00126 bool *tptrs_new=new bool[nint_new]; 00127 00128 for(size_t j=0;j<nint;j++) { 00129 iptrs_new[j]=iptrs[j]; 00130 tptrs_new[j]=tptrs[j]; 00131 } 00132 00133 delete[] iptrs; 00134 delete[] tptrs; 00135 00136 iptrs=iptrs_new; 00137 tptrs=tptrs_new; 00138 nint=nint_new; 00139 00140 } 00141 00142 iptrs[i]=⁢ 00143 tptrs[i]=true; 00144 00145 return gsl_success; 00146 } 00147 00148 /** \brief Integrate function \c func over the hypercube from 00149 \f$ x_i=a_i \f$ to \f$ x_i=b_i \f$ for 00150 \f$ 0<i< \f$ ndim-1 00151 00152 The function set_oned_inte() must be used first to set the 00153 one-dimensional routines to use. 00154 */ 00155 virtual int minteg_err(func_t &func, size_t n, const vec_t &a, 00156 const vec_t &b, double &res, double &err) { 00157 err=0.0; 00158 00159 // Test to make sure the 1-d integrators were set 00160 bool enough_oned=true; 00161 if (n>nint) enough_oned=false; 00162 for(size_t i=0;i<n;i++) { 00163 if (tptrs[i]==false) enough_oned=false; 00164 } 00165 00166 if (enough_oned==false) { 00167 O2SCL_ERR_RET("Too few objects specified with set_ptrs() in minteg().", 00168 gsl_einval); 00169 } 00170 00171 // Perform integration 00172 alloc_vec_t c; 00173 ao.allocate(c,n); 00174 00175 ax=&a; 00176 bx=&b; 00177 cx=&c; 00178 mf=&func; 00179 ndim=n; 00180 size_t ix=0; 00181 00182 funct_mfptr_param<composite_inte<func_t,vec_t, 00183 alloc_vec_t,alloc_t>,size_t> 00184 fmn(this,&composite_inte<func_t,vec_t,alloc_vec_t,alloc_t>::odfunc, 00185 ix); 00186 00187 res=iptrs[0]->integ(fmn,a[0],b[0]); 00188 00189 ao.free(c); 00190 00191 return gsl_success; 00192 00193 } 00194 00195 /// Return string denoting type ("composite_inte") 00196 virtual const char *type() { return "composite_inte"; } 00197 00198 /// The maxiumum number of integration dimensions (default 100) 00199 size_t max_dim; 00200 00201 protected: 00202 00203 #ifndef DOXYGEN_INTERNAL 00204 00205 /// Memory allocator for objects of type \c alloc_vec_t 00206 alloc_t ao; 00207 00208 /// The one-dimensional integration function 00209 double odfunc(double x, size_t &ix) { 00210 00211 double res; 00212 00213 (*cx)[ix]=x; 00214 if (ix==ndim-1) { 00215 res=(*mf)(ndim,(*cx)); 00216 } else { 00217 size_t ix_next=ix+1; 00218 00219 /// This function to send to the integrators 00220 funct_mfptr_param<composite_inte<func_t,vec_t, 00221 alloc_vec_t,alloc_t>,size_t> 00222 fmn(this,&composite_inte<func_t,vec_t,alloc_vec_t,alloc_t>::odfunc, 00223 ix_next); 00224 00225 res=iptrs[ix]->integ(fmn,(*ax)[ix+1],(*bx)[ix+1]); 00226 } 00227 return res; 00228 } 00229 00230 /// The size of the integration object arrays 00231 size_t nint; 00232 00233 /// Pointers to the integration objects 00234 inte<funct> **iptrs; 00235 00236 /// Flag indicating if integration object has been set 00237 bool *tptrs; 00238 00239 #endif 00240 00241 }; 00242 00243 #ifndef DOXYGENP 00244 } 00245 #endif 00246 00247 #endif 00248
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).