void InitDE431(const char* filepath) { ephem = jpl_init_ephemeris(filepath, nams, vals); if(jpl_init_error_code() != 0) { StelApp::getInstance().getCore()->setDe431Active(false); qDebug() << "Error "<< jpl_init_error_code() << "at DE431 init:" << jpl_init_error_message(); } else { initDone = true; double jd1, jd2; jd1=jpl_get_double(ephem, JPL_EPHEM_START_JD); jd2=jpl_get_double(ephem, JPL_EPHEM_END_JD); qDebug() << "DE431 init successful. startJD=" << QString::number(jd1, 'f', 4) << "endJD=" << QString::number(jd2, 'f', 4); } }
int main( const int argc, const char **argv) { char nams[JPL_MAX_N_CONSTANTS][6], buff[102]; double vals[JPL_MAX_N_CONSTANTS]; double max_err_found[10][6]; int line, n_failures[10]; size_t i, j; unsigned n_constants, n_columns; int output_frequency = 100; const char *ephfile_name = argv[1]; double start_jd, end_jd; double roundoff_error = 0.; bool report_all_errors = false; bool pause_on_errors = true; FILE *testfile; clock_t timer; void *ephem; const char *test_file_name = NULL; #if defined( __GNUC__) && !defined( __MINGW32__) const char path_separator = '/'; #else const char path_separator = '\\'; #endif const char *error_messages[7] = { "Result outside acceptable error tolerance", "Outside date range", "Read error", "Quantity not in index", "? Obsolete error; shouldn't happen", "Invalid index", "Seek error" }; const int n_errors = sizeof( error_messages) / sizeof( error_messages[0]); /***** Write a fingerprint to the screen. ***********************************/ setvbuf( stdout, NULL, _IONBF, 0); puts("\n JPL test-ephemeris program (v.1.2)\n" " C version translated from the original JPL FORTRAN code.\n"); if( argc < 2) error_exit( -1); for( i = 0; i < 10; i++) for( j = 0; j < 6; j++) max_err_found[i][j] = 0.; for( i = 2; i < (size_t)argc; i++) if( argv[i][0] == '-') switch( argv[i][1]) { case 'a': case 'A': report_all_errors = true; break; case 'f': case 'F': output_frequency = atoi( argv[i] + 2); break; case 'n': case 'N': pause_on_errors = false; break; case 't': case 'T': test_file_name = argv[i] + 2; break; default: printf( "Unrecognized option '%s'\n", argv[i]); error_exit( -2); break; } /****** Print the ephemeris constants. **************************************/ ephem = jpl_init_ephemeris( ephfile_name, nams, vals); if( !ephem) { printf( "Ephemeris file '%s' not loaded\n", ephfile_name); printf( "Error code: %d\n", jpl_init_error_code( )); error_exit( -2); } else printf( "Ephemeris initialized\n"); n_constants = (unsigned)jpl_get_long( ephem, JPL_EPHEM_N_CONSTANTS); printf( "%u constants\n", n_constants); if( n_constants > JPL_MAX_N_CONSTANTS) n_constants = JPL_MAX_N_CONSTANTS; start_jd = jpl_get_double( ephem, JPL_EPHEM_START_JD), end_jd = jpl_get_double( ephem, JPL_EPHEM_END_JD), printf("%.9f %.9f %.9f\n", start_jd, end_jd, jpl_get_double( ephem, JPL_EPHEM_STEP)); n_columns = (n_constants + 1) / 2; for( i = 0; i < (size_t)n_columns; i++) { printf("%.6s %24.16E",nams[i],vals[i]); if( i + n_columns < n_constants) printf(" %.6s %24.16E",nams[i + n_columns],vals[i + n_columns]); printf( "\n"); } printf( "emrat = %.15f AU = %.5f\n", jpl_get_double( ephem, JPL_EPHEM_EARTH_MOON_RATIO), jpl_get_double( ephem, JPL_EPHEM_AU_IN_KM)); /****** Skip the test points file header comments. *************************/ if( test_file_name) strcpy( buff, test_file_name); else { const char *extension; strcpy( buff, ephfile_name); for( i = strlen( buff); i && buff[i - 1] != path_separator; i--) ; strcpy( buff + i, "testpo"); extension = strchr( ephfile_name + i, '.'); if( extension) strcat( buff + i, extension); else sprintf( buff + strlen( buff), ".%3ld", jpl_get_long( ephem, JPL_EPHEM_EPHEMERIS_VERSION)); } testfile = fopen( buff, "r"); if( !testfile) { printf( "Test data file '%s' not found\n", buff); error_exit( -3); } while( fgets( buff, 100, testfile) && memcmp( buff, "EOT", 3)) ; puts(" LINE JED t# c# x# --- JPL value --- " "--- user value -- -- difference --"); line=0; timer = clock( ); for( i = 0; i < 10; i++) n_failures[i] = 0; while( fgets( buff, 100, testfile) != NULL) { int err_code, ntarg, nctr, ncoord; double del, et; double r[6], xi, xi_computed; bool fatal_error = false, report_this_error = false; /***** Read a value from the test case; Skip if not within the time-range of the present version of the ephemeris. */ line++; if( sscanf( buff + 15," %lf %d %d %d %lf", &et, &ntarg, &nctr, &ncoord, &xi) != 5) { printf( "Failure to parse line %d:\n%s\n", line, buff); fatal_error = true; } else { err_code = jpl_pleph(ephem, et, ntarg, nctr, r, 1); if( err_code > 0 || err_code < -n_errors) { printf( "Internal error: unknown error code %d\n", err_code); fatal_error = true; } else if( !roundoff_error) { char *tptr = strchr( buff + 30, '.'); assert( tptr); tptr++; roundoff_error = .5; while( *tptr >= '0' && *tptr <= '9') { tptr++; roundoff_error /= 10.; } } } if( fatal_error) { printf( "\nThis error shouldn't happen, ever. It indicates a bug\n"); printf( "that should be fixed.\n"); printf( "Please contact [email protected] and report this.\n"); return( -1); } xi_computed = r[ncoord - 1]; del = fabs( xi_computed - xi); if( err_code) { n_failures[-err_code]++; if( n_failures[-err_code] == 1 || report_all_errors) report_this_error = true; } else { const double tolerance = max_accepted_error( ntarg, ncoord) + fabs( xi) * 1e-14 + roundoff_error; const unsigned idx = (ntarg <= 13 ? 0 : ntarg - 13); if( max_err_found[idx][ncoord - 1] < del - tolerance) max_err_found[idx][ncoord - 1] = del - tolerance; if( del > tolerance) { n_failures[0]++; if( n_failures[-err_code] == 1 || report_all_errors) { report_this_error = true; printf( "***** warning : next difference >= tolerance *****\n"); printf( "%s", buff); } } } if( (!err_code && !(line % output_frequency)) || report_this_error) printf("%4d %10.1f %2d %2d %2d %25.20f %25.20f %22.20f\n", line,et,ntarg,nctr,ncoord,xi, xi_computed, xi_computed - xi); if( report_this_error) { printf( "Error message: '%s'\n", error_messages[-err_code]); if( err_code == JPL_EPH_OUTSIDE_RANGE) { const double J2000 = 2451545.; printf( "WARNING: The test file tests items outside the range\n"); printf( "of this ephemeris!\n"); printf( "The input ephemeris file covers years from %.1f to %.1f.\n", 2000. + (start_jd - J2000) / 365.25, 2000. + (end_jd - J2000) / 365.25); printf( "The test is for the year %.1f\n", 2000. + (et - J2000) / 365.25); printf( "It's common for DE files to be built that cover a subset of the\n"); printf( "range of the original ephemerides, so this may not be an error.\n"); } if( !report_all_errors) { printf( " Further errors of this type won't be shown, but you'll get a count\n"); printf( " of how many are found. (Use the '-a' switch to report all errors.)\n"); } if( pause_on_errors) { printf( " Hit any key:\n"); getchar( ); } } } for( i = 0; i < 10; i++) for( j = 0; j < 6; j++) if( max_err_found[i][j]) printf( "%d %d %.8e %c\n", (int)i, (int)j + 1, max_err_found[i][j], (max_err_found[i][j] > 0.) ? '*' : ' '); printf( "%d lines read and tested in %.3f seconds\n", line, (double)( clock( ) - timer) / (double)CLOCKS_PER_SEC); for( i = 0; i < (size_t)n_errors; i++) if( n_failures[i]) printf( "%d lines failed with error code %d ('%s').\n", n_failures[i], -(int)i, error_messages[i]); fclose( testfile); jpl_close_ephemeris( ephem); return( 0); }
static int planet_posn_raw( int planet_no, const double jd, double *vect_2000) { static void *ps_1996_data[10]; const int jpl_center = 11; /* default to heliocentric */ int i, rval = 0; static const char *jpl_filename = NULL; static void *jpl_eph = NULL; const int bc405_start = 100; const int calc_vel = (planet_no & PLANET_POSN_VELOCITY_FLAG) ? 1 : 0; planet_no &= ~PLANET_POSN_VELOCITY_FLAG; if( !planet_no) /* the sun */ { vect_2000[0] = vect_2000[1] = vect_2000[2] = 0.; if( !jd && jpl_eph) /* return version data: */ { vect_2000[0] = (double)jpl_get_long( jpl_eph, JPL_EPHEM_EPHEMERIS_VERSION); vect_2000[1] = jpl_get_double( jpl_eph, JPL_EPHEM_START_JD); vect_2000[2] = jpl_get_double( jpl_eph, JPL_EPHEM_END_JD); } return( 0); } if( planet_no >= bc405_start && planet_no < bc405_start + 300) { double temp_loc[4]; rval = asteroid_position_raw( planet_no - bc405_start, jd, temp_loc); if( debug_level > 8) debug_printf( "JD %f, minor planet %d: (%f %f %f)\n", jd, planet_no, temp_loc[0], temp_loc[1], temp_loc[2]); memcpy( vect_2000, temp_loc, 3 * sizeof( double)); return( rval); } if( !jpl_filename) { FILE *ifile; #if defined (_WIN32) || defined( __WATCOMC__) jpl_filename = get_environment_ptr( "JPL_FILENAME"); #else jpl_filename = get_environment_ptr( "LINUX_JPL_FILENAME"); #endif if( *jpl_filename) jpl_eph = jpl_init_ephemeris( jpl_filename, NULL, NULL); if( !jpl_eph) if( (ifile = fopen_ext( "jpl_eph.txt", "fcrb")) != NULL) { char buff[100]; while( !jpl_eph && fgets_trimmed( buff, sizeof( buff), ifile)) if( *buff && *buff != ';') { jpl_eph = jpl_init_ephemeris( buff, NULL, NULL); if( !jpl_eph) { char tname[255]; make_config_dir_name( tname, buff); jpl_eph = jpl_init_ephemeris( tname, NULL, NULL); } } if( debug_level) debug_printf( "Ephemeris file %s\n", buff); fclose( ifile); } if( debug_level && jpl_eph) { debug_printf( "\nEphemeris time span years %.3f to %.3f\n", (jpl_get_double( jpl_eph, JPL_EPHEM_START_JD) - J0) / 365.25, (jpl_get_double( jpl_eph, JPL_EPHEM_END_JD) - J0) / 365.25); debug_printf( "Ephemeris version %ld\n", jpl_get_long( jpl_eph, JPL_EPHEM_EPHEMERIS_VERSION)); debug_printf( "Kernel size %ld, record size %ld, swap_bytes %ld\n", jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_SIZE), jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_RECORD_SIZE), jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_SWAP_BYTES)); debug_printf( "ncon = %ld AU=%f emrat = %f\n", jpl_get_long( jpl_eph, JPL_EPHEM_N_CONSTANTS), jpl_get_double( jpl_eph, JPL_EPHEM_AU_IN_KM), jpl_get_double( jpl_eph, JPL_EPHEM_EARTH_MOON_RATIO)); } } if( jpl_eph) { double state[6]; /* DE gives both posn & velocity */ int failure_code; if( planet_no < 0) /* flag to unload everything */ { jpl_close_ephemeris( jpl_eph); jpl_eph = NULL; jpl_filename = NULL; return( 0); } else if( planet_no == 10) failure_code = jpl_pleph( jpl_eph, jd, 10, 3, state, calc_vel); else failure_code = jpl_pleph( jpl_eph, jd, (planet_no == 3) ? 13 : planet_no, jpl_center, state, calc_vel); if( !failure_code) /* we're done */ { if( debug_level > 8) debug_printf( "JD %f, planet %d: (%f %f %f)\n", jd, planet_no, state[0], state[1], state[2]); equatorial_to_ecliptic( state); memcpy( vect_2000, state + calc_vel, 3 * sizeof( double)); return( 0); } else if( debug_level) debug_printf( "Failed: JD %f, planet %d, code %d\n", jd, planet_no, failure_code); } if( planet_no == 10) /* the moon */ { double tloc[4]; if( !compute_elp_xyz( NULL, (jd - J2000) / 36525., 0., tloc)) for( i = 0; i < 3; i++) vect_2000[i] = tloc[i] / AU_IN_KM; else { static int first_time = 1; rval = -3; if( first_time) generic_message_box( get_find_orb_text( 2019), "o"); first_time = 0; compute_rough_planet_loc( (jd - J2000) / 36525., 10, vect_2000); } return( rval); } if( planet_no < 0) /* flag to unload everything */ { for( i = 0; i < 10; i++) if( ps_1996_data[i]) { unload_ps1996_series( ps_1996_data[i]); ps_1996_data[i] = NULL; } return( 0); } if( !ps_1996_data[planet_no]) ps_1996_data[planet_no] = load_ps1996_series( NULL, jd, planet_no); if( !ps_1996_data[planet_no]) rval = -1; else if( get_ps1996_position( jd, ps_1996_data[planet_no], vect_2000, 0)) { unload_ps1996_series( ps_1996_data[planet_no]); ps_1996_data[planet_no] = load_ps1996_series( NULL, jd, planet_no); if( !ps_1996_data[planet_no]) rval = -2; else if( get_ps1996_position( jd, ps_1996_data[planet_no], vect_2000, 0)) rval = -3; } if( !rval) equatorial_to_ecliptic( vect_2000); else { static int first_time = 1; if( first_time) { generic_message_box( get_find_orb_text( 2020), "o"); debug_printf( "Loading ps_1996: rval %d, planet %d, JD %f\n", rval, planet_no, jd); } first_time = 0; if( planet_no > 0 && planet_no < 9) compute_rough_planet_loc( (jd - J2000) / 36525., planet_no, vect_2000); } return( rval); }
int merge_jpl_files( const char *output_filename, const int n_input_files, const char **input_filenames) { void *jpl_eph = jpl_init_ephemeris( input_filenames[0], NULL, NULL); int i, j, de_number, kernel_size, kernel_days, rval = 0; FILE *ifile, *ofile = NULL; struct jpl_file *idata; char *buff = NULL; if( !jpl_eph) return( MERGE_ERR_INITIALIZING); de_number = (int)jpl_get_long( jpl_eph, JPL_EPHEM_EPHEMERIS_VERSION); kernel_days = (int)( jpl_get_double( jpl_eph, JPL_EPHEM_STEP) + .5); kernel_size = jpl_get_long( jpl_eph, JPL_EPHEM_KERNEL_SIZE); jpl_close_ephemeris( jpl_eph); idata = (struct jpl_file *)calloc( n_input_files, sizeof( struct jpl_file)); if( !idata) return( MERGE_ERR_INITIALIZING); for( i = 0; !rval && i < n_input_files; i++) { ifile = fopen( input_filenames[i], "rb"); if( !ifile) rval = MERGE_ERR_OPENING; else { if( fread( idata[i].header, 84, 3, ifile) != 3) rval = MERGE_ERR_READING_HEADER; fclose( ifile); if( !rval) { if( memcmp( idata[i].header, "JPL Planetary Ephemeris", 23)) rval = MERGE_ERR_NOT_A_JPL_EPHEM; else if( de_number != atoi( idata[i].header + 26)) { printf( "You can't merge files from different DE ephemerides\n"); printf( "'%s' is from DE-%d\n", input_filenames[i], atoi( idata[i].header + 26)); printf( "'%s' is from DE-%d\n", input_filenames[0], de_number); rval = MERGE_ERR_MISMATCHED_VERSIONS; } } idata[i].jd_start = atol( idata[i].header + 102); idata[i].jd_end = atol( idata[i].header + 186); idata[i].filename = input_filenames[i]; } } if( rval) { free( idata); return( rval); } /* OK, now sort by date: */ for( i = 0; i < n_input_files; i++) for( j = 0; j < i; j++) if( idata[i].jd_start < idata[j].jd_start) { struct jpl_file temp = idata[i]; idata[i] = idata[j]; idata[j] = temp; } printf( "Merging:\nJD Start JD End Filename\n"); for( i = 0; i < n_input_files; i++) printf( "%8ld.5 %8ld.5 %s\n", idata[i].jd_start, idata[i].jd_end, idata[i].filename); /* Check to be sure the files overlap: */ for( i = 0; i < n_input_files - 1; i++) if( idata[i + 1].jd_start > idata[i].jd_end) { printf( "ERROR: there is a gap between '%s' and '%s'.\n", idata[i].filename, idata[i + 1].filename); rval = MERGE_ERR_GAP_IN_DATA; } if( !rval) { ofile = fopen( output_filename, "wb"); if( !ofile) { printf( "Couldn't open output file '%s'\n", output_filename); rval = MERGE_ERR_OPENING_2; } } if( !rval) { buff = (char *)malloc( kernel_size); if( !buff) rval = MERGE_ERR_OUT_OF_MEMORY; } for( i = 0; !rval && i < n_input_files; i++) { int n_blocks; ifile = fopen( idata[i].filename, "rb"); if( !ifile) rval = MERGE_ERR_OPENING_3; if( !i) for( j = 0; !rval && j < 2; j++) /* copy out two header blocks */ { if( fread( buff, kernel_size, 1, ifile) != 1) rval = MERGE_ERR_DATA_READ; else if( fwrite( buff, kernel_size, 1, ofile) != 1) rval = MERGE_ERR_DATA_WRITE; } else fseek( ifile, 2L * kernel_size, SEEK_SET); if( i == n_input_files - 1) n_blocks = (idata[i].jd_end - idata[i].jd_start) / kernel_days; else n_blocks = (idata[i + 1].jd_start - idata[i].jd_start) / kernel_days; while( !rval && n_blocks--) { if( fread( buff, kernel_size, 1, ifile) != 1) rval = MERGE_ERR_DATA_READ_2; else if( fwrite( buff, kernel_size, 1, ofile) != 1) rval = MERGE_ERR_DATA_WRITE_2; } if( !rval && i == n_input_files - 1) /* patch up ending date */ { fseek( ofile, 2L * 84L, SEEK_SET); if( fwrite( idata[i].header + 2 * 84, 84, 1, ofile) != 1) rval = MERGE_ERR_DATA_WRITE_HEADER; fseek( ifile, 2660L, SEEK_SET); if( !rval) { if( fread( buff, 8, 1, ifile) != 1) rval = MERGE_ERR_DATA_READ_3; fseek( ofile, 2660L, SEEK_SET); if( !rval && fwrite( buff, 8, 1, ofile) != 1) rval = MERGE_ERR_DATA_WRITE_3; } } fclose( ifile); } // free memory and close filehandles if( buff) free( buff); free( idata); if( ofile) fclose( ofile); return( rval); }