Changeset 2301 for trunk/psLib/src/astronomy/psTime.c
- Timestamp:
- Nov 8, 2004, 2:36:13 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/astronomy/psTime.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astronomy/psTime.c
r2273 r2301 5 5 * 6 6 * A collection of functions are required by psLib to manipulate time data. These functions primarily consist 7 * of conversions between specific time formats. PSLib currently uses the UNIX timeval time system as the 8 * base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. TAI 9 * time varies over time due to the earth's rotation and the movement of the continental plates. 7 * of conversions between specific time formats. They use the UNIX timeval time system as the 8 * base upon which International Atomic Time (TAI) and Universal Time Coordinated (UTC) are calculated. 10 9 * 11 10 * @author Ross Harman, MHPCC 12 11 * 13 * @version $Revision: 1. 39$ $Name: not supported by cvs2svn $14 * @date $Date: 2004-11-0 4 01:04:57$12 * @version $Revision: 1.40 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2004-11-09 00:36:13 $ 15 14 * 16 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 21 20 #include <string.h> 22 21 #include <math.h> 22 #include <ctype.h> 23 23 24 24 #include "psTime.h" … … 31 31 #include "psMetadata.h" 32 32 #include "psMetadataIO.h" 33 #include "psLookupTable.h" 33 34 #include "psConstants.h" 34 35 #include "psAstronomyErrors.h" 35 36 36 #ifndef SER7_FILE37 #define SER7_FILE "../../data/ser7.dat"38 #pragma warning SER7_FILE was not defined in the makefile.37 #ifndef TIME_CONFIG_FILE 38 #define TIME_CONFIG_FILE "../../config/time.config" 39 #pragma warning TIME_CONFIG_FILE was not defined in the makefile. 39 40 #endif 40 41 #ifndef TAIUTC_FILE42 #define TAIUTC_FILE "../../data/tai-utc.dat"43 #pragma warning TAIUTC_FILE was not defined in the makefile.44 #endif45 46 41 47 42 /** Sidereal angular conversion from seconds to radians for GMST in seconds (i.e. pi/(180*240)) */ … … 72 67 #define USEC_PER_DAY 86400000000.0 73 68 74 /** Max size of a line read */75 #define LINESIZE 102476 77 78 69 /** Time metadata read from config file */ 79 70 static psMetadata *timeMetadata = NULL; 80 71 81 82 /** Read TAI/UTC data file. 83 * 84 * Reads TAI/UTC data file. 85 * 86 * @return psImage*: Two-dimensional array with table data. 87 */ 88 static psImage* readTaiUtcFile( 89 const char *fileName ///< Name of file to read. 90 ); 91 92 93 /** Read SER7 data file. 94 * 95 * Reads SER7 data file. 96 * 97 * @return psImage*: Two-dimensional array with table data. 98 */ 99 static psImage* readSer7File( 100 const char *fileName ///< Name of file to read. 101 ); 102 103 104 /** Read finals data file. 105 * 106 * Reads finals data file. 107 * 108 * @return psImage*: Two-dimensional array with table data. 109 */ 110 /* not yet used 111 static psImage* readFinalsFile( 112 char *fileName ///< Name of file to read. 113 ); 114 */ 115 116 /** Read EOPC data file. 117 * 118 * Reads EOPC data file. 119 * 120 * @return psImage*: Two-dimensional array with table data. 121 */ 122 /* not yet used 123 static psImage* readEopcFile( 124 char *fileName ///< Name of file to read. 125 ); 126 */ 127 128 /** Lookup and interpolate TAI-UTC data 129 * 130 * Interpolates TAI-UTC data, given time in MJD format. 131 * 132 * @return double: Interpolated value. 133 */ 134 static double lookupTaiUtcTable( 135 const psTime *time ///< time to lookup. 136 ); 137 138 /** Lookup and interpolate polar or UT1-UTC data 139 * 140 * Interpolates TAI-UT1 or polar coordinate data, given time in MJD format. 141 * 142 * @return double: Interpolated value. 143 */ 144 static double lookupSer7Table( 145 const psTime *time, ///< time to lookup. 146 psS32 col ///< Column to lookup. 147 ); 148 149 static psImage* readTaiUtcFile(const char *fileName) 150 { 151 char line[LINESIZE]; 152 psS32 j = 0; 153 psS32 maxLines = 1000; 154 psF64 *ptr = NULL; 155 psImage *table = NULL; 156 FILE *fd = NULL; 157 158 159 fd=fopen(fileName, "r"); 160 if(fd==NULL) { 161 psError(PS_ERR_IO,true, 162 PS_ERRORTEXT_psTime_FILE_NOT_FOUND, 163 fileName,"Tai-Utc"); 164 return NULL; 165 } 166 167 // Table shouldn't be larger than 100 rows. Select columns are read based on indices. 168 table = psImageAlloc(4, maxLines, PS_TYPE_F64); 169 170 while(fgets(line, LINESIZE, fd) != NULL) { 171 if(j>=maxLines) { 172 psError(PS_ERR_IO,true, 173 PS_ERRORTEXT_psTime_FILE_TOO_MANY_ROWS, 174 fileName,maxLines); 175 return NULL; 176 psFree(table); 177 } 178 179 ptr = table->data.F64[j++]; 180 *ptr = atof(line+16); // MJD 181 *(ptr+1) = atof(line+38); // TAI-UTC 182 *(ptr+2) = atof(line+59); // Contant #1 183 *(ptr+3) = atof(line+69); // Contant #2 184 } 185 186 *(psU32 *)&table->numRows = j; 187 188 p_psMemSetPersistent(table,true); 189 p_psMemSetPersistent(table->data.V,true); 190 p_psMemSetPersistent(table->rawDataBuffer,true); 191 192 return table; 193 } 194 195 static psImage* readSer7File(const char *fileName) 196 { 197 psBool beginRecord = false; 198 char line[LINESIZE]; 199 psS32 j = 0; 200 psS32 maxLines = 400; 201 psImage *table = NULL; 202 FILE *fd = NULL; 203 204 205 fd=fopen(fileName, "r"); 206 if(fd==NULL) { 207 psError(PS_ERR_IO,true, 208 PS_ERRORTEXT_psTime_FILE_NOT_FOUND, 209 fileName,"Ser7"); 210 return NULL ; 211 } 212 213 // Table shouldn't be larger than 400 rows. All columns in area of interest are read. 214 table = psImageAlloc(7, maxLines, PS_TYPE_F64); 215 216 while(fgets(line, LINESIZE, fd) != NULL) { 217 218 // Stop parsing after finding "These" in data file after read has began 219 if(beginRecord) { 220 if(strstr(line, "These")!=NULL) { 221 beginRecord = false; 222 break; 223 } 224 225 if(j>=maxLines) { 226 psError(PS_ERR_IO,true, 227 PS_ERRORTEXT_psTime_FILE_TOO_MANY_ROWS, 228 fileName,maxLines); 229 return NULL; 230 psFree(table); 231 } 232 psF64 *ptr = table->data.F64[j++]; 233 sscanf(line, "%lf %lf %lf %lf %lf %lf %lf", ptr, ptr+1, ptr+2, ptr+3, ptr+4, ptr+5, ptr+6); 234 } 235 236 // Start parsing after finding "x(arcsec)" in data file 237 if(strstr(line, "x(arcsec)") != NULL) { 238 beginRecord = true; 239 } 240 } 241 *(psU32 *)&table->numRows = j; 242 243 p_psMemSetPersistent(table,true); 244 p_psMemSetPersistent(table->data.V,true); 245 p_psMemSetPersistent(table->rawDataBuffer,true); 246 247 return table; 248 } 249 250 251 static double lookupTaiUtcTable(const psTime *time) 252 { 253 psS32 hiIdx = 0; 254 psS32 loIdx = 0; 255 psS32 numRows = 0; 256 double jd = 0.0; 257 double mjd = 0.0; 258 double out = 0.0; 259 double denom = 0.0; 260 double const1 = 0.0; 261 double const2 = 0.0; 262 double const3 = 0.0; 263 static psImage* table = NULL; 264 265 if (table == NULL) { 266 table = readTaiUtcFile(TAIUTC_FILE); 267 if (table == NULL) { 268 psAbort(__func__,"Failed to read tai-utc.dat file"); 269 } 270 } 271 272 // Number of rows is the number of rows of data read from the data file 273 numRows = table->numRows; 274 275 // Determine Julian and modified Julian dates used in table lookup and time delta calculation 276 jd = psTimeToJD(time); 277 mjd = psTimeToMJD(time); 278 279 // Variable in should be in MJD format 280 if(jd < table->data.F64[0][0]) { // MJD time before start of table 281 return 0.0; 282 } else if(jd > table->data.F64[numRows-1][0]) { // MJD time after end of table 283 return table->data.F64[numRows-1][1]; 284 } else { // All other times..interpolate 285 while(jd > table->data.F64[hiIdx][0]) { 286 hiIdx++; 287 if(hiIdx >= numRows) { 288 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 289 PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLE, 290 jd, "TAI-UTC"); 291 return 0.0; 292 } 293 } 294 loIdx = hiIdx--; 295 if(loIdx < 0) { 296 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 297 PS_ERRORTEXT_psTime_TIME_PREDATES_TABLE, 298 jd, "TAI-UTC"); 72 /** Static function prototypes */ 73 static char *cleanString(char *inString, int sLen); 74 static char* getToken(char **inString, char *delimiter, psParseErrorType *status); 75 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables); 76 77 /** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null 78 * terminated copy of the original input string. */ 79 static char *cleanString(char *inString, int sLen) 80 { 81 char *ptrB = NULL; 82 char *ptrE = NULL; 83 char *cleaned = NULL; 84 85 86 ptrB = inString; 87 88 /* Skip over leading # or whitespace */ 89 while (isspace(*ptrB) || *ptrB=='#') { 90 ptrB++; 91 } 92 93 /* Skip over trailing whitespace, null terminators, and # characters */ 94 ptrE = inString + sLen; 95 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') { 96 ptrE--; 97 } 98 99 // Length, sLen, does not include '\0' 100 sLen = ptrE - ptrB + 1; 101 102 // Adds '\0' to end of string and +1 to sLen 103 cleaned = psStringNCopy(ptrB, sLen); 104 105 return cleaned; 106 } 107 108 /** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location 109 * the beginning of the string. Tokens are newly allocated null terminated strings. */ 110 static char* getToken(char **inString, char *delimiter, psParseErrorType *status) 111 { 112 char *cleanToken = NULL; 113 int sLen = 0; 114 115 116 // Skip over leading whitespace 117 while(isspace(**inString)) { 118 (*inString)++; 119 } 120 121 // Length of token, not including delimiter 122 sLen = strcspn(*inString, delimiter); 123 if(sLen) { 124 125 // Create new, cleaned, and null terminated token 126 cleanToken = cleanString(*inString, sLen); 127 128 // Move to end of token 129 (*inString) += sLen; 130 } else if(**inString!='\0' && sLen==0) { 131 *status = PS_PARSE_ERROR_GENERAL; 132 } 133 134 return cleanToken; 135 } 136 137 /** Searches time tables in priority order and performs interpolation if input index value is within a table. 138 * If the index value is out of range, the status is set accordingly. */ 139 psF64 searchTables(psF64 index, psU64 column, psLookupStatusType *status, char *metadataTableNames[], psU32 nTables) 140 { 141 psU32 i = 0; 142 char *tableName = NULL; 143 psF64 result = 0.0; 144 psLookupTable *table = NULL; 145 psMetadataItem *tableMetadataItem = NULL; 146 147 148 149 // Check time metadata. Function call reports errors. 150 if(timeMetadata == NULL) { 151 if(!psTimeInit(TIME_CONFIG_FILE)) 299 152 return 0.0; 300 } 301 302 // since rows of table can not have same jd, this check is probably not needed. 303 denom = table->data.F64[hiIdx][0]-table->data.F64[loIdx][0]; 304 if(fabs(denom) < FLT_EPSILON) { 305 psError(PS_ERR_UNKNOWN,true, 306 PS_ERRORTEXT_psTime_TABLE_DUPLICATE_ROWS 307 "Ser7"); 153 } 154 155 // Search each table in priority order: ser7, eopc,finals 156 for(i=0; i<nTables; i++) { 157 158 // Get table from metadata 159 tableName = metadataTableNames[i]; 160 tableMetadataItem = psMetadataLookup(timeMetadata, tableName); 161 if(tableMetadataItem == NULL) { 162 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 163 tableName); 308 164 return 0.0; 309 } else { 310 // Interpolate three constants required to calculate TAI-UTC 311 const1 = table->data.F64[loIdx][1]+(table->data.F64[hiIdx][1]-table->data.F64[loIdx][1]) 312 *(jd-table->data.F64[loIdx][0])/denom; 313 314 const2 = table->data.F64[loIdx][2]+(table->data.F64[hiIdx][2]-table->data.F64[loIdx][2]) 315 *(jd-table->data.F64[loIdx][0])/denom; 316 317 const3 = table->data.F64[loIdx][3]+(table->data.F64[hiIdx][3]-table->data.F64[loIdx][3]) 318 *(jd-table->data.F64[loIdx][0])/denom; 319 } 320 } 321 322 out = const1 + (mjd - const2) * const3; 323 324 return out; 325 } 326 327 static double lookupSer7Table(const psTime *time, psS32 col) 328 { 329 psS32 hiIdx = 0; 330 psS32 loIdx = 0; 331 psS32 numRows = 0; 332 double out = 0.0; 333 double denom = 0.0; 334 double mjdUtc = 0.0; 335 static psImage* table = NULL; 336 337 if (table == NULL) { 338 table = readSer7File(SER7_FILE); 339 if (table == NULL) { 340 psAbort(__func__,"Failed to read the ser7.dat file."); 341 } 342 } 343 344 // Number of rows is the number of rows of data read from the data file 345 numRows = table->numRows; 346 347 // Interpolation value in should be in MJD format 348 mjdUtc = psTimeToMJD(time); 349 if(mjdUtc < table->data.F64[0][3]) { // MJD time before start of table 350 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 351 PS_ERRORTEXT_psTime_TIME_PREDATES_TABLE, 352 mjdUtc, "Ser7"); 353 354 } else if(mjdUtc > table->data.F64[numRows-1][3]) { // MJD time after end of table 355 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 356 PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLE, 357 mjdUtc, "Ser7"); 358 } else { // All other times..interpolate 359 while(mjdUtc > table->data.F64[hiIdx][3]) { 360 hiIdx++; 361 if(hiIdx >= numRows) { 362 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 363 PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLE, 364 mjdUtc, "Ser7"); 365 return 0.0; 366 } 367 } 368 369 loIdx = hiIdx--; 370 if(loIdx < 0) { 371 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 372 PS_ERRORTEXT_psTime_TIME_PREDATES_TABLE, 373 mjdUtc, "Ser7"); 374 } 375 376 denom = table->data.F64[hiIdx][3] - table->data.F64[loIdx][3]; 377 if(fabs(denom) < FLT_EPSILON) { 378 psError(PS_ERR_UNKNOWN,true, 379 PS_ERRORTEXT_psTime_TABLE_DUPLICATE_ROWS, 380 "Ser7"); 381 } else { 382 out = table->data.F64[loIdx][col]+(table->data.F64[hiIdx][col]-table->data.F64[loIdx][col]) 383 *(mjdUtc-table->data.F64[loIdx][3])/denom; 384 } 385 } 386 387 return out; 388 } 389 390 void psTimeInit(char *fileName) 391 { 165 } 166 table = (psLookupTable*)tableMetadataItem->data.V; 167 PS_PTR_CHECK_NULL(table,0.0); 168 169 // Attempt to interpolate table 170 *status = PS_LOOKUP_SUCCESS; 171 result = psLookupTableInterpolate(table, index, 2, status); 172 if(*status == PS_LOOKUP_SUCCESS) { 173 return result; 174 } else if(*status == PS_LOOKUP_ERROR) { 175 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED_NAME, 176 tableName); 177 return 0.0; 178 } 179 } 180 181 return result; 182 } 183 184 bool psTimeInit(char *fileName) 185 { 186 bool foundTable = false; 392 187 char *tableDir = NULL; 393 188 char *tableNames = NULL; 394 psU8 numTables = 0; 189 char *namesPtr = NULL; 190 char *metadataNamesPtr = NULL; 191 char *tableName = NULL; 192 char *fullTableName = NULL; 193 psS32 i = 0; 194 psS32 j = 0; 195 psS32 numTables = 0; 395 196 psVector *tablesFrom = NULL; 396 197 psVector *tablesTo = NULL; 397 psF64 beforeXp = 0.0;398 psF64 beforeYp = 0.0;399 psF64 beforeDut = 0.0;400 198 psMetadataItem *metadataItem = NULL; 199 psLookupTable *table = NULL; 200 psLookupStatusType status = PS_LOOKUP_SUCCESS; 201 char *metadataTableNames[4] = {"ser7", "eopc", "finals", "tai"}; 401 202 402 203 403 204 // Read time config file 404 psMetadataParseConfig(&timeMetadata, fileName, true); 205 if(psMetadataParseConfig(&timeMetadata, fileName, true) < 0) { 206 return false; 207 } 405 208 406 209 // Get path to time data files 407 210 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.dir"); 408 tableDir = (char*)metadataItem->data.V; 211 if(metadataItem == NULL) { 212 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 213 "psLib.time.tables.dir"); 214 return false; 215 } 216 tableDir = psStringCopy(metadataItem->data.V); 409 217 410 218 // Get number of tables 411 219 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.n"); 412 numTables = (psU8)metadataItem->data.S32; 413 414 // Get table names 220 if(metadataItem == NULL) { 221 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 222 "psLib.time.tables.n"); 223 return false; 224 } 225 numTables = (psS32)metadataItem->data.S32; 226 227 // Table file names 415 228 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.files"); 416 tableNames = (char*)metadataItem->data.V; 417 418 // Get ranges of tables 229 if(metadataItem == NULL) { 230 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 231 "psLib.time.tables.files"); 232 return false; 233 } 234 tableNames = psStringCopy(metadataItem->data.V); 235 236 // Get lower range of tables 419 237 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.from"); 420 tablesFrom = (psVector*)metadataItem->data.V; 238 if(metadataItem == NULL) { 239 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 240 "psLib.time.tables.from"); 241 return false; 242 } 243 tablesFrom = psVectorCopy(tablesFrom, metadataItem->data.V, PS_TYPE_F64); 244 if(tablesFrom->n != numTables) { 245 return false; 246 } 247 248 // Get upper range of tables 421 249 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.tables.to"); 422 tablesTo = (psVector*)metadataItem->data.V; 423 424 // Out of range values 425 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.xp"); 426 beforeXp =(psF64)metadataItem->data.F64; 427 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.yp"); 428 beforeYp =(psF64)metadataItem->data.F64; 429 metadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut"); 430 beforeDut = (psF64)metadataItem->data.F64; 250 if(metadataItem == NULL) { 251 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 252 "psLib.time.tables.to"); 253 return false; 254 } 255 tablesTo = psVectorCopy(tablesTo, metadataItem->data.V, PS_TYPE_F64); 256 if(tablesTo->n != numTables) { 257 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_VECTOR, tablesTo->n, numTables); 258 return false; 259 } 260 261 // Read time tables 262 namesPtr = tableNames; 263 while((tableName=getToken(&namesPtr, " ", &status)) != NULL) { 264 fullTableName = (char*)psAlloc(strlen(tableDir)+strlen(tableName)+1+1); // Add one for last dir "/" 265 fullTableName[0]='\0'; // Old strings may come back from psAlloc, so set init pos to EOL 266 strcat(fullTableName, tableDir); 267 strcat(fullTableName, "/"); 268 strcat(fullTableName, tableName); 269 270 if(i < numTables) { 271 table = psLookupTableAlloc(fullTableName, tablesFrom->data.F64[i], tablesTo->data.F64[i]); 272 psLookupTableRead(table); 273 } else { 274 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, i+1, numTables); 275 } 276 277 // Place tables into metadata slightly altered names as keys to create consistent naming conventions 278 foundTable = false; 279 for(j=0; j<numTables; j++) { 280 metadataNamesPtr = strstr(tableName, metadataTableNames[j]); 281 if(metadataNamesPtr != NULL) { 282 psMetadataAdd(timeMetadata, PS_LIST_TAIL, strcat(metadataTableNames[j], "Table"), 283 PS_META_LOOKUPTABLE, NULL, table); 284 foundTable = true; 285 } else if(foundTable==false && j==numTables-1) { 286 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, j, numTables); 287 } 288 } 289 290 psFree(fullTableName); 291 psFree(tableName); 292 i++; 293 } 294 295 if(numTables > i+1) { 296 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_BAD_TABLE_COUNT, i+1, numTables); 297 } 298 299 psFree(tableDir); 300 psFree(tableNames); 301 psFree(tablesFrom); 302 psFree(tablesTo); 303 304 return true; 305 } 306 307 void psTimeFinalize(void) 308 { 309 psFree(timeMetadata); 431 310 } 432 311 … … 552 431 // Convert Universal Time (UTC) to UT1 553 432 ut1UtcDelta = psTimeAlloc(PS_TIME_UTC); 554 555 ut1UtcDbl = psTimeGetUT1Delta(utcTime)*1e6; 433 ut1UtcDbl = psTimeGetUT1Delta(taiTime)*1e6; 556 434 ut1UtcDelta->usec = (psU32)fabs(ut1UtcDbl); 557 435 if(ut1UtcDbl<0) { … … 561 439 } 562 440 563 564 441 // Calculate UT1 as Julian Centuries since J2000.0 565 442 jdUt1Days = psTimeToJD(ut1Time); … … 580 457 fracDays = fmod(mjdUt1Days, 1.0); 581 458 582 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. Equation set up to minimize multiplications 459 // Calculate Greenwich Mean Sidereal Time (GMST) in radians. Equation set up to minimize multiplications. 583 460 gmstRad = fracDays*TWOPI+(const1+const2*tu+t*(const3+t*(const4+t*(const5+const6*t))))*S2R; 584 461 … … 602 479 double psTimeGetUT1Delta(const psTime *time) 603 480 { 481 psU32 nTables = 3; 482 psF64 mjd = 0.0; 483 psF64 result = 0.0; 484 psF64 dut2ut1 = 0.0; 485 psF64 t = 0.0; 486 psVector *dut = NULL; 487 psMetadataItem *tableMetadataItem = NULL; 488 psLookupStatusType status = PS_LOOKUP_SUCCESS; 489 char *metadataTableNames[3] = {"ser7", "eopc", "finals"}; 490 604 491 605 492 // Error checks … … 607 494 PS_INT_CHECK_RANGE(time->usec,0,1e6-1,NAN); 608 495 609 return lookupSer7Table(time, 6); 496 if(time->type != PS_TIME_TAI) { 497 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_INCORRECT, time->type); 498 return 0.0; 499 } 500 501 // Attempt to find value through table lookup and interpolation 502 mjd = psTimeToMJD(time); 503 result = searchTables(mjd, 0, &status, metadataTableNames, nTables); 504 505 // Value could not be found through table lookup and interpolation 506 if(status == PS_LOOKUP_PAST_TOP) { 507 508 // Date too early for tables. Get default time delta value from metadata, and issue warning. 509 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES, mjd, "UT1-UTC"); 510 511 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.dut"); 512 if(tableMetadataItem == NULL) { 513 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.before.dut"); 514 return 0.0; 515 } 516 result = tableMetadataItem->data.F64; 517 518 } else if(status == PS_LOOKUP_PAST_BOTTOM) { 519 /* Date too late for tables. Issue warning and use following formulae for predicting 520 ahead of the most recent available table entry. 521 ut1-utc = [0] + [1]*(MJD - [2]) - (ut2-ut1) 522 [0, 1, 2] = @psLib.time.predict.dut 523 ut2-ut1 = 0.022 sin(2*pi*t) - 0.012 cos(2*pi*t) - 0.006 sin(4*pi*t) + 0.007 cos(4*pi*t) 524 t = 2000.0 + (MJD - 51544.03)/365.2422 525 */ 526 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "UT1-UTC"); 527 528 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.dut"); 529 if(tableMetadataItem == NULL) { 530 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.predict.dut"); 531 return 0.0; 532 } 533 dut = (psVector*)tableMetadataItem->data.V; 534 PS_PTR_CHECK_NULL(dut,0.0); 535 536 t = 2000.0 + (mjd - 51544.03)/365.2422; 537 dut2ut1 = 0.022*sin(TWOPI*t) - 0.012*cos(TWOPI*t) - 0.006*sin(4.0*M_PI*t) + 0.007*cos(4.0*M_PI*t); 538 result = dut->data.F64[0] + dut->data.F64[1]*(mjd - dut->data.F64[2]) - dut2ut1; 539 540 } else if(status != PS_LOOKUP_SUCCESS) { 541 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 542 return 0.0; 543 } 544 545 return result; 610 546 } 611 547 612 548 struct psSphere* psTimeGetPoleCoords(const psTime* time) 613 549 { 614 double x = 0.0; 615 double y = 0.0; 550 psU32 nTables = 3; 551 psF64 x = 0.0; 552 psF64 y = 0.0; 553 psF64 mjd = 0.0; 554 psF64 a = 0.0; 555 psF64 c = 0.0; 556 psF64 mjdPred = 0.0; 616 557 struct psSphere* output = NULL; 617 558 psLookupStatusType xStatus = PS_LOOKUP_SUCCESS; 559 psLookupStatusType yStatus = PS_LOOKUP_SUCCESS; 560 psMetadataItem *tableMetadataItem = NULL; 561 char *metadataTableNames[3] = {"ser7", "eopc", "finals"}; 562 psVector *xp = NULL; 563 psVector *yp = NULL; 618 564 619 565 // Error checks … … 621 567 PS_INT_CHECK_RANGE(time->usec,0,1e6-1,NULL); 622 568 623 x = lookupSer7Table((psTime*)time, 4); 624 y = lookupSer7Table((psTime*)time, 5); 625 569 if(time->type != PS_TIME_TAI) 570 { 571 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TYPE_INCORRECT, time->type); 572 return NULL; 573 } 574 575 // Attempt to find value through table lookup and interpolation 576 mjd = psTimeToMJD(time); 577 x = searchTables(mjd, 0, &xStatus, metadataTableNames, nTables); 578 y = searchTables(mjd, 0, &yStatus, metadataTableNames, nTables); 579 580 // Value could not be found through table lookup and interpolation 581 if(xStatus==PS_LOOKUP_PAST_TOP && yStatus==PS_LOOKUP_PAST_TOP) 582 { 583 584 // Date too earlier for tables. Get default polar coodinate values from metadata, and issue warning. 585 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_PREDATES_TABLES, mjd, "polar motion"); 586 587 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.xp"); 588 if(tableMetadataItem == NULL) { 589 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.before.xp"); 590 return NULL; 591 } 592 x = tableMetadataItem->data.F64; 593 594 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.before.yp"); 595 if(tableMetadataItem == NULL) { 596 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.before.yp"); 597 return NULL; 598 } 599 y = tableMetadataItem->data.F64; 600 601 } else if(xStatus==PS_LOOKUP_PAST_BOTTOM && yStatus==PS_LOOKUP_PAST_BOTTOM) 602 { 603 604 /* Date too late for tables. Issue warning and use following formulae for predicting 605 ahead of the most recent available table entry. 606 x = [0] + [1]*cos a + [2]*sin a + [3]*cos c + [4]*sin c 607 [0], [1], [2], [3] = @psLib.time.predict.xp 608 y = [0] + [1]*cos a + [2]*sin a + [3]*cos c + [4]*sin c 609 [0], [1], [2], [3] = @psLib.time.predict.yp 610 a = 2*pi*(mjd - pslib.time.predict.mjd)/365.25 611 c = 2*pi*(mjd - pslib.time.predict.mjd)/435.0 612 */ 613 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_TIME_POSTDATES_TABLES, mjd, "polar motion"); 614 615 616 // Get predicted MJD 617 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.mjd"); 618 if(tableMetadataItem == NULL) { 619 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, 620 "psLib.time.predict.mjd"); 621 return NULL; 622 } 623 mjdPred = tableMetadataItem->data.F64; 624 625 // Get xp 626 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.xp"); 627 if(tableMetadataItem == NULL) { 628 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.predict.xp"); 629 return NULL; 630 } 631 xp = (psVector*)tableMetadataItem->data.V; 632 PS_PTR_CHECK_NULL(xp,NULL); 633 634 // Get yp 635 tableMetadataItem = psMetadataLookup(timeMetadata, "psLib.time.predict.yp"); 636 if(tableMetadataItem == NULL) { 637 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "psLib.time.predict.yp"); 638 return NULL; 639 } 640 yp = (psVector*)tableMetadataItem->data.V; 641 PS_PTR_CHECK_NULL(yp,NULL); 642 643 // Calculate "a" and "c" constants 644 a = TWOPI*(mjd - mjdPred)/365.25; 645 c = TWOPI*(mjd - mjdPred)/435.0; 646 647 // Calculate x and y polar coordinates 648 x = xp->data.F64[0] + 649 xp->data.F64[1]*cos(a) + 650 xp->data.F64[2]*sin(a) + 651 xp->data.F64[3]*cos(c) + 652 xp->data.F64[4]*sin(c); 653 654 y = yp->data.F64[0] + 655 yp->data.F64[1]*cos(a) + 656 yp->data.F64[2]*sin(a) + 657 yp->data.F64[3]*cos(c) + 658 yp->data.F64[4]*sin(c); 659 660 } else if(xStatus!=PS_LOOKUP_SUCCESS || yStatus!=PS_LOOKUP_SUCCESS) 661 { 662 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 663 return NULL; 664 } 665 666 // Create output sphere and convert arcsec to radians (i.e. x/60/60*M_PI/180) 626 667 output = psAlloc(sizeof(psSphere)); 627 output->r = x * M_PI / 648000.0; // x in arcsec converted to radians, i.e., x/60/60*M_PI/180668 output->r = x * M_PI / 648000.0; 628 669 output->d = y * M_PI / 648000.0; 629 670 … … 633 674 double psTimeGetTAIDelta(const psTime *time) 634 675 { 676 psU64 i = 0; 677 psF64 jd = 0.0; 678 psF64 mjd = 0.0; 679 psF64 out = 0.0; 680 psF64 const1 = 0.0; 681 psF64 const2 = 0.0; 682 psF64 const3 = 0.0; 683 psLookupTable* table = NULL; 684 psMetadataItem *tableMetadataItem = NULL; 685 psVector *stats = NULL; 686 psVector *results = NULL; 635 687 636 688 // Error checks … … 638 690 PS_INT_CHECK_RANGE(time->usec,0,1e6-1,NAN); 639 691 640 return lookupTaiUtcTable(time); 641 } 692 // Check time metadata 693 if(timeMetadata == NULL) { 694 if(!psTimeInit(TIME_CONFIG_FILE)) 695 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_FILE_NOT_FOUND, "psTime.config"); 696 return 0.0; 697 } 698 699 // Get table from metadata 700 tableMetadataItem = psMetadataLookup(timeMetadata, "taiTable"); 701 if(tableMetadataItem == NULL) { 702 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_LOOKUP_METADATA_FAILED, "taiTable"); 703 return 0.0; 704 } 705 table = (psLookupTable*)tableMetadataItem->data.V; 706 PS_PTR_CHECK_NULL(table,0); 707 708 // Determine Julian and modified Julian dates used in table lookup and time delta calculation 709 jd = psTimeToJD(time); 710 mjd = psTimeToMJD(time); 711 712 stats = psVectorAlloc(table->numCols, PS_TYPE_U32); 713 results = psLookupTableInterpolateAll(table, jd, stats); 714 715 // Check for successful interpolation 716 for(i=0; i<stats->n; i++) { 717 if(stats->data.U32[i]!=PS_LOOKUP_PAST_BOTTOM && stats->data.U32[i]!=PS_LOOKUP_PAST_TOP) { 718 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psTime_INTERPOLATION_FAILED); 719 } 720 } 721 722 const1 = results->data.F64[0]; 723 const2 = results->data.F64[1]; 724 const3 = results->data.F64[2]; 725 out = const1 + (mjd - const2) * const3; 726 727 psFree(stats); 728 psFree(results); 729 730 return out; 731 } 732 642 733 643 734 psS64 psTimeLeapseconds(const psTime *time1, const psTime *time2)
Note:
See TracChangeset
for help on using the changeset viewer.
