JURASSIC
zenith.c
Go to the documentation of this file.
1/*
2 This file is part of JURASSIC.
3
4 JURASSIC is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 JURASSIC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with JURASSIC. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright (C) 2003-2026 Forschungszentrum Juelich GmbH
18*/
19
25#include "jurassic.h"
26
27/* ------------------------------------------------------------
28 Functions...
29 ------------------------------------------------------------ */
30
32static void usage(
33 void);
34
35/* ------------------------------------------------------------
36 Main...
37 ------------------------------------------------------------ */
38
39int main(
40 int argc,
41 char *argv[]) {
42
43 static ctl_t ctl;
44 static obs_t obs;
45
46 /* Print usage information... */
47 USAGE;
48
49 /* Check arguments... */
50 if (argc < 3)
51 ERRMSG("Missing or invalid command-line arguments.\n\n"
52 "Usage: zenith <ctl> <obs> [KEY VALUE ...]\n\n"
53 "Use -h for full help.");
54
55 /* Read control parameters... */
56 read_ctl(argc, argv, &ctl);
57 const double t0 = scan_ctl(argc, argv, "T0", -1, "0", NULL);
58 const double t1 = scan_ctl(argc, argv, "T1", -1, "0", NULL);
59 const double dt = scan_ctl(argc, argv, "DT", -1, "1", NULL);
60 const double vpz = scan_ctl(argc, argv, "VPZ", -1, "700", NULL);
61 const double theta0 = scan_ctl(argc, argv, "THETA0", -1, "-90.0", NULL);
62 const double theta1 = scan_ctl(argc, argv, "THETA1", -1, "90.0", NULL);
63 const double dtheta = scan_ctl(argc, argv, "DTHETA", -1, "3.0", NULL);
64 const double obsz = scan_ctl(argc, argv, "OBSZ", -1, "0", NULL);
65
66 /* Set distances... */
67 const double ro = RE + obsz; /* observer radius */
68 const double rv = RE + vpz; /* shell radius */
69
70 /* Create measurement geometry... */
71 for (double t = t0; t <= t1; t += dt) {
72 for (double theta = theta0; theta <= theta1 + 1e-12; theta += dtheta) {
73
74 /* Check number of ray paths... */
75 if ((obs.nr) >= NR)
76 ERRMSG("Too many rays!");
77
78 /* Auxilary variables... */
79 const double th = DEG2RAD(theta);
80 const double sth = sin(th);
81 const double cth = cos(th);
82
83 /*
84 Ray in local x-z plane:
85 A = (0, 0, ro)
86 u = (sin(th), 0, cos(th)) (|u|=1)
87 P(s) = A + s u, s >= 0
88
89 Intersect with sphere |P| = rv:
90 s^2 + 2 ro cos(th) s + (ro^2 - rv^2) = 0
91 Discriminant:
92 disc = rv^2 - ro^2 sin^2(th)
93 */
94 double disc = rv * rv - ro * ro * sth * sth;
95 if (disc < 0.0) {
96 if (disc > -1e-12 * rv * rv)
97 disc = 0.0; // tolerate tiny negatives
98 else
99 continue;
100 }
101
102 /* If disc < 0, ray misses the shell: skip this ray */
103 if (disc < 0.0)
104 continue;
105
106 /* Two intersections along the ray... */
107 const double sq = sqrt(disc);
108 const double s1 = -ro * cth - sq;
109 const double s2 = -ro * cth + sq;
110
111 /* Choose nearest forward intersection (smallest s >= 0)... */
112 double s = DBL_MAX;
113 if (s1 >= 0.0)
114 s = s1;
115 if (s2 >= 0.0 && s2 < s)
116 s = s2;
117
118 /* If both are behind observer, skip... */
119 if (s == DBL_MAX)
120 continue;
121
122 /* Intersection point B in local x-z plane... */
123 const double bx = s * sth;
124 const double bz = ro + s * cth;
125
126 /*
127 Central angle beta = angle between OA (z-axis) and OB.
128 In this local frame, OA is +z. For points in x-z plane:
129 beta = atan2(bx, bz)
130 This preserves sign (north/south) consistent with theta sign.
131 */
132 const double beta = atan2(bx, bz);
133
134 /* Set observer and view point... */
135 obs.time[obs.nr] = t;
136 obs.obsz[obs.nr] = obsz;
137 obs.vpz[obs.nr] = vpz;
138
139 /* Stored as "view point latitude-like" angle for this 2-D meridional setup... */
140 obs.vplat[obs.nr] = RAD2DEG(beta);
141
142 /* Increment ray path counter... */
143 obs.nr++;
144 }
145 }
146
147 /* Write observation data... */
148 write_obs(NULL, argv[2], &ctl, &obs, 0);
149
150 return EXIT_SUCCESS;
151}
152
153/*****************************************************************************/
154
155static void usage(
156 void) {
157 printf("\nJURASSIC zenith-geometry tool.\n\n");
158 printf("Create observation geometry for zenith observations in the\n");
159 printf("meridional 2-D setup used by JURASSIC.\n\n");
160 printf("Usage:\n");
161 printf(" zenith <ctl> <obs> [KEY VALUE ...]\n\n");
162 printf("Arguments:\n");
163 printf(" <ctl> Control file.\n");
164 printf(" <obs> Output observation geometry file.\n");
165 printf(" [KEY VALUE] Optional control parameters.\n\n");
166 printf("Tool-specific control parameters:\n");
167 printf(" VPZ View-point altitude [km].\n");
168 printf(" OBSZ Observer altitude [km].\n");
169 printf(" T0, T1, DT Time range and spacing.\n");
170 printf(" THETA0, THETA1 Zenith-angle range.\n");
171 printf(" DTHETA Zenith-angle spacing.\n\n");
172 printf("Common control parameters:\n");
173 printf(" OBSFMT Output observation file format.\n");
174 printf
175 (" ND, NU[i] Spectral channels in observation files.\n\n");
176 printf("Further information:\n");
177 printf(" Manual: https://slcs-jsc.github.io/jurassic/\n");
178}
void usage(void)
Print command-line help.
Definition: formod.c:163
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read model control parameters from command-line and configuration input.
Definition: jurassic.c:5516
void write_obs(const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs, int profile)
Write observation data to an output file in ASCII or binary format.
Definition: jurassic.c:8275
double scan_ctl(int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scan control file or command-line arguments for a configuration variable.
Definition: jurassic.c:6612
JURASSIC library declarations.
#define RE
Mean radius of Earth [km].
Definition: jurassic.h:224
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: jurassic.h:1325
#define USAGE
Print usage information on -h or --help.
Definition: jurassic.h:1206
#define DEG2RAD(deg)
Convert degrees to radians.
Definition: jurassic.h:505
#define RAD2DEG(rad)
Convert radians to degrees.
Definition: jurassic.h:1047
#define NR
Maximum number of ray paths.
Definition: jurassic.h:318
Control parameters.
Definition: jurassic.h:1428
Observation geometry and radiance data.
Definition: jurassic.h:1657
double vpz[NR]
View point altitude [km].
Definition: jurassic.h:1675
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:1681
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:1666
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1663
int nr
Number of ray paths.
Definition: jurassic.h:1660
int main(int argc, char *argv[])
Definition: zenith.c:39