giastroutils.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <math.h>
00033
00034 #include <cxtypes.h>
00035
00036 #include <cpl_msg.h>
00037
00038 #include <giastroutils.h>
00039
00040
00041
00050 static const cxdouble TINY = 1.e-12;
00051
00052 static const cxdouble RV_DPI =
00053 3.1415926535897932384626433832795028841971693993751;
00054
00055 static const cxdouble DEG_TO_RAD =
00056 0.017453292519943295769236907684886127134428718885417;
00057
00058 static const cxdouble SEC_TO_DEG = 15. / 3600.;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 inline static cxdouble
00084 _giraffe_compute_zdistance(cxdouble hourangle, cxdouble delta,
00085 cxdouble latitude)
00086 {
00087
00088 cxdouble p0 = sin(latitude) * sin(delta);
00089 cxdouble p1 = cos(latitude) * cos(delta);
00090 cxdouble z = p0 + cos(hourangle) * p1;
00091
00092 if (fabs(z) < TINY) {
00093 z = z < 0. ? -TINY : TINY;
00094 }
00095
00096 return 1. / z;
00097
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 inline static cxdouble
00118 _giraffe_compute_airmass_young_irvine(cxdouble secz)
00119 {
00120
00121 return secz * (1. - 0.0012 * (pow(secz, 2.) - 1.));
00122
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 inline static cxdouble
00142 _giraffe_compute_airmass_young(cxdouble secz)
00143 {
00144
00145 cxdouble z = 1. / secz;
00146 cxdouble x = 0.;
00147 cxdouble y = 0.;
00148
00149 x = 1.002432 * z * z + 0.148386 * z + 0.0096467;
00150 y = z * z * z + 0.149864 * z * z + 0.0102963 * z + 0.000303978;
00151
00152 return x / y;
00153
00154 }
00155
00156
00184 cxdouble
00185 giraffe_compute_airmass(cxdouble alpha, cxdouble delta, cxdouble lst,
00186 cxdouble exptime, cxdouble latitude)
00187 {
00188
00189 const cxchar* const fctid = "giraffe_compute_airmass";
00190
00191
00192
00193
00194 const cxdouble weights[] = {1. / 6., 2. / 3., 1. / 6.};
00195
00196
00197
00198
00199
00200
00201
00202 const cxdouble airmass_upper_limit = 10.;
00203
00204
00205 cxdouble z = 0.;
00206 cxdouble hourangle = 0.;
00207 cxdouble airmass = 0.;
00208
00209
00210
00211
00212
00213
00214 hourangle = lst * SEC_TO_DEG - alpha;
00215
00216
00217
00218
00219
00220
00221
00222 if (hourangle < -180.) {
00223 hourangle += 360.;
00224 }
00225
00226 if (hourangle > 180.) {
00227 hourangle -= 360.;
00228 }
00229
00230
00231
00232
00233
00234
00235 delta *= DEG_TO_RAD;
00236 latitude *= DEG_TO_RAD;
00237 hourangle *= DEG_TO_RAD;
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 z = _giraffe_compute_zdistance(hourangle, delta, latitude);
00249
00250 if (fabs(z) < TINY) {
00251 cpl_msg_debug(fctid, "Airmass computation failed. Object is "
00252 "below the horizon.");
00253 return -1.;
00254 }
00255
00256 airmass = _giraffe_compute_airmass_young(z);
00257
00258 if (exptime > 0.) {
00259
00260 const cxint nweights = CX_N_ELEMENTS(weights);
00261
00262 cxint i = 0;
00263
00264 cxdouble timestep = exptime / (nweights - 1) * SEC_TO_DEG *
00265 DEG_TO_RAD;
00266
00267
00268 airmass *= weights[0];
00269
00270 for (i = 1; i < nweights; i++) {
00271
00272 z = _giraffe_compute_zdistance(hourangle + i * timestep,
00273 delta, latitude);
00274
00275 if (fabs(z) < TINY) {
00276
00277 cpl_msg_debug(fctid, "Airmass computation failed. Object "
00278 "is below the horizon.");
00279 return -1.;
00280
00281 }
00282
00283 airmass += weights[i] * _giraffe_compute_airmass_young(z);
00284
00285 }
00286
00287 }
00288
00289
00290 if (airmass > airmass_upper_limit) {
00291 cpl_msg_debug(fctid, "Airmass larger than %f", airmass_upper_limit);
00292 }
00293
00294 return airmass;
00295
00296 }