//自适应Simpson公式(递归过程)。整个区间[a,b]的三点Simpson值A double asr(double a, double b, double eps, double A) { double c = a + (b - a) / 2; double L = Simpson (a, c), R = Simpson (c, b); if (std::fabs (L+R-A) <= 15*eps) { return L+R+(L+R-A)/15.0; } return asr (a, c, eps/2, L) + asr (c, b, eps/2, R); }
double DoubleSimpson (double a, double b, double (*f) (double x)){ double sac, c; c = (a+b)/2; sac = Simpson(a,c,f); sac += Simpson(c,b,f); return sac; }
double CIRadialQkIntegratedMSub(cfac_t *cfac, int j1, int m1, int j2, int m2, int k0, int k1, double te, double e12) { double e0, e1, e2, d, r; double x[NINT0], y[NINT0], xi[NINT], yi[NINT]; double ymin, ymax, bms, bte; int i, qlog; bms = BornMass(); BornFormFactorTE(&bte); e0 = te + e12; ymin = (YEG0*(bte+te))/e12; ymax = (YEG1*(bte+te))/e12; if (ymax > 0.99*bms) ymax = 0.99*bms; if (fabs(bms-1) < EPS3 && ymax > 0.5) ymax = 0.5; ymin = log(ymin); ymax = log(ymax); x[0] = ymin; d = (ymax - ymin)/(NINT0-1); for (i = 1; i < NINT0; i++) { x[i] = x[i-1] + d; } for (i = 0; i < NINT0; i++) { r = exp(x[i]); e2 = e12*r; e1 = e12 - e2/bms; y[i] = CIRadialQkMSub(cfac, j1, m1, j2, m2, k0, k1, e1, e2, e0); y[i] *= r; } xi[0] = ymin; d = (ymax - ymin)/(NINT-1.0); for (i = 1; i < NINT; i++) { xi[i] = xi[i-1] + d; } qlog = 1; for (i = 0; i < NINT0; i++) { if (y[i] <= 0) { qlog = 0; break; } } if (qlog) { for (i = 0; i < NINT0; i++) { y[i] = log(y[i]); } } UVIP3P(NINT0, x, y, NINT, xi, yi); if (qlog) { for (i = 0; i < NINT; i++) { yi[i] = exp(yi[i]); } } r = Simpson(yi, 0, NINT-1); r *= d*e12; ReinitRadial(cfac, 1); return r; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *sum; double a, b; plhs[0]=mxCreateDoubleMatrix(1, 1, mxREAL); sum=mxGetPr(plhs[0]); a=*(mxGetPr(prhs[0])); b=*(mxGetPr(prhs[1])); *sum=Simpson(a,b); }
int main(void) { int k; double a = 0, b=5.0; printf("Integral from %f to %f is:\n",a,b); for( k=1; k<=40; k++ ) { printf(" k = %3d: %f\n",k,Simpson(a,b,k,example_function)); } return 0; }
double AdaptiveSimpson (double a, double b, double (*f) (double x), double tol){ double sab, sacb, c; if(tol == 0){ puts("[Warning] Machine Precision has been reached"); return DoubleSimpson(a,b,f); } sab = Simpson(a,b,f); sacb = DoubleSimpson(a,b,f); if(fabs(sab -sacb) < tol*15 ){ //printf("\t dif: %0.7f 15*tol: %0.7f\n",sab-sacb,15*tol); return sacb; } c = (a+b)/2; sacb = AdaptiveSimpson(a,c,f,tol/2); sacb += AdaptiveSimpson(c,b,f,tol/2); return sacb; }
//自适应Simpson公式(主过程) double asr(double a, double b, double eps) { return asr (a, b, eps, Simpson (a, b)); }
double *CIRadialQkIntegratedTable(cfac_t *cfac, int kb, int kbp) { int index[2], ie, ite, i, k, nqk, qlog; double **p, *qkc, e1, e2; double yint[NINT], integrand[NINT]; double ymin, ymax, dy, y, bte, bms; double yegrid[NINT0], qi[MAXNTE], qt[MAXNTE][NINT0]; index[0] = kb; index[1] = kbp; p = (double **) MultiSet(qk_array, index, NULL); if (*p) { return (*p); } nqk = n_tegrid*n_egrid; *p = malloc(sizeof(double)*nqk); qkc = *p; bms = BornMass(); BornFormFactorTE(&bte); for (ie = 0; ie < n_egrid; ie++) { for (ite = 0; ite < n_tegrid; ite++) { for (i = 0; i < NINT0; i++) { qt[ite][i] = 0.0; } } ymin = ((bte+tegrid[0])*YEG0)/egrid[ie]; ymax = ((bte+tegrid[n_tegrid-1])*YEG1)/egrid[ie]; if (ymax >= 0.99*bms) ymax = 0.99*bms; if (fabs(bms-1) < EPS3 && ymax > 0.5) ymax = 0.5; ymin = log(ymin); ymax = log(ymax); dy = (ymax - ymin)/(NINT0-1.0); yegrid[0] = ymin; for (i = 1; i < NINT0; i++) { yegrid[i] = yegrid[i-1] + dy; } dy = (ymax - ymin)/(NINT-1.0); yint[0] = ymin; for (i = 1; i < NINT; i++) { yint[i] = yint[i-1] + dy; } for (i = 0; i < NINT0; i++) { y = exp(yegrid[i]); e2 = egrid[ie]*y; e1 = egrid[ie]*(1.0-y/bms); for (k = 0; k <= pw_scratch.max_k; k += 2) { CIRadialQk(cfac, qi, e1, e2, kb, kbp, k); for (ite = 0; ite < n_tegrid; ite++) { qi[ite] /= (k + 1.0); qt[ite][i] += qi[ite]; } } } for (ite = 0; ite < n_tegrid; ite++) { for (i = 0; i < NINT0; i++) { y = exp(yegrid[i]); qt[ite][i] *= y; } qlog = 1; for (i = 0; i < NINT0; i++) { if (qt[ite][i] <= 0.0) { qlog = 0; break; } } if (qlog) { for (i = 0; i < NINT0; i++) { qt[ite][i] = log(qt[ite][i]); } } UVIP3P(NINT0, yegrid, qt[ite], NINT, yint, integrand); if (qlog) { for (i = 0; i < NINT; i++) { integrand[i] = exp(integrand[i]); } } y = Simpson(integrand, 0, NINT-1); y *= dy*egrid[ie]; i = ite*n_egrid + ie; qkc[i] = 16.0*y; } } ReinitRadial(cfac, 1); return (*p); }
int CIRadialQkBED(double *dp, double *bethe, double *b, int kl, double *xe, double *logxe, double *q, double *p, double te) { double integrand[NINT]; double x[NINT], y[NINT], t[NINT], s[NINT], d; double x0[MAXNUSR]; int i, j, n, n1; for (i = 0; i < NINT; i++) { x[i] = 1.0/(2.0*yegrid0[i]); t[i] = log(x[i]); } for (i = 0; i < n_egrid; i++) { q[i] = log(q[i]); } for (i = 0; i < NINT; i++) { if (t[i] < logxe[n_egrid-1]) break; } if (i > 1) { d = te/p[3]; for (j = 0; j < i; j++) { y[j] = (x[j]-1.0)*d + 1.0; s[j] = log(y[j]); } RRRadialQkFromFit(3, p, i, y, s, integrand, NULL, 0, &kl); for (j = 0; j < i; j++) { integrand[j] *= x[j]*d; } } if (i < NINT) { n = NINT-i; n1 = n_egrid; UVIP3P(n1, logxe, q, n, &(t[i]), &(integrand[i])); for (; i < NINT; i++) { integrand[i] = exp(integrand[i]); } } for (i = 0; i < NINT; i++) { integrand[i] *= x[i]*yegrid0[i]; } d = 4.0*log(yegrid0[1]/yegrid0[0]); if (qk_mode == QK_DW) { (*bethe) = Simpson(integrand, 0, NINT-1); (*bethe) *= d; } else { n = (NINT+1)/2; j = n-1; t[j] = 1.0; y[j--] = 0.0; for (i = NINT-1; i > 0 && j >= 0; i -= 2, j--) { y[j] = Simpson(integrand, i-2, i); y[j] *= d; y[j] += y[j+1]; t[j] = 2.0*yegrid0[i-2]; } *bethe = y[0]; for (i = 0; i < NINT; i++) { integrand[i] *= x[i]; } (*b) = Simpson(integrand, 0, NINT-1); (*b) *= d; for (i = 0; i < n_egrid; i++) { x0[i] = 1.0/xe[i]; } UVIP3P(n, t, y, n_egrid, x0, dp); } if (!isfinite(*bethe)) { return 1; } return 0; }
int main(int argc, char** argv) { int my_rank; /* My process rank */ int p; /* The number of processes */ double a; /* Left endpoint */ double b; /* Right endpoint */ int n; /* Number of trapezoids */ double h; /* Trapezoid base length */ double local_a; /* Left endpoint my process */ double local_b; /* Right endpoint my process */ int local_n; /* Number of trapezoids for */ /* my calculation */ double my_area; /* Integral over my interval */ double total = 0; /* Total area */ int source; /* Process sending area */ int dest = 0; /* All messages go to 0 */ int tag = 0; double start, finish, elapsed; MPI_Status status; /* Let the system do what it needs to start up MPI */ MPI_Init(&argc, &argv); /* Get my process rank */ MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); /* Find out how many processes are being used */ MPI_Comm_size(MPI_COMM_WORLD, &p); Get_data(p, my_rank, &a, &b, &n); MPI_Barrier(MPI_COMM_WORLD); start = MPI_Wtime(); h = (b-a)/n; /* h is the same for all processes */ local_n = n/p; /* So is the number of trapezoids */ /* Length of each process' interval of * integration = local_n*h. So my interval * starts at: */ local_a = a + my_rank*local_n*h; local_b = local_a + local_n*h; my_area = Simpson(local_a, local_b, local_n, h); /* Add up the areas calculated by each process */ if (my_rank == 0) { total = my_area; for (source = 1; source < p; source++) { MPI_Recv(&my_area, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, &status); total = total + my_area; } } else { MPI_Send(&my_area, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD); } finish = MPI_Wtime(); elapsed = finish - start; printf("Elapsed time = %.14e seconds\n", elapsed); printf("Clock resolution = %.14e seconds\n", MPI_Wtick()); /* Print the result */ if (my_rank == 0) { printf("With n = %d trapezoids, our estimate\n", n); printf("of the area from %f to %f = %.15f\n", a, b, total); } /* Shut down MPI */ MPI_Finalize(); return 0; } /* main */