#include #include #include #include #include #include #define MAX_FILENAME_LENGTH 1024 char infile_name[MAX_FILENAME_LENGTH]; char noisefile_name[MAX_FILENAME_LENGTH]; char parfile_name[MAX_FILENAME_LENGTH]; char outfile_name[MAX_FILENAME_LENGTH]; FILE *infile; FILE *parfile; FILE *noisefile; FILE *outfile; FILE *logfile; int n_proc; int gauss_quality; int exit_code; /* exit code for error identification */ int infile_length; int parfile_length; int noisefile_length; int outfile_length; int want_log; double amp_grid; double freq_grid; double phase_grid; double *jd; /* time values array */ double *amp; /* amplitude values array */ double *freq; /* frequency values array */ double *phase; /* phase values array */ double *mag; /* magnitude values array */ double *rms; /* noise levels array */ double **noisy; /* light curve plus noise */ double **newamp; double **newfreq; double **newphase; double **var_amp; double **var_freq; double **var_phase; int count_file(char *fname); void read_parfile(); void read_infile(); void read_noisefile(); int check_outfile(); void least_squares(); double sum_of_squares(int noiseindex); void update_outfile(); /*****************************************************************************/ /******************* Welcome to the start of the program! ********************/ /*****************************************************************************/ main(int argc, char *argv[]) { int i; /* index */ int j; /* index */ int k; /* index */ double nval; /* value from random number generator */ /* Variable initialization */ n_proc = -1; infile_length = -1; /* no input file specified yet */ parfile_length = -1; /* no parameter file specified yet */ noisefile_length = -1; /* no noise file specified yet */ outfile_length = -1; /* no output file specified yet */ gauss_quality = 10; /* default iterations */ amp_grid = .01; /* default amplitude grid spacing */ freq_grid = .0001; /* default frequency grid spacing */ phase_grid = .001; /* default phase grid spacing */ exit_code = 0; /* no errors yet */ want_log = 0; printf("EPSIM - Error Propagation SIMulator\n"); printf("Version 1.0 beta\n"); printf("**************************************"); printf("****************************************\n"); printf("by Peter Reegen\n"); printf("Department of Astronomy\n"); printf("University of Vienna\n"); printf("Tuerkenschanzstrasse 17\n"); printf("1180 Vienna, Austria\n"); printf("Release date: April 1, 2003 (NO JOKE!)\n\n"); printf("**************************************"); printf("****************************************\n\n"); /* Scan command line arguments */ while (--argc > 0) { if (strcmp(*++argv, "-I") == 0) /* scan input file name */ { --argc; sprintf(infile_name, "%s", *++argv); printf("Input file: %s\n", infile_name); ++infile_length; } else if (strcmp(*argv, "-L") == 0) /* create log file */ ++want_log; else if (strcmp(*argv, "-N") == 0) /* scan noise file name */ { --argc; sprintf(noisefile_name, "%s", *++argv); printf("Noise file: %s\n", noisefile_name); ++noisefile_length; } else if (strcmp(*argv, "-O") == 0) /* scan output file name */ { --argc; sprintf(outfile_name, "%s", *++argv); printf("Output file: %s\n", outfile_name); ++outfile_length; } else if (strcmp(*argv, "-P") == 0) /* scan parameter file name */ { --argc; sprintf(parfile_name, "%s", *++argv); printf("Parameter file: %s\n", parfile_name); ++parfile_length; } else if (strcmp(*argv, "-#") == 0) /* scan number of processes */ { --argc; n_proc = atoi(*++argv); printf("Number of processes: %lu\n", n_proc); } else if (strcmp(*argv, "-a") == 0) /* scan amplitude grid */ { --argc; amp_grid = strtod(*++argv, NULL); printf("Amplitude grid: %lg\n", amp_grid); } else if (strcmp(*argv, "-f") == 0) /* scan frequency grid */ { --argc; freq_grid = strtod(*++argv, NULL); printf("Frequency grid: %lg\n", freq_grid); } else if (strcmp(*argv, "-g") == 0) /* scan Gaussian quality */ { --argc; gauss_quality = atoi(*++argv); printf("Gaussian quality: %lu\n", gauss_quality); } else if (strcmp(*argv, "-p") == 0) /* scan phase grid */ { --argc; phase_grid = strtod(*++argv, NULL); printf("Phase grid %lg\n", phase_grid); } else { printf("\nAbnormal program termination.\n"); printf("Exit code 1 - "); printf ("Unknown command line argument \'%s\'.\n", *argv); return 1; } } if (want_log) logfile = fopen("epsim.log", "w"); /* Ask for parameters missing in the command line */ if (infile_length == -1) { printf("Please enter (path and) name of input file: "); scanf("%s", infile_name); } if (noisefile_length == -1) { printf("Please enter (path and) name of noise file: "); scanf("%s", noisefile_name); } if (outfile_length == -1) { printf("Please enter (path and) name of parameter file: "); scanf("%s", parfile_name); } if (parfile_length == -1) { printf("Please enter (path and) name of output file: "); scanf("%s", outfile_name); } while (n_proc < 0) { printf("Please enter number of processes: "); scanf("%lu", &n_proc); if (n_proc < 0) printf("\nNumber of processes < 0. Please retry.\n\n"); } if (n_proc == 0) n_proc = INT_MAX; printf("%s: counting number of entries...", infile_name); if ((infile_length = count_file(infile_name)) == -1) { printf("\nAbnormal program termination.\n"); printf("Exit code 2 - Failed to count input file entries.\n"); return 2; } printf("done.\n%s: %lu entries found.\n", infile_name, infile_length); printf("%s: counting number of entries...", noisefile_name); if ((noisefile_length = count_file(noisefile_name)) == -1) { printf("\nAbnormal program termination.\n"); printf("Exit code 3 - Failed to count noise file entries.\n"); return 3; } printf("done.\n%s: %lu entries found.\n", noisefile_name, noisefile_length); printf("%s: counting number of entries...", parfile_name); if ((parfile_length = count_file(parfile_name)) == -1) { printf("\nAbnormal program termination.\n"); printf("Exit code 4 - Failed to count parameter file entries."); return 4; } else if (parfile_length / 3. > parfile_length / 3 + .1) { printf("\nAbnormal program termination.\n"); printf("Exit code 5 - Format error in parameter file %s.\n", parfile_name); return 5; } else parfile_length /= 3; printf("done.\n%s: %lu entries found.\n", parfile_name, parfile_length); printf("Reading parameter file..."); amp = (double*)calloc(parfile_length, sizeof(double)); freq = (double*)calloc(parfile_length, sizeof(double)); phase = (double*)calloc(parfile_length, sizeof(double)); newamp = (double**)calloc(noisefile_length, sizeof(double*)); newfreq = (double**)calloc(noisefile_length, sizeof(double*)); newphase = (double**)calloc(noisefile_length, sizeof(double*)); noisy = (double**)calloc(noisefile_length, sizeof(double*)); var_amp = (double**)calloc(noisefile_length, sizeof(double*)); var_freq = (double**)calloc(noisefile_length, sizeof(double*)); var_phase = (double**)calloc(noisefile_length, sizeof(double*)); for (i = 0; i < noisefile_length; i++) { noisy[i] = (double*)calloc(infile_length, sizeof(double)); newamp[i] = (double*)calloc(parfile_length, sizeof(double)); newfreq[i] = (double*)calloc(parfile_length, sizeof(double)); newphase[i] = (double*)calloc(parfile_length, sizeof(double)); var_amp[i] = (double*)calloc(parfile_length, sizeof(double)); var_freq[i] = (double*)calloc(parfile_length, sizeof(double)); var_phase[i] = (double*)calloc(parfile_length, sizeof(double)); for (j = 0; j < parfile_length; j++) { var_amp[i][j] = 0; var_freq[i][j] = 0; var_phase[i][j] = 0; } } read_parfile(); printf("done.\n"); printf("Reading input file and computing signal..."); jd = (double*)calloc(infile_length, sizeof(double)); mag = (double*)calloc(infile_length, sizeof(double)); read_infile(); printf("done.\n"); printf("Reading noise file..."); rms = (double*)calloc(noisefile_length, sizeof(double)); read_noisefile(); printf("done.\n"); printf("Initializing random number generator using system time..."); int fseed; fseed = time(NULL); printf("done.\nInitial value: %lu\n", time(NULL)); if ((outfile_length = check_outfile()) == -6) { printf("\nAbnormal program termination.\n"); printf("Exit code 6 - Failed to create output file %s.\n", outfile_name); return 6; } if (outfile_length == -1) return 0; outfile_length = parfile_length; printf("Entering main procedure.\n"); printf("Processes finished: %16lu\n", 0); for (i = 0; i < n_proc; i++) { if (want_log) { fprintf(logfile, "Entering procedure %lu of %lu.\n", i + 1, n_proc); fprintf(logfile, " Generating noise data.\n"); } for (j = 0; j < infile_length; j++) { /*****************************************************************************/ /************* Random number generator for Gaussian distribution *************/ /*****************************************************************************/ /* This random number generator is supposed to produce normally distributed random numbers. It uses the central limit theorem. The number of iterations is the gauss_quality parameter. The result is a normal distribution with expected value 0 and standard deviation 1; */ nval = 0; for (k = 0; k < gauss_quality; k++) nval += (double)rand() / RAND_MAX; nval = (nval / gauss_quality - .5) * sqrt(12. * gauss_quality); /*****************************************************************************/ /* Now the light curve stored in the mag array has to be distorted by the noise evaluated above. */ /*****************************************************************************/ for (k = 0; k < noisefile_length; k++) noisy[k][j] = mag[j] + rms[k] * nval; } /*****************************************************************************/ /* The next step is to compute the least squares fit. The sum of squares of the residuals is evaluated. Then the minimum is searched for by means of a step-by-step approximation. */ /*****************************************************************************/ if (want_log) fprintf(logfile, " Entering least squares algorithm.\n"); least_squares(); if (want_log) fprintf(logfile, " Writing output file.\n"); outfile = fopen(outfile_name, "w"); for (j = 0; j < noisefile_length; j++) { if (i > 1) { fprintf(outfile, "NOISE LEVEL: %lg ", rms[j]); fprintf(outfile, "frequency grid: %lg / amp ", freq_grid * rms[j] / (jd[infile_length - 1] - jd[0])); fprintf(outfile, "amplitude grid: %lg ", amp_grid * rms[j]); fprintf(outfile, "phase grid: %lg / amp\n", phase_grid * rms[j]); fprintf(outfile, "frequency "); fprintf(outfile, "rms frequency "); fprintf(outfile, "amplitude "); fprintf(outfile, "rms amplitude "); fprintf(outfile, "phase "); fprintf(outfile, "rms phase \n"); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " \n"); } for (k = 0; k < outfile_length; k++) { var_amp[j][k] += pow(newamp[j][k] - amp[k], 2); var_freq[j][k] += pow(newfreq[j][k] - freq[k], 2); var_phase[j][k] += pow(newphase[j][k] - phase[k], 2); if (i > 1) { fprintf(outfile, "%24lg ", freq[k]); fprintf(outfile, "%24lg ", sqrt(var_freq[j][k] / i)); fprintf(outfile, "%24lg ", amp[k]); fprintf(outfile, "%24lg ", sqrt(var_amp[j][k]/ i)); fprintf(outfile, "%24lg ", phase[k]); fprintf(outfile, "%24lg\n", sqrt(var_phase[j][k] / i)); } } } if (want_log) { fprintf(logfile, "\nUpdated sums of squares:\n"); for (j = 0; j < noisefile_length; j++) { fprintf(logfile, "Noise level: %lg\n", rms[j]); for (k = 0; k < outfile_length; k++) { fprintf(logfile, "%24lg ", var_freq[j][k]); fprintf(logfile, "%24lg ", var_amp[j][k]); fprintf(logfile, "%24lg\n", var_phase[j][k]); } } } fprintf(outfile, "\n%lu processes", i + 1); fclose(outfile); printf("Processes finished: %16lu\n", i + 1); } free(noisy); free(rms); free(amp); free(freq); free(phase); free(jd); free(mag); free(newamp); free(newfreq); free(newphase); free(var_amp); free(var_freq); free(var_phase); printf("\nFinished.\n\n"); printf("**************************************"); printf("****************************************\n\n"); printf("Thank you for using EPSIM.\n"); printf("Questions or complaints?\n"); printf("Please contact Peter Reegen (reegen@astro.univie.ac.at)\n"); printf("Bye!\n\n"); if (want_log) fclose(logfile); return exit_code; } /*****************************************************************************/ /************************** The middle of the film ***************************/ /*****************************************************************************/ /*****************************************************************************/ /*************************** Preparing output file ***************************/ /*****************************************************************************/ int check_outfile() { int i; /* index */ int j; /* index */ printf("Checking for output file...done.\n"); if ((outfile = fopen(outfile_name, "r")) != NULL) { printf("Output file %s already exists!\n", outfile_name); printf("Please re-run with a different file name.\n"); return -1; } if ((outfile = fopen(outfile_name, "w")) == NULL) return -6; for (j = 0; j < noisefile_length; j++) { fprintf(outfile, "NOISE LEVEL: %lg ", rms[j]); fprintf(outfile, "frequency grid: %lg / amp ", freq_grid * rms[j] / (jd[infile_length - 1] - jd[0])); fprintf(outfile, "amplitude grid: %lg ", amp_grid * rms[j]); fprintf(outfile, "phase grid: %lg / amp\n", phase_grid * rms[j]); fprintf(outfile, "amplitude "); fprintf(outfile, "rms amplitude "); fprintf(outfile, "frequency "); fprintf(outfile, "rms frequency "); fprintf(outfile, "phase "); fprintf(outfile, "rms phase \n"); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " "); fprintf(outfile, " \n"); for (i = 0; i < parfile_length; i++) fprintf(outfile, "%24lg %24lg %24lg %24lg %24lg %24lg \n", freq[i], 0., amp[i], 0., phase[i], 0.); } fprintf(outfile, "\n0 processes\n"); fclose(outfile); return 0; } /*****************************************************************************/ /******************** Counting the number of file entries ********************/ /*****************************************************************************/ int count_file(char *fname) { FILE *whichfile; int file_length; double file_entry; file_length = 0; while ((whichfile = fopen(fname, "r")) == NULL) { printf("\nUnable to open file %s. Please retry.\n\n", fname); printf("Please enter (path and) name: "); scanf("%s", fname); } for (file_length = 0; fscanf(whichfile, "%lf", &file_entry) != EOF; ++file_length); fclose (whichfile); return file_length; } /*****************************************************************************/ /****************** Scan amplitudes, frequencies and phases ******************/ /*****************************************************************************/ void read_parfile() { int i; /* index */ int j; /* index */ parfile = fopen(parfile_name, "r"); for (i = 0; i < parfile_length; i++) { fscanf(parfile, "%lf", &freq[i]); fscanf(parfile, "%lf", &[i]); fscanf(parfile, "%lf", &phase[i]); for (j = 0; j < noisefile_length; j++) { newamp[j][i] = amp[i]; newfreq[j][i] = freq[i]; newphase[j][i] = phase[i]; } } fclose(parfile); return; } /*****************************************************************************/ /********************* Scan time values from input file **********************/ /*****************************************************************************/ void read_infile() { int i; /* index */ int j; /* index */ infile = fopen(infile_name, "r"); printf("\n"); for (i = 0; i < infile_length; i++) { fscanf(infile, "%lf", &jd[i]); mag[i] = 0; for (j = 0; j < parfile_length; j++) mag[i] += amp[j] * sin(2 * M_PI * (freq[j] * jd[i] + phase[j])); } fclose(infile); return; } /*****************************************************************************/ /********************* Scan noise levels from noise file *********************/ /*****************************************************************************/ void read_noisefile() { int i; /* index */ noisefile = fopen(noisefile_name, "r"); for (i = 0; i < noisefile_length; i++) fscanf(noisefile, "%lf", &rms[i]); fclose(noisefile); return; } /*****************************************************************************/ /************************** Least squares algorithm **************************/ /*****************************************************************************/ void least_squares() { int whichpar; /* This value is used as an indicator for the type of parameter that has been modified. It is set -1 or +1 for amplitude, -2 or +2 for frequency, and -3 or +3 for phase, respectively. */ int index_changed; /* This is the line number in the parameters file corresponding to the modified parameter. */ double reference; /* The result of the sum of squares for the current parameter setup is stored here. */ double best_improvement; /* This variable is for the result of the sum of squares for the new parameter setup. */ int i; /* index */ int j; /* index */ int k; /* index */ double zero; for (i = 0; i < noisefile_length; i++) { if (want_log) fprintf(logfile, "\n Initialization..."); for (j = 0; j < parfile_length; j++) { newamp[i][j] = amp[j]; newfreq[i][j] = freq[j]; newphase[i][j] = phase[j]; } if (want_log) { fprintf(logfile, "done.\n"); fprintf(logfile, "\n Least squares for noise level %lg:\n", rms[i]); } whichpar = 0; best_improvement = sum_of_squares(i); if (want_log) fprintf(logfile, " RMS %lg.\n", sqrt(best_improvement / (infile_length - 1))); k = 0; do { if (want_log) fprintf(logfile, " Starting iteration %lu.\n", ++k); reference = best_improvement; switch (whichpar) { case -3: newphase[i][index_changed] -= phase_grid * rms[i] / amp[index_changed]; if (want_log) { fprintf(logfile, " Changing phase %lu by %lg.\n", index_changed + 1, -phase_grid * rms[i] / amp[index_changed]); fprintf(logfile, " New phase: %lg\n", newphase[i][index_changed]); } break; case -2: newfreq[i][index_changed] -= freq_grid * rms[i] / (jd[infile_length - 1] - jd[0]) / amp[index_changed]; if (want_log) { fprintf(logfile, " Changing frequency %lu by %lg.\n", index_changed + 1, -freq_grid * rms[i] / amp[index_changed] / (jd[infile_length - 1] - jd[0])); fprintf(logfile, " New frequency: %lg\n", newfreq[i][index_changed]); } break; case -1: newamp[i][index_changed] -= amp_grid * rms[i]; if (want_log) { fprintf(logfile, " Changing amplitude %lu by %lg.\n", index_changed + 1, -amp_grid * rms[i]); fprintf(logfile, " New amplitude: %lg\n", newamp[i][index_changed]); } break; case 1: newamp[i][index_changed] += amp_grid * rms[i]; if (want_log) { fprintf(logfile, " Changing amplitude %lu by %lg.\n", index_changed + 1, amp_grid * rms[i]); fprintf(logfile, " New amplitude: %lg\n", newamp[i][index_changed]); } break; case 2: newfreq[i][index_changed] += freq_grid * rms[i] / (jd[infile_length - 1] - jd[0]) / amp[index_changed]; if (want_log) { fprintf(logfile, " Changing frequency %lu by %lg.\n", index_changed + 1, freq_grid * rms[i] / amp[index_changed] / (jd[infile_length - 1] - jd[0])); fprintf(logfile, " New frequency: %lg\n", newfreq[i][index_changed]); } break; case 3: newphase[i][index_changed] += phase_grid * rms[i] / amp[index_changed]; if (want_log) { fprintf(logfile, " Changing phase %lu by %lg.\n", index_changed + 1, phase_grid * rms[i] / amp[index_changed]); fprintf(logfile, " New phase: %lg\n", newphase[i][index_changed]); } break; default: break; } for (j = 0; j < parfile_length; j++) { newamp[i][j] -= amp_grid * rms[i]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = -1; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary amplitude: %24lg\n", newamp[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newamp[i][j] += 2 * amp_grid * rms[i]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = 1; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary amplitude: %24lg\n", newamp[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newamp[i][j] -= amp_grid * rms[i]; newfreq[i][j] -= freq_grid * rms[i] / (jd[infile_length - 1] - jd[0]) / amp[i]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = -2; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary frequency: %24lg\n", newfreq[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newfreq[i][j] += 2 * freq_grid * rms[i] / (jd[infile_length - 1] - jd[0]) / amp[i]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = 2; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary frequency: %24lg\n", newfreq[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newfreq[i][j] -= freq_grid * rms[i] / (jd[infile_length - 1] - jd[0]) / amp[i]; newphase[i][j] -= phase_grid * rms[i] / amp[index_changed]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = -3; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary phase: %24lg\n", newphase[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newphase[i][j] += 2 * phase_grid * rms[i] / amp[index_changed]; if ((zero = sum_of_squares(i)) < best_improvement) { whichpar = 3; index_changed = j; best_improvement = zero; if (want_log) { fprintf(logfile, " Improvement found at component %lu.\n", index_changed + 1); fprintf(logfile, " Preliminary phase: %24lg\n", newphase[i][j]); fprintf(logfile, " Preliminary RMS: %24lg\n", sqrt(best_improvement / (infile_length - 1))); } } newphase[i][j] -= phase_grid * rms[i] / amp[index_changed]; } if (want_log) for (j = 0; j < parfile_length; j++) { fprintf(logfile, "\n Result of iteration %8lu:\n", k); fprintf (logfile, " C: %4lu F: %24lg A: %24lg P: %24lg S: %24lg\n", j + 1, newfreq[i][j], newamp[i][j], newphase[i][j], best_improvement); } } while(best_improvement < reference); if (want_log) fprintf(logfile, "\n Least squares for noise level %lg finished.\n", rms[i]); } return; } /*****************************************************************************/ /********** This function has to attain a minimum for least squares **********/ /*****************************************************************************/ double sum_of_squares(int noiseindex) { int i; /* index */ int j; /* index */ double result; double buf; result = 0; for (i = 0; i < infile_length; i++) { buf = 0; for (j = 0; j < parfile_length; j++) buf += newamp[noiseindex][j] * sin(2 * M_PI * (newfreq[noiseindex][j] * jd[i] + newphase[noiseindex][j])); result += pow(noisy[noiseindex][i] - buf, 2); } return result; }