/* Generic main function for the tessb* programs. */ #include #include #include #include #include "logger.h" #include "version.h" #include "grav_tess.h" #include "glq.h" #include "constants.h" #include "geometry.h" #include "parsers.h" #include "tessb_main.h" #include "linalg.h" #include /* Print the help message for tessh* programs */ void print_tessb_help(const char *progname) { printf("MAGNETIC MAG_TESSEROIDS\n"); printf("Usage: %s MODELFILE [OPTIONS]\n\n", progname); if(strcmp(progname + 4, "pot") == 0) { printf("Calculate the potential due to a tesseroid model on\n"); } else { printf("Calculate the %s component due to a tesseroid model on\n", progname + 4); } printf("TODO\n"); } /* Run the main for a generic tessh* program */ int run_tessb_main(int argc, char **argv, const char *progname, double (*field)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ), double ratio1, double ratio2, double ratio3) { TESSB_ARGS args; GLQ *glq_lon, *glq_lat, *glq_r; MAG_TESSEROID *model; int modelsize, rc, line, points = 0, error_exit = 0, bad_input = 0; char buff[10000]; double lon, lat, height, res; /*variables for precalculation of trigonometrical functions for tesseroid centers*/ double cos_a2, sin_a2, cos_b2, sin_b2; /*variables for precalculation of trigonometrical functions for grid points*/ double lon_prev, lat_prev; double cos_a2_prev, sin_a2_prev, cos_b2_prev, sin_b2_prev; FILE *logfile = NULL, *modelfile = NULL; time_t rawtime; clock_t tstart; struct tm * timeinfo; double (*field1)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ); double (*field2)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ); double (*field3)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ); void (*field_triple)(MAG_TESSEROID, double, double, double, GLQ, GLQ, GLQ, double*); double ggt_1, ggt_2, ggt_3; double gtt_v[3]; int n_tesseroid; log_init(LOG_INFO); rc = parse_tessb_args(argc, argv, progname, &args, &print_tessb_help); if(rc == 2) { return 0; } if(rc == 1) { log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); return 1; } /* Set the appropriate logging level and log to file if necessary */ if(!args.verbose) { log_init(LOG_WARNING); } if(args.logtofile) { logfile = fopen(args.logfname, "w"); if(logfile == NULL) { log_error("unable to create log file %s", args.logfname); log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); return 1; } log_tofile(logfile, LOG_DEBUG); } /* Check if a custom distance-size ratio is given */ if(args.ratio1 != 0) { ratio1 = args.ratio1; } if(args.ratio2 != 0) { ratio2 = args.ratio2; } if(args.ratio3 != 0) { ratio3 = args.ratio3; } /* Print standard verbose */ log_info("%s (Tesseroids project) %s", progname, tesseroids_version); time(&rawtime); timeinfo = localtime(&rawtime); log_info("(local time) %s", asctime(timeinfo)); log_info("Use recursive division of tesseroids: %s", args.adaptative ? "True" : "False"); log_info("Distance-size ratio1 for recusive division: %g", ratio1); log_info("Distance-size ratio2 for recusive division: %g", ratio2); log_info("Distance-size ratio3 for recusive division: %g", ratio3); /* Make the necessary GLQ structures */ log_info("Using GLQ orders: %d lon / %d lat / %d r", args.lon_order, args.lat_order, args.r_order); glq_lon = glq_new(args.lon_order, -1, 1); glq_lat = glq_new(args.lat_order, -1, 1); glq_r = glq_new(args.r_order, -1, 1); if(glq_lon == NULL || glq_lat == NULL || glq_r == NULL) { log_error("failed to create required GLQ structures"); log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); if(args.logtofile) fclose(logfile); return 1; } /* Read the tesseroid model file */ log_info("Reading magnetic tesseroid model from file %s", args.modelfname); modelfile = fopen(args.modelfname, "r"); if(modelfile == NULL) { log_error("failed to open model file %s", args.modelfname); log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); if(args.logtofile) fclose(logfile); return 1; } model = read_mag_tess_model(modelfile, &modelsize); fclose(modelfile); if(modelsize == 0) { log_error("tesseroid file %s is empty", args.modelfname); log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); if(args.logtofile) fclose(logfile); return 1; } if(model == NULL) { log_error("failed to read model from file %s", args.modelfname); log_warning("Terminating due to bad input"); log_warning("Try '%s -h' for instructions", progname); if(args.logtofile) fclose(logfile); return 1; } log_info("Total of %d tesseroid(s) read", modelsize); /* Print a header on the output with provenance information */ if(strcmp(progname + 4, "pot") == 0) { printf("# Potential calculated with %s %s:\n", progname, tesseroids_version); } else { printf("# %s component calculated with %s %s:\n", progname+4, progname, tesseroids_version); } printf("# local time: %s", asctime(timeinfo)); printf("# model file: %s (%d tesseroids)\n", args.modelfname, modelsize); printf("# GLQ order: %d lon / %d lat / %d r\n", args.lon_order, args.lat_order, args.r_order); printf("# Use recursive division of tesseroids: %s\n", args.adaptative ? "True" : "False"); printf("# Distance-size ratio1 for recusive division: %g\n", ratio1); printf("# Distance-size ratio2 for recusive division: %g\n", ratio2); printf("# Distance-size ratio3 for recusive division: %g\n", ratio3); /////////////ELDAR BAYKIEV////////////// /* Assign pointers to functions that calculate gravity gradient tensor components */ if (!strcmp("tessbx", progname)) { field1 = &tess_gxx; field2 = &tess_gxy; field3 = &tess_gxz; field_triple = &tess_gxx_gxy_gxz; } if (!strcmp("tessby", progname)) { field1 = &tess_gxy; field2 = &tess_gyy; field3 = &tess_gyz; field_triple = &tess_gxy_gyy_gyz; } if (!strcmp("tessbz", progname)) { field1 = &tess_gxz; field2 = &tess_gyz; field3 = &tess_gzz; field_triple = &tess_gxz_gyz_gzz; } /////////////ELDAR BAYKIEV////////////// /* Read each computation point from stdin and calculate */ log_info("Calculating (this may take a while)..."); tstart = clock(); /////////////// lon_prev = 0; lat_prev = 0; for(line = 1; !feof(stdin); line++) { if(fgets(buff, 10000, stdin) == NULL) { if(ferror(stdin)) { log_error("problem encountered reading line %d", line); error_exit = 1; break; } } else { /* Check for comments and blank lines */ if(buff[0] == '#' || buff[0] == '\r' || buff[0] == '\n') { printf("%s", buff); continue; } if(sscanf(buff, "%lf %lf %lf", &lon, &lat, &height) != 3) { log_warning("bad/invalid computation point at line %d", line); log_warning("skipping this line and continuing"); bad_input++; continue; } /* Need to remove \n and \r from end of buff first to print the result in the end */ strstrip(buff); /////////////ELDAR BAYKIEV////////////// res = 0; if(args.adaptative) { for(n_tesseroid = 0; n_tesseroid < modelsize; n_tesseroid++) { gtt_v[0] = 0; gtt_v[1] = 0; gtt_v[2] = 0; double B_to_H = model[n_tesseroid].suscept/(M_0);//IMPORTANT double M_vect[3] = {model[n_tesseroid].Bx * B_to_H, model[n_tesseroid].By * B_to_H, model[n_tesseroid].Bz * B_to_H}; double M_vect_p[3] = {0, 0, 0}; conv_vect_cblas(M_vect, (model[n_tesseroid].w + model[n_tesseroid].e)*0.5, (model[n_tesseroid].s + model[n_tesseroid].n)*0.5, lon, lat, M_vect_p); ggt_1 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field1, ratio1); ggt_2 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field2, ratio2); ggt_3 = calc_tess_model_adapt(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field3, ratio3); res = res + M_0*EOTVOS2SI*(ggt_1 * M_vect_p[0] + ggt_2 * M_vect_p[1] + ggt_3 * M_vect_p[2]) /(G*model[n_tesseroid].density*4*PI); //printf("res %g\n", res); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// } else { //precalculate trigonometrical functions if(lon == lon_prev) { cos_b2 = cos_b2_prev; sin_b2 = sin_b2_prev; } else { cos_b2 = cos(DEG2RAD*lon); sin_b2 = sin(DEG2RAD*lon); } if(lat == lat_prev) { cos_a2 = cos_a2_prev; sin_a2 = sin_a2_prev; } else { cos_a2 = cos(PI/2.0-DEG2RAD*lat); sin_a2 = sin(PI/2.0-DEG2RAD*lat); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// for(n_tesseroid = 0; n_tesseroid < modelsize; n_tesseroid++) { gtt_v[0] = 0; gtt_v[1] = 0; gtt_v[2] = 0; //ELDAR: TODO: PRECALCULATE SIC COSINE TABLES double B_to_H = model[n_tesseroid].suscept/(M_0);//IMPORTANT double M_vect[3] = {model[n_tesseroid].Bx * B_to_H, model[n_tesseroid].By * B_to_H, model[n_tesseroid].Bz * B_to_H}; double M_vect_p[3] = {0, 0, 0}; //conv_vect_cblas(M_vect, (model[n_tesseroid].w + model[n_tesseroid].e)*0.5, (model[n_tesseroid].s + model[n_tesseroid].n)*0.5, lon, lat, M_vect_p); conv_vect_cblas_precalc(M_vect, model[n_tesseroid].cos_a1, model[n_tesseroid].sin_a1, model[n_tesseroid].cos_b1, model[n_tesseroid].sin_b1, cos_a2, sin_a2, cos_b2, sin_b2, M_vect_p); calc_tess_model_triple(&model[n_tesseroid], 1, lon, lat, height + MEAN_EARTH_RADIUS, glq_lon, glq_lat, glq_r, field_triple, gtt_v); res = res + M_0*EOTVOS2SI*(gtt_v[0] * M_vect_p[0] + gtt_v[1] * M_vect_p[1] + gtt_v[2] * M_vect_p[2]) /(G*model[n_tesseroid].density*4*PI); } lon_prev = lon; lat_prev = lat; cos_a2_prev = cos_a2; sin_a2_prev = sin_a2; cos_b2_prev = cos_b2; sin_b2_prev = sin_b2; ///////////////////////////////////////////////////////////////////////////////////////////////////////// } printf("%s %.15g\n", buff, res); points++; } } if(bad_input) { log_warning("Encountered %d bad computation points which were skipped", bad_input); } if(error_exit) { log_warning("Terminating due to error in input"); log_warning("Try '%s -h' for instructions", progname); } else { log_info("Calculated on %d points in %.5g seconds", points, (double)(clock() - tstart)/CLOCKS_PER_SEC); } /* Clean up */ free(model); glq_free(glq_lon); glq_free(glq_lat); glq_free(glq_r); log_info("Done"); if(args.logtofile) fclose(logfile); return 0; }