1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package edu.sc.seis.TauP;
29
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.Serializable;
33
34 /***
35 * This class provides storage and methods for generating slowness-depth
36 * pairs in a spherical earth model.
37 *
38 * @version 1.1.3 Wed Jul 18 15:00:35 GMT 2001
39
40
41
42 * @author H. Philip Crotwell
43 *
44 */
45 public class SphericalSModel extends SlownessModel
46 implements Serializable, Cloneable {
47
48
49
50 /*** Just for debugging purposes. */
51 public static void main(String[] args) {
52 System.out.println("Starting main");
53
54 VelocityModel vMod = new VelocityModel();
55 SphericalSModel sMod = new SphericalSModel();
56 String modelFilename;
57 if (args.length == 1) {
58 modelFilename = args[0];
59 } else {
60 vMod.setFileType("tvel");
61 modelFilename = File.separator+"MacintoshHD"+File.separator+"Philip"+File.separator+"TauP"+File.separator+"VModels"+File.separator+"iasp91.tvel";
62 }
63 boolean DEBUG = true;
64
65 try {
66 DEBUG = true;
67 vMod.readVelocityFile(modelFilename);
68 System.out.println("Done reading.");
69 if (DEBUG) System.out.println(vMod);
70 DEBUG = true;
71
72 sMod.DEBUG = true;
73
74 sMod.createSample(vMod);
75
76 if (sMod.DEBUG) System.out.println(sMod);
77 sMod.validate();
78 } catch (IOException e) {
79 System.out.println("Tried to read!\n Caught IOException "
80 + e.getMessage()+"\n"+e.getClass().getName());
81 e.printStackTrace();
82 } catch (VelocityModelException e) {
83 System.out.println("Tried to read!\n Caught VelocityModelException "
84 + e.getMessage());
85 e.printStackTrace();
86 } catch (SlownessModelException e) {
87 System.out.println(vMod);
88 System.out.println(sMod);
89 System.out.println("Tried to create slowness!\n Caught SlownessModelException "
90 + e.getMessage());
91 e.printStackTrace();
92 } finally {
93 System.out.println("Done!\n");
94 }
95
96 }
97
98 /*** Returns the slowness for a velocity at a depth.
99 * @exception SlownessModelException if velocity is zero. */
100 public double toSlowness(double velocity, double depth) throws SlownessModelException {
101 if (velocity == 0.0) {
102 throw new SlownessModelException("Divide by zero in toSlowness()"+
103 "\ndepth = "+depth+"\nThis likely has to do with using S velocities in the outer core");
104 }
105 return (radiusOfEarth-depth)/velocity;
106 }
107
108 /*** Returns the velocity for a slowness at a depth.
109 * @exception SlownessModelException if slowness is zero. */
110 public double toVelocity(double slowness, double depth) throws SlownessModelException {
111 if (slowness == 0.0) {
112 throw new SlownessModelException("Divide by zero in toVelocity()"+
113 "\ndepth = "+depth+"\nPossibly this is due to depth at center of the earth?");
114 }
115 return (radiusOfEarth-depth)/slowness;
116 }
117
118 /*** Converts a velocity layer into a slowness layer.
119 * @exception SlownessModelException if velocity layer is malformed. */
120 public SlownessLayer toSlownessLayer(VelocityLayer vLayer, boolean isPWave)
121 throws SlownessModelException {
122 return new SlownessLayer(vLayer, true, radiusOfEarth, isPWave);
123 }
124
125 /*** Returns the depth for a slowness given a velocity gradient.
126 * @exception SlownessModelException if the velocity gradient
127 * exactly balances the spherical decrease in slowness. */
128 public double interpolate(double p, double topVelocity, double topDepth,
129 double slope) throws SlownessModelException {
130 double depth;
131 double denominator = p * slope + 1.0;
132
133 if (denominator != 0.0) {
134 depth = (radiusOfEarth +
135 p* (topDepth*slope-topVelocity))/ denominator;
136 } else {
137
138
139
140
141
142
143 depth = Double.MAX_VALUE;
144 throw new SlownessModelException("Neg velocity gradient "+
145 "just balances the earth flattening!"+
146 " What should I do?!?!?!? topDepth= "+topDepth);
147 }
148 return depth;
149 }
150
151 /*** Calculates the time and distance increments accumulated by a
152 * ray of spherical ray parameter p when passing through layer layerNum.
153 * for the easy cases of zero ray parameter, the center of the earth,
154 * and constant velocity layers.
155 * Note that this gives 1/2 of the true range and time increments since
156 * there will be both an up going and a downgoing path.
157 *
158 * @exception SlownessModelException occurs if the ray with the given
159 * spherical ray parameter cannot propagate within this layer, or
160 * if the ray turns within this layer but not at the bottom.
161 */
162 public TimeDist layerTimeDist(double sphericalRayParam, int layerNum,
163 boolean isPWave) throws SlownessModelException {
164
165 double swapDouble;
166 double b;
167
168
169 TimeDist timedist = new TimeDist(sphericalRayParam);
170
171 SlownessLayer sphericalLayer = getSlownessLayer(layerNum, isPWave);
172 double topRadius = radiusOfEarth-sphericalLayer.getTopDepth();
173 double botRadius = radiusOfEarth-sphericalLayer.getBotDepth();
174
175
176
177
178 if (sphericalRayParam >
179 Math.max(sphericalLayer.getTopP(),sphericalLayer.getBotP())) {
180 throw new SlownessModelException("Ray cannot propagate within this"+
181 " layer. layerNum = "+ layerNum+
182 " sphericalRayParam="+sphericalRayParam+"\n"+sphericalLayer);
183 }
184 if (sphericalRayParam < 0.0) {
185 throw new SlownessModelException("Ray Parameter is negative!!! "+
186 sphericalRayParam);
187 }
188 if (sphericalRayParam >
189 Math.min(sphericalLayer.getTopP(),sphericalLayer.getBotP())) {
190 if (DEBUG) {
191 System.out.println("Ray Turns in layer, velocities: "+
192 topRadius/sphericalRayParam+" "+
193 topRadius/sphericalLayer.getTopP()+" "+
194 botRadius/sphericalLayer.getBotP());
195 System.out.println("depths top "+sphericalLayer.getTopDepth()+
196 " bot "+sphericalLayer.getBotDepth());
197 }
198 throw new SlownessModelException("Ray turns in the middle of this"+
199 " layer. \nlayerNum = "+ layerNum+
200 " sphericalRayParam "+sphericalRayParam+
201 " sphericalLayer = "+sphericalLayer+"\n");
202 }
203
204
205
206
207 if (sphericalLayer.getTopDepth() == sphericalLayer.getBotDepth()) {
208 timedist.time = 0.0;
209 timedist.dist = 0.0;
210 return timedist;
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234 if (sphericalRayParam == 0.0 && sphericalLayer.getBotDepth() == radiusOfEarth){
235 if (layerNum != getNumLayers(isPWave)-1) throw new SlownessModelException(
236 "There are layers deeper than the center of the earth!");
237
238 timedist.dist = Math.PI/2.0;
239 timedist.time = sphericalLayer.getTopP();
240
241 if (DEBUG) {
242 System.out.println("Center of Earth: dist "+timedist.dist+
243 " time "+timedist.time);
244 }
245 if (timedist.dist<0.0 || timedist.time<0.0 ||
246 Double.isNaN(timedist.time) || Double.isNaN(timedist.dist)) {
247 throw new SlownessModelException("CoE timedist <0.0 or NaN: "+
248 "sphericalRayParam= "+sphericalRayParam+
249 " botDepth = "+sphericalLayer.getBotDepth()+
250 " dist="+timedist.dist+
251 " time="+timedist.time);
252 }
253 return timedist;
254 }
255
256
257
258
259
260
261
262
263
264
265
266 if (Math.abs(topRadius/sphericalLayer.getTopP() -
267 botRadius/sphericalLayer.getBotP()) < slownessTolerance ) {
268
269
270 double vel = botRadius / sphericalLayer.getBotP();
271
272
273
274
275
276 double topTerm, botTerm;
277 topTerm = topRadius*topRadius-
278 sphericalRayParam*sphericalRayParam*vel*vel;
279 if (Math.abs(topTerm) < slownessTolerance) {topTerm = 0.0;}
280
281 if (sphericalRayParam == sphericalLayer.getBotP()) {
282
283
284
285
286
287 botTerm = 0.0;
288 } else {
289 botTerm = botRadius*botRadius-
290 sphericalRayParam*sphericalRayParam*vel*vel;
291 }
292
293
294 b = Math.sqrt(topTerm) - Math.sqrt(botTerm);
295
296 timedist.time = b/vel;
297
298 timedist.dist=Math.asin(b*sphericalRayParam*vel/(topRadius*botRadius));
299
300 if (timedist.dist<0.0 || timedist.time<0.0 ||
301 Double.isNaN(timedist.time) || Double.isNaN(timedist.dist)) {
302 throw new SlownessModelException("CVL timedist <0.0 or NaN: "+
303 "\nsphericalRayParam= "+sphericalRayParam+
304 "\n botDepth = "+sphericalLayer.getBotDepth()+
305 "\n topDepth = "+sphericalLayer.getTopDepth()+
306 "\n topRadius="+topRadius+" botRadius="+botRadius+
307 "\n dist="+timedist.dist+
308 "\n time="+timedist.time+
309 "\n b="+b+
310 "\n topTerm="+topTerm+
311 "\n botTerm="+botTerm+
312 "\n vel ="+vel+"\n"+
313 "\n bR^2 ="+(botRadius*botRadius)+
314 "\n p^2v^2 ="+sphericalRayParam*sphericalRayParam*vel*vel+
315 "\n tR^2 ="+(topRadius*topRadius)+
316 "\n p^2v^2 ="+sphericalRayParam*sphericalRayParam*vel*vel);
317
318 }
319 return timedist;
320 }
321
322
323
324
325
326
327 return sphericalLayer.bullenRadialSlowness(sphericalRayParam,
328 radiusOfEarth);
329 }
330
331 /*** Performs consistency check on the velocity model.
332 * @return true if successful, throws SlownessModelException otherwise.
333 * @exception SlownessModelException if any check fails
334 */
335 public boolean validate()
336 throws SlownessModelException
337 {
338 boolean isOK = super.validate();
339
340 double prevDepth= 0.0;
341 DepthRange highSZoneDepth, fluidZone;
342 SlownessLayer sLayer;
343
344 boolean isPWave = true;
345 for (int j=0;j<2; j++, isPWave = false) {
346 for (int i=0;i<getNumLayers(isPWave);i++) {
347 sLayer = getSlownessLayer(i,isPWave);
348 prevDepth = sLayer.getBotDepth();
349
350
351 if (prevDepth > radiusOfEarth) {
352 isOK = false;
353 throw new SlownessModelException(
354 "Slowness layer has a depth larger than the radius of "+
355 "the earth in a spherical model. max depth = "+prevDepth+
356 " radiusOfEarth = "+radiusOfEarth);
357 } else {
358 isOK |= true;
359 }
360 }
361 }
362
363
364
365 return isOK;
366 }
367
368
369
370 public Object clone() {
371 SphericalSModel newObject = (SphericalSModel)super.clone();
372
373 return newObject;
374 }
375
376 public String toString() {
377 int topCriticalLayerNum;
378 int botCriticalLayerNum;
379
380 String desc = "spherical model:\n"+super.toString();
381
382 return desc;
383 }
384
385 }
386