1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.sc.seis.TauP;
18
19 import java.io.*;
20 import java.util.Vector;
21
22 /***
23 * Calculate pierce points for different branches using linear interpolation
24 * between known slowness samples. A pierce point is where a ray pierces a tau
25 * branch. This gives a (very) rough path through the model for a ray.
26 *
27 * @version 1.1.3 Fri Apr 5 14:12:19 GMT 2002
28 * @author H. Philip Crotwell
29 */
30 public class TauP_Pierce extends TauP_Time {
31
32 protected boolean onlyTurnPoints = false;
33
34 protected boolean onlyRevPoints = false;
35
36 protected boolean onlyUnderPoints = false;
37
38 protected boolean onlyAddPoints = false;
39
40 protected double[] addDepth = new double[0];
41
42 protected TauP_Pierce() {
43 super();
44 }
45
46 public TauP_Pierce(TauModel tMod) throws TauModelException {
47 super(tMod);
48 }
49
50 public TauP_Pierce(String modelName) throws TauModelException {
51 super(modelName);
52 }
53
54
55 public void setOnlyTurnPoints(boolean onlyTurnPoints) {
56 this.onlyTurnPoints = onlyTurnPoints;
57 }
58
59 public void setOnlyRevPoints(boolean onlyRevPoints) {
60 this.onlyRevPoints = onlyRevPoints;
61 }
62
63 public void setOnlyUnderPoints(boolean onlyUnderPoints) {
64 this.onlyUnderPoints = onlyUnderPoints;
65 }
66
67 public void setOnlyAddPoints(boolean onlyAddPoints) {
68 this.onlyAddPoints = onlyAddPoints;
69 }
70
71 /***
72 * sets depths for additional pierce points, ie depths that are not really
73 * discontinuities in the model.
74 */
75 public void setAddDepths(String depthString) {
76 addDepth = parseAddDepthsList(depthString);
77 }
78
79 public void appendAddDepths(String depthString) {
80 double[] newDepths = parseAddDepthsList(depthString);
81 double[] temp = new double[addDepth.length + newDepths.length];
82 System.arraycopy(addDepth, 0, temp, 0, addDepth.length);
83 System.arraycopy(newDepths, 0, temp, addDepth.length, newDepths.length);
84 addDepth = temp;
85 }
86
87 protected double[] parseAddDepthsList(String depthList) {
88 int offset = 0;
89 int commaIndex;
90 String degEntry;
91 int numDepths = 0;
92 depthList = depthList.replace(' ', ',');
93
94
95 commaIndex = depthList.indexOf(",,", offset);
96 while(commaIndex != -1) {
97 depthList = depthList.substring(0, commaIndex)
98 + depthList.substring(commaIndex + 1);
99 commaIndex = depthList.indexOf(",,", offset);
100 }
101
102 if(depthList.charAt(0) == ',') {
103 if(depthList.length() > 1) {
104 depthList = depthList.substring(1);
105 } else {
106
107 return new double[0];
108 }
109 }
110
111 if(depthList.charAt(depthList.length() - 1) == ',') {
112
113
114 depthList = depthList.substring(0, depthList.length() - 1);
115 }
116 double[] depthsFound = new double[depthList.length()];
117 while(offset < depthList.length()) {
118 commaIndex = depthList.indexOf(',', offset);
119 if(commaIndex != -1) {
120 degEntry = depthList.substring(offset, commaIndex);
121 depthsFound[numDepths] = Double.valueOf(degEntry).doubleValue();
122 offset = commaIndex + 1;
123 numDepths++;
124 } else {
125 degEntry = depthList.substring(offset);
126 depthsFound[numDepths] = Double.valueOf(degEntry).doubleValue();
127 offset = depthList.length();
128 numDepths++;
129 }
130 }
131 double[] temp = new double[numDepths];
132 System.arraycopy(depthsFound, 0, temp, 0, numDepths);
133 depthsFound = temp;
134 return depthsFound;
135 }
136
137 /*** override depthCorrect so that we can put the pierce depths in. */
138 public void depthCorrect(double depth) throws TauModelException {
139 TauModel tModOrig = (TauModel)tMod.clone();
140 TauModel tModDepthOrig = tModDepth;
141 boolean mustRecalc = false;
142
143
144
145 if(tModDepth.sourceDepth == depth) {
146 if(addDepth != null) {
147 double[] branchDepths = tModDepth.getBranchDepths();
148 for(int i = 0; i < addDepth.length; i++) {
149 for(int j = 0; j < branchDepths.length; j++) {
150 if(addDepth[i] == branchDepths[j]) {
151
152 break;
153 }
154
155
156
157 mustRecalc = true;
158 }
159 if(mustRecalc) {
160
161 break;
162 }
163 }
164 }
165 } else {
166
167 mustRecalc = true;
168 }
169 if(mustRecalc) {
170
171 tModDepth = null;
172 } else {
173
174 super.depthCorrect(depth);
175 return;
176 }
177 try {
178 if(addDepth != null) {
179 for(int i = 0; i < addDepth.length; i++) {
180 tMod = tMod.splitBranch(addDepth[i]);
181 }
182 }
183 } catch(TauModelException e) {
184 System.err.println("depthCorrect: caught TauModelException: "
185 + e.getMessage() + "\nSkipping added depth"
186 + " pierce points.");
187 tMod = tModOrig;
188 tMod = tModDepthOrig;
189 }
190 super.depthCorrect(depth);
191 tMod = tModOrig;
192 }
193
194 public void calculate(double degrees) throws TauModelException {
195 depthCorrect(getSourceDepth());
196 recalcPhases();
197 clearArrivals();
198 calcPierce(degrees);
199 }
200
201 /*** calculates the pierce points for phases at the given distance. */
202 protected void calcPierce(double degrees) {
203 this.degrees = degrees;
204 SeismicPhase phase;
205 Arrival[] phaseArrivals;
206 double calcDepth, calcTime, calcDist;
207 for(int phaseNum = 0; phaseNum < phases.size(); phaseNum++) {
208 phase = (SeismicPhase)phases.elementAt(phaseNum);
209 try {
210 phase.setDEBUG(DEBUG);
211 phase.calcTime(degrees);
212 if(phase.hasArrivals()) {
213 phase.calcPierce(tModDepth);
214 phaseArrivals = phase.getArrivals();
215 for(int i = 0; i < phaseArrivals.length; i++) {
216 arrivals.addElement(phaseArrivals[i]);
217 }
218 }
219 } catch(TauModelException e) {
220 System.err.println("Caught TauModelException: "
221 + e.getMessage());
222 System.err.println("Skipping phase " + phase.getName());
223 }
224 }
225 }
226
227 public void printResult(Writer out) throws IOException {
228 double calcTime, calcDist;
229 double prevDepth, nextDepth;
230 double lat, lon;
231 Arrival currArrival;
232 String tempString;
233 boolean longWayRound = false;
234 for(int i = 0; i < arrivals.size(); i++) {
235 currArrival = (Arrival)arrivals.elementAt(i);
236 out.write("> " + currArrival.name + " at "
237 + outForms.formatTime(currArrival.time) + " seconds at "
238 + outForms.formatDistance(currArrival.getDistDeg())
239 + " degrees for a "
240 + outForms.formatDepth(currArrival.sourceDepth)
241 + " km deep source in the " + modelName + " model.\n");
242 longWayRound = false;
243 if((currArrival.dist * 180 / Math.PI) % 360 > 180) {
244 longWayRound = true;
245 }
246 prevDepth = currArrival.pierce[0].depth;
247 for(int j = 0; j < currArrival.pierce.length; j++) {
248 calcTime = currArrival.pierce[j].time;
249 calcDist = currArrival.pierce[j].dist * 180.0 / Math.PI;
250 if(longWayRound && calcDist != 0.0) {
251 calcDist *= -1.0;
252 }
253 if(j < currArrival.pierce.length - 1) {
254 nextDepth = currArrival.pierce[j + 1].depth;
255 } else {
256 nextDepth = currArrival.pierce[j].depth;
257 }
258 if(!(onlyTurnPoints || onlyRevPoints || onlyUnderPoints || onlyAddPoints)
259 || ((onlyAddPoints && isAddDepth(currArrival.pierce[j].depth))
260 || (onlyRevPoints && ((prevDepth - currArrival.pierce[j].depth)
261 * (currArrival.pierce[j].depth - nextDepth) < 0))
262 || (onlyTurnPoints && j != 0 && ((prevDepth - currArrival.pierce[j].depth) <= 0 && (currArrival.pierce[j].depth - nextDepth) >= 0)) || (onlyUnderPoints && ((prevDepth - currArrival.pierce[j].depth) >= 0 && (currArrival.pierce[j].depth - nextDepth) <= 0)))) {
263 out.write(outForms.formatDistance(calcDist));
264 out.write(outForms.formatDepth(currArrival.pierce[j].depth));
265 out.write(outForms.formatDepth(currArrival.pierce[j].time));
266 if(eventLat != Double.MAX_VALUE
267 && eventLon != Double.MAX_VALUE
268 && azimuth != Double.MAX_VALUE) {
269 lat = SphericalCoords.latFor(eventLat,
270 eventLon,
271 calcDist,
272 azimuth);
273 lon = SphericalCoords.lonFor(eventLat,
274 eventLon,
275 calcDist,
276 azimuth);
277 out.write(" " + outForms.formatLatLon(lat) + " "
278 + outForms.formatLatLon(lon));
279 } else if(stationLat != Double.MAX_VALUE
280 && stationLon != Double.MAX_VALUE
281 && backAzimuth != Double.MAX_VALUE) {
282 lat = SphericalCoords.latFor(stationLat,
283 stationLon,
284 degrees - calcDist,
285 backAzimuth);
286 lon = SphericalCoords.lonFor(stationLat,
287 stationLon,
288 degrees - calcDist,
289 backAzimuth);
290 out.write(" " + outForms.formatLatLon(lat) + " "
291 + outForms.formatLatLon(lon));
292 } else if(stationLat != Double.MAX_VALUE
293 && stationLon != Double.MAX_VALUE
294 && eventLat != Double.MAX_VALUE
295 && eventLon != Double.MAX_VALUE) {
296 azimuth = SphericalCoords.azimuth(eventLat,
297 eventLon,
298 stationLat,
299 stationLon);
300 backAzimuth = SphericalCoords.azimuth(stationLat,
301 stationLon,
302 eventLat,
303 eventLon);
304 lat = SphericalCoords.latFor(eventLat,
305 eventLon,
306 calcDist,
307 azimuth);
308 lon = SphericalCoords.lonFor(eventLat,
309 eventLon,
310 calcDist,
311 azimuth);
312 out.write(" " + outForms.formatLatLon(lat) + " "
313 + outForms.formatLatLon(lon));
314 }
315 out.write("\n");
316 }
317 prevDepth = currArrival.pierce[j].depth;
318 }
319 }
320 }
321
322 /***
323 * checks to see if the given depth has been "added" as a pierce point.
324 */
325 public synchronized boolean isAddDepth(double depth) {
326 for(int i = 0; i < addDepth.length; i++) {
327 if(depth == addDepth[i]) { return true; }
328 }
329 return false;
330 }
331
332 /*** prints the known command line flags. */
333 public void printUsage() {
334 printStdUsage();
335 System.out.println("-az azimuth -- sets the azimuth (event to station)\n"
336 + " used to output lat and lon of pierce points\n"
337 + " if the event lat lon and distance are also\n"
338 + " given. Calculated if station and event\n"
339 + " lat and lon are given.");
340 System.out.println("-baz backazimuth -- sets the back azimuth (station to event)\n"
341 + " used to output lat and lon of pierce points\n"
342 + " if the station lat lon and distance are also\n"
343 + " given. Calculated if station and event\n"
344 + " lat and lon are given.\n");
345 System.out.println("-rev -- only prints underside and bottom turn points, e.g. ^ and v");
346 System.out.println("-turn -- only prints bottom turning points, e.g. v");
347 System.out.println("-under -- only prints underside reflection points, e.g. ^\n");
348 System.out.println("-pierce depth -- adds depth for calculating pierce points");
349 System.out.println("-nodiscon -- only prints pierce points for the depths added with -pierce\n");
350 printStdUsageTail();
351 }
352
353 public String[] parseCmdLineArgs(String[] args) throws IOException {
354 int i = 0;
355 String[] leftOverArgs;
356 int numNoComprendoArgs = 0;
357 File tempFile;
358 leftOverArgs = super.parseCmdLineArgs(args);
359 String[] noComprendoArgs = new String[leftOverArgs.length];
360 while(i < leftOverArgs.length) {
361 if(leftOverArgs[i].equalsIgnoreCase("-turn")) {
362 onlyTurnPoints = true;
363 } else if(leftOverArgs[i].equalsIgnoreCase("-rev")) {
364 onlyRevPoints = true;
365 } else if(leftOverArgs[i].equalsIgnoreCase("-under")) {
366 onlyUnderPoints = true;
367 } else if(leftOverArgs[i].equalsIgnoreCase("-pierce")
368 && i < leftOverArgs.length - 1) {
369 appendAddDepths(leftOverArgs[i + 1]);
370 i++;
371 } else if(leftOverArgs[i].equalsIgnoreCase("-nodiscon")) {
372 onlyAddPoints = true;
373 } else if(leftOverArgs[i].equals("-help")) {
374 noComprendoArgs[numNoComprendoArgs++] = leftOverArgs[i];
375 } else {
376 noComprendoArgs[numNoComprendoArgs++] = leftOverArgs[i];
377 }
378 i++;
379 }
380 if(numNoComprendoArgs > 0) {
381 String[] temp = new String[numNoComprendoArgs];
382 System.arraycopy(noComprendoArgs, 0, temp, 0, numNoComprendoArgs);
383 return temp;
384 } else {
385 return new String[0];
386 }
387 }
388
389 /***
390 * Allows TauP_Pierce to run as an application. Creates an instance of
391 * TauP_Pierce. .
392 */
393 public static void main(String[] args) throws FileNotFoundException,
394 IOException, StreamCorruptedException, ClassNotFoundException,
395 OptionalDataException {
396 try {
397 TauP_Pierce tauPPierce = new TauP_Pierce();
398 String[] noComprendoArgs = tauPPierce.parseCmdLineArgs(args);
399 if(noComprendoArgs.length > 0) {
400 for(int i = 0; i < noComprendoArgs.length; i++) {
401 if(noComprendoArgs[i].equals("-help")
402 || noComprendoArgs[i].equals("-version")) {
403 System.exit(0);
404 }
405 }
406 System.out.println("I don't understand the following arguments, continuing:");
407 for(int i = 0; i < noComprendoArgs.length; i++) {
408 System.out.print(noComprendoArgs[i] + " ");
409 if(noComprendoArgs[i].equals("-help")
410 || noComprendoArgs[i].equals("-version")) {
411 System.out.println();
412 System.exit(0);
413 }
414 }
415 System.out.println();
416 noComprendoArgs = null;
417 }
418 if(tauPPierce.DEBUG) {
419 System.out.println("Done reading " + tauPPierce.modelName);
420 }
421 tauPPierce.init();
422 tauPPierce.start();
423 tauPPierce.destroy();
424 } catch(TauModelException e) {
425 System.out.println("Caught TauModelException: " + e.getMessage());
426 e.printStackTrace();
427 } catch(TauPException e) {
428 System.out.println("Caught TauPException: " + e.getMessage());
429 e.printStackTrace();
430 }
431 }
432 }