/** * 2D trapezoidal integration */ float trapzd2d(Func2D *func, float x1, float x2, float y1, float y2, int n) { TrapezFunc2D trapezFunc2D( func, x1, x2 ); return trapzd( &trapezFunc2D, n, y1, y2, n ); }
double qromb(double (*funcd)(), double es, double Wind, double AirDens, double ZO, double EactAir, double F, double hsalt, double phi_r, double ushear, double Zrh, double a, double b) // Returns the integral of the function func from a to b. Integration is performed // by Romberg's method: Numerical Recipes in C Section 4.3 { void polint(double xa[], double ya[], int n, double x, double *y, double *dy); double trapzd(double (*funcd)(), double es, double Wind, double AirDens, double ZO, double EactAir, double F, double hsalt, double phi_r, double ushear, double Zrh, double a, double b, int n); double ss, dss; double s[MAX_ITER+1], h[MAX_ITER+2]; int j; h[1] = 1.0; for(j=1; j<=MAX_ITER; j++) { s[j]=trapzd(funcd,es, Wind, AirDens, ZO, EactAir, F, hsalt, phi_r, ushear, Zrh, a,b,j); if(j >= K) { polint(&h[j-K],&s[j-K],K,0.0,&ss,&dss); if (fabs(dss) <= MACHEPS*fabs(ss)) return ss; } h[j+1]=0.25*h[j]; } nrerror("Too many steps in routine qromb"); return 0.0; }
double CMesh::qromb(meshMemFunc mf, double a, double b) { const int JMAX=20, JMAXP=JMAX+1, K=5; const double EPS=1E-10; double ss, dss; std::vector<double> s, h, s_t, h_t; int i,j; h.push_back(1.0); for (j=1;j<=JMAX;j++){ s.push_back(trapzd(mf,a,b,j)); if (j>=K){ for (i=0;i<K;i++){ h_t.push_back(h[j-K+i]); s_t.push_back(s[j-K+i]); } polint(h_t,s_t,0.0,ss,dss); if (fabs(dss) <= EPS*fabs(ss)) { return ss; } h_t.clear(); s_t.clear(); } h.push_back(0.25*h[j-1]); } fprintf(stderr,"Too many steps in routine qromb\n"); exit(1); return 0.0; }
template < class T > T qtrap(T (* func) (T), T a, T b ) { /* Integrira funkciju 'func' koristeæi trapezoidalno pravilo NINETGR_EPS - željena relativna toènost JMAX - max. broj koraka */ int j; T s, olds; olds = T(-1.e30); for( j=1; j<=JMAX; j++ ) { s = trapzd(func,a,b,j); if( fabs(s-olds) < NINTEGR_EPS*fabs(olds) ) return s; if( s == 0.0 && olds == 0.0 && j > 6 ) return s; olds = s; } printf("To many steps in NIntegrate !!!"); return T(); }
main(){ int count,n; double y1, y2, y3; printf("Numerical integration using Trapzoidal rule\n"); printf("1: 1/(1+0.5*cos(x)) from 0 to pi\n"); printf("2: x*log(abs(x)) from 0 to 1 \n"); printf("3: sin(x) from 0 to pi \n\n"); printf("%10s %15s %15s %19s\n","n","y1","y2","sin(x)"); n=1; for (count=0; count<10; count++){ n *=2; y1=trapzd(fun1, 0.0, M_PI, n); y2=trapzd(fun2, 0.0, 1.0, n); y3=trapzd(sin, 0.0, M_PI, n); printf("%10d \t %12.4f\t %12.4f\t %12.4f\n",n, y1, y2, y3); } system("pause"); }
void initialize_global() { real yo = 0; real dy = YMAX/NG; g[0] = 0; for (int i = 1; i <= NG; i++) { real y = yo + dy; g[i] = g[i-1] + trapzd(gaus2, yo, y, EPS); yo = y; } }
int main(void) { int i; float a=0.0,b=PIO2,s; printf("\nIntegral of func with 2^(n-1) points\n"); printf("Actual value of integral is %10.6f\n",fint(b)-fint(a)); printf("%6s %24s\n","n","approx. integral"); for (i=1;i<=NMAX;i++) { s=trapzd(func,a,b,i); printf("%6d %20.6f\n",i,s); } return 0; }
double qromb(double (*func)(double), double a, double b, double eps, int imax) { double ss = 0; double dss; int i; /* allocate enough storage */ if (imax+1 > nmax) { #ifdef DEBUG (void)fprintf(stdout, "qromb: malloc %d cells %d bytes\n", imax+1, (imax+1) * sizeof(double)); #endif if (h != NULL) { free(h); } h = (double *)malloc((imax+1) * sizeof(double)); if (s != NULL) { free(s); } s = (double *)malloc((imax+1) * sizeof(double)); nmax = imax+1; } h[0] = 1; for (i = 0; i < imax; i++) { s[i] = trapzd(func, a, b, i); if (i >= K-1) { ss = polint(&h[i-(K-1)], &s[i-(K-1)], K, 0.0, &dss); #ifdef DEBUG (void)fprintf(stdout, "qromb: a %.15e b %.15e i %d ss %.15e dss %.15e eps %.15e\n", a, b, i, ss, dss, eps); #endif if (fabs(dss) < eps * fabs(ss)) { return(ss); } } h[i+1] = 0.25 * h[i]; s[i+1] = s[i]; } #ifdef DEBUG (void)fprintf(stdout, "qromb: a %.15e b %.15e i %d ss %.15e\n", a, b, i, ss); #endif return(ss); }
float qsimp(float (*func)(float), float a, float b) { int j; float s,st,ost=0.0,os=0.0; for (j=1;j<=JMAX;j++){ st=trapzd(func,a,b,j); s=(4.0*st-ost)/3.0; if (j > 5) if (fabs(s-os) < EPS*fabs(os) || (s == 0.0 && os == 0.0)) return s; os=s; ost=st; } error("Too many steps in routine qsimp", 10); }
float qtrap(float (*func)(float), float a, float b) { float trapzd(float (*func)(float), float a, float b, int n); void nrerror(char error_text[]); int j; float s,olds; olds = -1.0e30; for (j=1;j<=JMAX;j++) { s=trapzd(func,a,b,j); if (fabs(s-olds) < EPS*fabs(olds)) return s; olds=s; } nrerror("Too many steps in routine qtrap"); return 0.0; }
Real qsimp(Real (*func)(Real), const Real a, const Real b) { int j; Real s,st,ost,os; ost = os = -1.0e30; for (j=1; j<=JMAX; j++) { st = trapzd(func,a,b,j,ost); s = (4.0*st-ost)/3.0; /* EQUIVALENT TO SIMPSON'S RULE */ if (j > 5) /* AVOID SPURIOUS EARLY CONVERGENCE. */ if (fabs(s-os) < EPS*fabs(os) || (s == 0.0 && os == 0.0)) return s; os=s; ost=st; } ath_error("[qsimp]: Too many steps!\n"); return 0.0; }
double qsimp(double (*func)(double, double *, double *, int, double *,int), double a, double b, double *ss, double p[], double *c, int npts, double xx[], int idx) /*Returns the integral of the function func from a to b. The parameters EPS can be set to the desired fractional accuracy and JMAX so that 2 to the power JMAX-1 is the maximum allowed number of steps. Integration is performed by Simpson's rule. */ { void trapzd(double (*func)(double, double *, double *, int, double *,int), double a, double b, int n, double *ss, double p[], double *c, int npts, double xx[], int idx); /*void nrerror(char error_text[]);*/ int j; double s,st,ost=0.0,os=0.0; for (j=1;j<=JMAX;j++) { trapzd(func,a,b,j,ss,p,c,npts,xx,idx); st = *ss; s=(4.0*st-ost)/3.0; if (j > 5) /*Avoid spurious early convergence.*/ if (fabs(s-os) < EPS*fabs(os) || (s == 0.0 && os == 0.0)) return s; os=s; ost=st; } /*nrerror("Too many steps in routine qsimp");*/ return s; /*Never get here.*/ }
float qsimp(float (*func)(float), float a, float b) { float trapzd(float (*func)(float), float a, float b, int n); void nrerror(char error_text[]); int j; float s,st,ost=0.0,os=0.0; for (j=1;j<=JMAX;j++) { st=trapzd(func,a,b,j); s=(4.0*st-ost)/3.0; if (j > 5) if (fabs(s-os) < EPS*fabs(os) || (s == 0.0 && os == 0.0)) return s; os=s; ost=st; } nrerror("Too many steps in routine qsimp"); return 0.0; }
double romb(float (*func)(float), float a, float b) { double s[MAX]; int m,n; double var; for (m = 0; m < MAX; m++) s[m] = 1; for (n = 0; n < MAX; n++) { for (m = 0; m <= n; m++) { if (m==0) { var = s[m]; s[m] = trapzd(func, a, b, n); } else { s[n]= ( pow(4 , m-1) * s[m-1] - var ) / (pow(4, m-1) - 1); var = s[m]; s[m]= s[n]; } } } return s[MAX-1]; }
float qromb(float (*func)(float), float a, float b) { void polint(float xa[], float ya[], int n, float x, float *y, float *dy); float trapzd(float (*func)(float), float a, float b, int n); float ss,dss; float s[JMAXP+1],h[JMAXP+1]; int j; h[1]=1.0; for (j=1;j<=JMAX;j++) { s[j]=trapzd(func,a,b,j); if (j >= K) { polint(&h[j-K],&s[j-K],K,0.0,&ss,&dss); if (fabs(dss) < EPS*fabs(ss)) return ss; } s[j+1]=s[j]; h[j+1]=0.25*h[j]; } error("Too many steps in routine qromb"); return 0.0; }
double qsimp (double (*func)(double), double a, /* lower limit */ double b) /* upper limit */ { int j; long double s, st, ost, os; ost = os = -1.0e30; for (j = 1; j <= JMAX; j++){ st = trapzd (func, a, b, j); s = (4.0 * st - ost)/3.0; if (fabs (s - os) < EPS * fabs(os)) return s; os = s; ost = st; } fprintf (stderr, "Too many steps in routine QSIMP\n"); // exit (1); return s; }
template < class T > T qsimp( T (*func)(T), T a, T b ) { int j; T s, st, ost, os; ost = os = T(-1.0e30); for( j=1; j<=JMAX; j++ ) { st = trapzd(func, a, b, j); s = ( 4.0 * st - ost) / 3.0; if( fabs(s-os) < EPS * fabs(os) ) return s; if( s == 0.0 && os == 0.0 && j > 6 ) return s; os = s; ost = st; } printf("Previse koraka u qsimp"); return T(0.0); }
/****************************************************************************** * @brief Integration is performed by Romberg's method: Numerical Recipes * in C Section 4.3 *****************************************************************************/ double qromb(double (*funcd)(), double es, double Wind, double AirDens, double ZO, double EactAir, double F, double hsalt, double phi_r, double ushear, double Zrh, double a, double b) { extern parameters_struct param; double ss, dss; double s[param.BLOWING_MAX_ITER + 1]; double h[param.BLOWING_MAX_ITER + 2]; int j; h[1] = 1.0; for (j = 1; j <= param.BLOWING_MAX_ITER; j++) { s[j] = trapzd(funcd, es, Wind, AirDens, ZO, EactAir, F, hsalt, phi_r, ushear, Zrh, a, b, j); if (j >= param.BLOWING_K) { polint(&h[j - param.BLOWING_K], &s[j - param.BLOWING_K], param.BLOWING_K, 0.0, &ss, &dss); if (fabs(dss) <= DBL_EPSILON * fabs(ss)) { return ss; } } h[j + 1] = 0.25 * h[j]; } log_err("Too many steps"); return 0.; // To avoid warnings. }
/** Romberg integration. \param func Pointer to a member function of class model_parameters. \param a Lower limit of integration. \param b Upper limit of inegration. \param ns \return The integral of the function from a to b using Romberg's method */ dvariable function_minimizer::adromb( dvariable (model_parameters::*func)(const dvariable&), double a, const dvariable& b, int ns) { const double base = 4; int MAXN = min(JMAX, ns); dvar_vector s(1,MAXN+1); for(int j=1; j<=MAXN+1; j++) { s[j] = trapzd(func,a,b,j); } for(int iter=1; iter<=MAXN+1; iter++) { for(int j=1; j<=MAXN+1-iter; j++) { s[j] = (pow(base,iter)*s[j+1]-s[j])/(pow(base,iter)-1); } } return s[1]; }
template < class T > T qromb( T (*func)(T), T a, T b ) { T ss, dss; T s [JMAXP+1], h[JMAXP+1]; int j; h[1-1] = T(1.0); for( j=1; j<=JMAX; j++ ) { s[j-1] = trapzd(func, a, b, j); if( j >= K ) { polint(&h[j-K-1], &s[j-K-1], K, T(0.0), &ss, &dss ); if( fabs(dss) <= EPS*fabs(ss) ) return ss; } s[j+1-1] = s[j-1]; h[j+1-1] = 0.25 * h[j-1]; } puts("To many steps in qromb"); return T(0.0); }
/***********************************************************************//** * @brief Perform Romberg integration * * @param[in] a Left integration boundary. * @param[in] b Right integration boundary. * @param[in] k Integration order (default: k=5) * * Returns the integral of the integrand from a to b. Integration is * performed by Romberg's method of order 2K, where e.g. K=2 in Simpson's * rule. * The number of iterations is limited by m_max_iter. m_eps specifies the * requested fractional accuracy. By default it is set to 1e-6. * * @todo Check that k is smaller than m_max_iter * @todo Make use of std::vector class ***************************************************************************/ double GIntegral::romb(const double& a, const double& b, const int& k) { // Initialise result double result = 0.0; // Continue only if integration range is valid if (b > a) { // Initialise variables bool converged = false; double ss = 0.0; double dss = 0.0; // Allocate temporal storage double* s = new double[m_max_iter+2]; double* h = new double[m_max_iter+2]; // Initialise step size h[1] = 1.0; s[0] = 0.0; // Iterative loop for (m_iter = 1; m_iter <= m_max_iter; ++m_iter) { // Integration using Trapezoid rule s[m_iter] = trapzd(a, b, m_iter, s[m_iter-1]); // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (is_notanumber(s[m_iter]) || is_infinite(s[m_iter])) { std::cout << "*** ERROR: GIntegral::romb"; std::cout << "(a=" << a << ", b=" << b << ", k=" << k << "):"; std::cout << " NaN/Inf encountered"; std::cout << " (s[" << m_iter << "]=" << s[m_iter] << ")"; std::cout << std::endl; } #endif // Starting from iteration k on, use polynomial interpolation if (m_iter >= k) { ss = polint(&h[m_iter-k], &s[m_iter-k], k, 0.0, &dss); if (std::abs(dss) <= m_eps * std::abs(ss)) { converged = true; result = ss; break; } } // Reduce step size h[m_iter+1]= 0.25 * h[m_iter]; } // endfor: iterative loop // Free temporal storage delete [] s; delete [] h; // Dump warning if (!m_silent) { if (!converged) { std::string msg = "Integration uncertainty "+ gammalib::str(std::abs(dss))+ " exceeds tolerance of "+ gammalib::str(m_eps * std::abs(ss))+ " after "+gammalib::str(m_iter)+ " iterations. Result "+ gammalib::str(result)+ " is inaccurate."; gammalib::warning(G_ROMB, msg); } } } // endif: integration range was valid // Return result return result; }
virtual float func( float y, float n ) { return trapzd( innerFunc, y, x1, x2, (int)n ); }
/***********************************************************************//** * @brief Perform Romberg integration * * @param[in] a Left integration boundary. * @param[in] b Right integration boundary. * @param[in] k Integration order (default: k=5) * * Returns the integral of the integrand from a to b. Integration is * performed by Romberg's method of order 2K, where e.g. K=2 in Simpson's * rule. * The number of iterations is limited by m_max_iter. m_eps specifies the * requested fractional accuracy. By default it is set to 1e-6. * * @todo Check that k is smaller than m_max_iter * @todo Make use of std::vector class ***************************************************************************/ double GIntegral::romb(double a, double b, int k) { // Initialise result bool converged = false; double result = 0.0; double ss = 0.0; double dss = 0.0; // Continue only if integration range is valid if (b > a) { // Allocate temporal storage double* s = new double[m_max_iter+2]; double* h = new double[m_max_iter+2]; // Initialise step size h[1] = 1.0; s[0] = 0.0; // Iterative loop for (m_iter = 1; m_iter <= m_max_iter; ++m_iter) { // Integration using Trapezoid rule s[m_iter] = trapzd(a, b, m_iter, s[m_iter-1]); // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (isnotanumber(s[m_iter]) || isinfinite(s[m_iter])) { std::cout << "*** ERROR: GIntegral::romb"; std::cout << "(a=" << a << ", b=" << b << ", k=" << k << "):"; std::cout << " NaN/Inf encountered"; std::cout << " (s[" << m_iter << "]=" << s[m_iter] << ")"; std::cout << std::endl; } #endif // Starting from iteration k on, use polynomial interpolation if (m_iter >= k) { ss = polint(&h[m_iter-k], &s[m_iter-k], k, 0.0, &dss); if (std::abs(dss) <= m_eps * std::abs(ss)) { converged = true; result = ss; break; } } // Reduce step size h[m_iter+1]= 0.25 * h[m_iter]; } // endfor: iterative loop // Free temporal storage delete [] s; delete [] h; // Dump warning if (!m_silent) { if (!converged) { std::cout << "*** WARNING: GIntegral::romb: "; std::cout << "Integration did not converge "; std::cout << "(iter=" << m_iter; std::cout << ", result=" << ss; std::cout << ", d=" << std::abs(dss); std::cout << " > " << m_eps * std::abs(ss) << ")"; std::cout << std::endl; //throw; } } } // endif: integration range was valid // Return result return result; }