void spline_coef(int *method, int *n, double *x, double *y, double *b, double *c, double *d, double *e) { switch(*method) { case 1: periodic_spline(*n, x, y, b, c, d, e); break; case 2: natural_spline(*n, x, y, b, c, d); break; case 3: fmm_spline(*n, x, y, b, c, d); break; } }
void random_wave(double *wav_org, double *dist, int N, int flag, double *y, int NS){ /* wav_org - array of input wavelegnth dist - array of photon number distribution N - size of wav_org and dist flag - interpolation degree : 0 (for line list) or 3 (for continious spectra) y - output: randomly sampled wavelength NS - size of y (number of sampling points) */ clock_t start = clock(); srand48((long)time(NULL)); int n, N_plus = N + 1; //number of extended data if (flag == 0){ // no interpolation, step-like CDF, emission-line spectra printf("Dealing with line list\n"); double *CDF = malloc(sizeof(double) * N_plus); CDF[0] = 0; for (n = 0; n < N; n++) CDF[n+1] = CDF[n] + dist[n]; double total = CDF[N]; for (n = 0; n <= N; n++) CDF[n] = CDF[n] / total; //normalization unsigned long long ns; double random; int i, j, k; //double *num_den = malloc(sizeof(double) * N); for (ns = 0; ns < NS; ns ++) { random = drand48(); i = 0; j = N; do{ // search algorithm (bi-section) to find position of random in CDF k = (i+j)/2; if (random < CDF[k]) j = k; else i = k; } while(j > i+1); //until random number falls into (CDF[i], CDF[i+1]) y[ns] = wav_org[i]; //num_den[i] ++; } /*---data analysis---*/ /* FILE *num_den_file; num_den_file = fopen("./num_den_cum.dat", "w+"); FILE *normalized_PDF_file; normalized_PDF_file = fopen("./normalized_PDF.dat", "w+"); printf("Writing statistics to file\n"); for (n = 0; n < N; n++) { fprintf(num_den_file, "%lf\t%le\n", wav_org[n], (double) num_den[n] / NS); //normalization fprintf(normalized_PDF_file, "%lf\t%le\n", wav_org[n], dist[n] / total); } fclose(num_den_file); fclose(normalized_PDF_file); */ } if (flag == 3){ //continious spectra, data interpolation /*---CDF; Data extension---*/ double *wav = malloc(sizeof(double) * N_plus); double *CDF = malloc(sizeof(double) * N_plus); double *delta_lambda = malloc(sizeof(double) * N); double *flux = malloc(sizeof(double) * N); /*---add a threshold where flux is too small---*/ double sum = 0; for (n = 0; n < N; n++) { flux[n] = dist[n]; sum += flux[n]; } double threshold = sum * pow(10, -14); //15 decimal places for double precision for (n = 0; n < N; n++) if (flux[n] < threshold) flux[n] = threshold; //---delta lambda--- delta_lambda[0] = wav_org[1] - wav_org[0]; for (n = 1; n < N-1; n++) delta_lambda[n] = (wav_org[n+1] - wav_org[n-1]) / 2; delta_lambda[N-1] = wav_org[N-1] - wav_org[N-2]; //---CDF--- CDF[0] = 0; CDF[1] = flux[0] * delta_lambda[0]; wav[0] = 1.5 * wav_org[0] - 0.5 * wav_org[1]; for (n = 1; n < N; n++) { CDF[n+1] = CDF[n] + flux[n] * delta_lambda[n]; wav[n] = (wav_org[n-1] + wav_org[n]) / 2; } wav[N] = 1.5 * wav_org[N-1] - 0.5 * wav_org[N-2]; double total = CDF[N]; //printf("total = %le\n", total); for (n = 0; n < N_plus; n++) CDF[n] = CDF[n] / total; free(flux); /*---data output--- FILE *order_43; order_43 = fopen("./order_43.dat", "w+"); for(n = 0; n < N_plus; n++) fprintf(order_43, "%le\t%le\n", wav[n], CDF[n]); fclose(order_43); FILE *spec_43; spec_43 = fopen("./spec_43.dat", "w+"); for(n = 0; n < N; n++) fprintf(spec_43, "%le\t%le\n", wav_org[n], dist[n]); fclose(spec_43); */ /*FILE *inter_43; inter_43 = fopen("./inter_43.dat", "w+");*/ /*---interpolation---*/ unsigned long long ns; double *b, *c, *d, *x; b = malloc(sizeof(double) * N_plus); c = malloc(sizeof(double) * N_plus); d = malloc(sizeof(double) * N_plus); natural_spline(N_plus, CDF, wav, b, c, d); //wav as a function of CDF /*---sampling---*/ if (NS <= pow(10, 7)){ x = malloc(sizeof(double) * NS); for (ns = 0; ns < NS; ns ++) x[ns] = drand48(); printf("Sampling in progress\n"); spline_eval(&NS, x, y, &N_plus, CDF, wav, b, c, d); //returns y to be the sampling wavelength /*for (n = 0; n < 500; n++) printf("%le\t%16.14lf\n", x[n], y[n]); for (n = 0; n < NS/10; n++) fprintf(inter_43, "%le\t%16.14lf\n", x[n], y[n]); fclose(inter_43); */ free(x); } else { //(NS > pow(10, 7)) int new_NS = pow(10, 7); int progress, times, TIMES = (int)(NS / new_NS), tail = NS - new_NS * TIMES; double ratio; x = malloc(sizeof(double) * new_NS); printf("Sampling in progress\n"); for (times = 0; times < TIMES; times ++){ for (ns = 0; ns < new_NS; ns ++) x[ns] = drand48(); spline_eval(&new_NS, x, y, &N_plus, CDF, wav, b, c, d); y += new_NS; // Show the load bar. ratio = (double)(times + 1) / TIMES; printf("%3d%% [", (int)(ratio*100) ); for (progress = 0; progress < (int)(ratio * 50) ; progress++) printf("="); printf(">"); for (progress = (int)(ratio * 50); progress < 50; progress++) printf(" "); printf("]\r"); fflush(stdout); } free(x); double *x2 = malloc(sizeof(double) * tail); for (ns = 0; ns < tail; ns ++) x2[ns] = drand48(); spline_eval(&tail, x2, y, &N_plus, CDF, wav, b, c, d); printf("\n"); free(x2); y -= new_NS * TIMES; } /* FILE *wavelegnth_sam; wavelegnth_sam = fopen("./wavelegnth_sam.dat", "w+"); for (ns = 0; ns < NS; ns++) fprintf(wavelegnth_sam, "%lf\n", y[ns]); fclose(wavelegnth_sam); */ /*---deallocate array memory---*/ free(b); free(c); free(d); free(wav); free(CDF); free(delta_lambda); } clock_t ends = clock(); printf("%.2f s to return %.2le wavelegnths\n",(double) (ends - start) / CLOCKS_PER_SEC, (double)NS); }