1
-
!! Acoustic arrivals module for computing and storing arrival information
4
-
!! Management of acoustic arrival data including storage, sorting, and output formatting
12
-
! Variables for arrival information
13
-
REAL, PARAMETER :: PhaseTol = 0.05 ! arrivals with essentially the same phase are grouped into one
15
-
INTEGER, ALLOCATABLE :: NArr( :, : ), NArr3D( :, :, : )
16
-
REAL (KIND=4) :: factor = 1.0
19
-
INTEGER :: NTopBnc, NBotBnc
20
-
REAL :: SrcDeclAngle, SrcAzimAngle, RcvrDeclAngle, RcvrAzimAngle, A, Phase
24
-
TYPE(Arrival), ALLOCATABLE :: Arr( :, :, : ), Arr3D( :, :, :, : )
28
962
SUBROUTINE AddArr( omega, id, ir, Amp, Phase, delay, SrcDeclAngle, RcvrDeclAngle, NumTopBnc, NumBotBnc )
29
-
!! Adds an arrival to the arrival data structure
31
-
! Adds the amplitude and delay for an ARRival into a matrix of same.
32
-
! Extra logic included to keep only the strongest arrivals.
34
-
INTEGER, INTENT( IN ) :: NumTopBnc, NumBotBnc, id, ir
35
-
REAL ( KIND = 8 ), INTENT( IN ) :: omega, Amp, Phase, SrcDeclAngle, RcvrDeclAngle
36
-
COMPLEX ( KIND = 8 ), INTENT( IN ) :: delay
38
-
INTEGER :: iArr( 1 ), Nt
39
-
REAL :: AmpTot, w1, w2
41
962*
Nt = NArr( id, ir ) ! # of arrivals
44
-
! Is this the second step of a pair (on the same ray)?
45
-
! If so, we want to combine the arrivals to conserve space.
46
-
! (test this by seeing if the arrival time is close to the previous one)
47
-
! (also need that the phase is about the same to make sure surface and direct paths are not joined)
48
-
! LP: BUG: This only checks the last arrival, whereas the first step of the
49
-
! pair could have been placed in previous slots. See readme.
51
962
IF ( Nt >= 1 ) THEN
52
1904*
IF ( omega * ABS( delay - Arr( id, ir, Nt )%delay ) < PhaseTol .AND. &
53
1409*
ABS( Arr( id, ir, Nt )%phase - Phase ) < PhaseTol ) NewRay = .FALSE.
56
962
IF ( NewRay ) THEN
57
505
IF ( Nt >= MaxNArr ) THEN ! space not available to add an arrival?
58
#####
iArr = MINLOC( Arr( id, ir, : )%A ) ! replace weakest arrival
59
#####
IF ( Amp > Arr( id, ir, iArr( 1 ) )%A ) THEN
60
#####
Arr( id, ir, iArr( 1 ) )%A = SNGL( Amp ) ! amplitude
61
#####
Arr( id, ir, iArr( 1 ) )%Phase = SNGL( Phase ) ! phase
62
#####
Arr( id, ir, iArr( 1 ) )%delay = CMPLX( delay ) ! delay time
63
#####
Arr( id, ir, iArr( 1 ) )%SrcDeclAngle = SNGL( SrcDeclAngle ) ! launch angle from source
64
#####
Arr( id, ir, iArr( 1 ) )%RcvrDeclAngle = SNGL( RcvrDeclAngle ) ! angle ray reaches receiver
65
#####
Arr( id, ir, iArr( 1 ) )%NTopBnc = NumTopBnc ! Number of top bounces
66
#####
Arr( id, ir, iArr( 1 ) )%NBotBnc = NumBotBnc ! " bottom
69
505*
NArr( id, ir ) = Nt + 1 ! # of arrivals
70
505*
Arr( id, ir, Nt + 1 )%A = SNGL( Amp ) ! amplitude
71
505*
Arr( id, ir, Nt + 1 )%Phase = SNGL( Phase ) ! phase
72
505*
Arr( id, ir, Nt + 1 )%delay = CMPLX( delay ) ! delay time
73
505*
Arr( id, ir, Nt + 1 )%SrcDeclAngle = SNGL( SrcDeclAngle ) ! launch angle from source
74
505*
Arr( id, ir, Nt + 1 )%RcvrDeclAngle = SNGL( RcvrDeclAngle ) ! angle ray reaches receiver
75
505*
Arr( id, ir, Nt + 1 )%NTopBnc = NumTopBnc ! Number of top bounces
76
505*
Arr( id, ir, Nt + 1 )%NBotBnc = NumBotBnc ! " bottom
78
-
ELSE ! not a new ray
79
-
!PhaseArr( id, ir, Nt ) = PhaseArr( id, ir, Nt )
81
-
! calculate weightings of old ray information vs. new, based on amplitude of the arrival
82
457*
AmpTot = Arr( id, ir, Nt )%A + SNGL( Amp )
83
457*
w1 = Arr( id, ir, Nt )%A / AmpTot
84
457
w2 = REAL( Amp ) / AmpTot
86
457*
Arr( id, ir, Nt )%delay = w1 * Arr( id, ir, Nt )%delay + w2 * CMPLX( delay ) ! weighted sum
87
457*
Arr( id, ir, Nt )%A = AmpTot
88
457*
Arr( id, ir, Nt )%SrcDeclAngle = w1 * Arr( id, ir, Nt )%SrcDeclAngle + w2 * SNGL( SrcDeclAngle )
89
457*
Arr( id, ir, Nt )%RcvrDeclAngle = w1 * Arr( id, ir, Nt )%RcvrDeclAngle + w2 * SNGL( RcvrDeclAngle )
93
-
END SUBROUTINE AddArr
95
-
! **********************************************************************!
97
8*
SUBROUTINE WriteArrivalsASCII( r, Nrd, Nr, SourceType )
98
-
!! Writes arrival data in ASCII format
100
-
! Writes the arrival data (Amplitude, delay for each eigenray)
101
-
! ASCII output file
103
-
INTEGER, INTENT( IN ) :: Nrd, Nr
104
-
REAL, INTENT( IN ) :: r( Nr )
105
-
CHARACTER (LEN=1), INTENT( IN ) :: SourceType
106
-
INTEGER :: ir, id, iArr
108
34*
WRITE( ARRFile, * ) MAXVAL( NArr( 1 : Nrd, 1 : Nr ) )
112
13
IF ( SourceType == 'X' ) THEN ! line source
113
#####
factor = 4.0 * SQRT( pi )
114
-
ELSE ! point source
115
13*
IF ( r ( ir ) == 0 ) THEN
116
#####
factor = 1e5 ! avoid /0 at origin
118
13*
factor = 1. / SQRT( ABS( r( ir ) ) ) ! cyl. spreading [CF] ABS() used to eliminate NaN for -ve range values
122
13*
WRITE( ARRFile, * ) NArr( id, ir )
123
526*
DO iArr = 1, NArr( id, ir )
124
-
! You can compress the output file a lot by putting in an explicit format statement here ...
125
-
! However, you'll need to make sure you keep adequate precision
126
-
WRITE( ARRFile, * ) &
127
505*
factor * Arr( id, ir, iArr )%A, &
128
505*
SNGL( RadDeg ) * Arr( id, ir, iArr )%Phase, &
129
505*
REAL( Arr( id, ir, iArr )%delay ), &
130
505*
AIMAG( Arr( id, ir, iArr )%delay ), &
131
505*
Arr( id, ir, iArr )%SrcDeclAngle, &
132
505*
Arr( id, ir, iArr )%RcvrDeclAngle, &
133
505*
Arr( id, ir, iArr )%NTopBnc, &
134
1023
Arr( id, ir, iArr )%NBotBnc
135
-
END DO ! next arrival
136
-
END DO ! next receiver depth
137
-
END DO ! next receiver range
140
-
END SUBROUTINE WriteArrivalsASCII
142
-
! **********************************************************************!
145
#####
SUBROUTINE WriteArrivalsBinary( r, Nrd, Nr, SourceType )
146
-
!! Writes arrival data in binary format
148
-
! Writes the arrival data (amplitude, delay for each eigenray)
149
-
! Binary output file
151
-
INTEGER, INTENT( IN ) :: Nrd, Nr
152
-
REAL, INTENT( IN ) :: r( Nr )
153
-
CHARACTER (LEN=1), INTENT( IN ) :: SourceType
154
-
INTEGER :: ir, id, iArr
156
#####
WRITE( ARRFile ) MAXVAL( NArr( 1 : Nrd, 1 : Nr ) )
160
#####
IF ( SourceType == 'X' ) THEN ! line source
161
#####
factor = 4.0 * SQRT( pi )
162
-
ELSE ! point source
163
#####
IF ( r ( ir ) == 0 ) THEN
164
#####
factor = 1e5 ! avoid /0 at origin
166
#####
factor = 1. / SQRT( r( ir ) ) ! cyl. spreading
170
#####
WRITE( ARRFile ) NArr( id, ir )
172
#####
DO iArr = 1, NArr( id, ir )
173
-
! integers written out as reals below for fast reading in Matlab
175
#####
factor * Arr( id, ir, iArr )%A, &
176
#####
SNGL( RadDeg * Arr( id, ir, iArr )%Phase ), &
177
#####
Arr( id, ir, iArr )%delay, &
178
#####
Arr( id, ir, iArr )%SrcDeclAngle, &
179
#####
Arr( id, ir, iArr )%RcvrDeclAngle, &
180
#####
REAL( Arr( id, ir, iArr )%NTopBnc ), &
181
#####
REAL( Arr( id, ir, iArr )%NBotBnc )
183
-
END DO ! next arrival
184
-
END DO ! next receiver depth
185
-
END DO ! next receiver range
188
-
END SUBROUTINE WriteArrivalsBinary
190
-
! **********************************************************************!
192
#####
SUBROUTINE AddArr3D( omega, itheta, id, ir, Amp, Phase, delay, SrcDeclAngle, &
193
-
SrcAzimAngle, RcvrDeclAngle, RcvrAzimAngle, NumTopBnc, NumBotBnc )
194
-
!! Adds the amplitude and delay for an ARRival into a matrix of same.
196
-
! Extra logic included to keep only the strongest arrivals.
198
-
INTEGER, INTENT( IN ) :: itheta, id, ir
199
-
INTEGER, INTENT( IN ) :: NumTopBnc, NumBotBnc
200
-
REAL ( KIND = 8 ), INTENT( IN ) :: omega, Amp, Phase, SrcDeclAngle, SrcAzimAngle, RcvrDeclAngle, RcvrAzimAngle
202
-
COMPLEX ( KIND = 8 ), INTENT( IN ) :: delay
204
-
INTEGER :: iArr( 1 ), Nt
205
-
REAL :: AmpTot, w1, w2
207
#####
Nt = NArr3D( itheta, id, ir ) ! # of arrivals
208
#####
NewRay = .TRUE.
210
-
! Is this the second bracketing ray of a pair?
211
-
! If so, we want to combine the arrivals to conserve space.
212
-
! (test this by seeing if the arrival time is close to the previous one)
213
-
! (also need that the phase is about the same to make sure surface and direct paths are not joined)
214
-
! LP: BUG: This only checks the last arrival, whereas the first step of the
215
-
! pair could have been placed in previous slots. See readme.
217
#####
IF ( Nt >= 1 ) THEN
218
#####
IF ( omega * ABS( delay - Arr3D( itheta, id, ir, Nt )%delay ) < PhaseTol .AND. &
219
#####
ABS( Arr3D( itheta, id, ir, Nt )%phase - Phase ) < PhaseTol ) NewRay = .FALSE.
222
#####
IF ( NewRay ) THEN
223
#####
IF ( Nt >= MaxNArr ) THEN ! space available to add an arrival?
224
#####
iArr = MINLOC( Arr3D( itheta, id, ir, : )%A ) ! no: replace weakest arrival
225
#####
IF ( Amp > Arr3D( itheta, id, ir, iArr( 1 ) )%A ) THEN
226
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%A = SNGL( Amp ) ! amplitude
227
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%Phase = SNGL( Phase ) ! phase
228
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%delay = CMPLX( delay ) ! delay time
229
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%SrcDeclAngle = SNGL( SrcDeclAngle ) ! angle
230
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%SrcAzimAngle = SNGL( SrcAzimAngle ) ! angle
231
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%RcvrDeclAngle = SNGL( RcvrDeclAngle ) ! angle
232
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%RcvrAzimAngle = SNGL( RcvrAzimAngle ) ! angle
233
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%NTopBnc = NumTopBnc ! Number of top bounces
234
#####
Arr3D( itheta, id, ir, iArr( 1 ) )%NBotBnc = NumBotBnc ! " bottom
237
#####
NArr3D( itheta, id, ir ) = Nt + 1 ! # of arrivals
238
#####
Arr3D( itheta, id, ir, Nt + 1 )%A = SNGL( Amp ) ! amplitude
239
#####
Arr3D( itheta, id, ir, Nt + 1 )%Phase = SNGL( Phase ) ! phase
240
#####
Arr3D( itheta, id, ir, Nt + 1 )%delay = CMPLX( delay ) ! delay time
241
#####
Arr3D( itheta, id, ir, Nt + 1 )%SrcDeclAngle = SNGL( SrcDeclAngle ) ! angle
242
#####
Arr3D( itheta, id, ir, Nt + 1 )%SrcAzimAngle = SNGL( SrcAzimAngle ) ! angle
243
#####
Arr3D( itheta, id, ir, Nt + 1 )%RcvrDeclAngle = SNGL( RcvrDeclAngle ) ! angle
244
#####
Arr3D( itheta, id, ir, Nt + 1 )%RcvrAzimAngle = SNGL( RcvrAzimAngle ) ! angle
245
#####
Arr3D( itheta, id, ir, Nt + 1 )%NTopBnc = NumTopBnc ! Number of top bounces
246
#####
Arr3D( itheta, id, ir, Nt + 1 )%NBotBnc = NumBotBnc ! " bottom
248
-
ELSE ! not a new ray
249
-
!PhaseArr( id, ir, Nt ) = PhaseArr( id, ir, Nt )
250
-
! calculate weightings of old ray information vs. new, based on amplitude of the arrival
251
#####
AmpTot = Arr3D( itheta, id, ir, Nt )%A + SNGL( Amp )
252
#####
w1 = Arr3D( itheta, id, ir, Nt )%A / AmpTot
253
#####
w2 = REAL( Amp ) / AmpTot
255
#####
Arr3D( itheta, id, ir, Nt )%delay = w1 * Arr3D( itheta, id, ir, Nt )%delay + w2 * CMPLX( delay ) ! weighted sum
256
#####
Arr3D( itheta, id, ir, Nt )%A = AmpTot
257
#####
Arr3D( itheta, id, ir, Nt )%SrcDeclAngle = w1 * Arr3D( itheta, id, ir, Nt )%SrcDeclAngle + w2 * SNGL( SrcDeclAngle )
258
#####
Arr3D( itheta, id, ir, Nt )%SrcAzimAngle = w1 * Arr3D( itheta, id, ir, Nt )%SrcAzimAngle + w2 * SNGL( SrcAzimAngle )
259
#####
Arr3D( itheta, id, ir, Nt )%RcvrDeclAngle = w1 * Arr3D( itheta, id, ir, Nt )%RcvrDeclAngle + w2 * SNGL( RcvrDeclAngle )
260
#####
Arr3D( itheta, id, ir, Nt )%RcvrAzimAngle = w1 * Arr3D( itheta, id, ir, Nt )%RcvrAzimAngle + w2 * SNGL( RcvrAzimAngle )
264
-
END SUBROUTINE AddArr3D
266
-
! **********************************************************************!
268
#####
SUBROUTINE WriteArrivalsASCII3D( r, Ntheta, Nrd, Nr )
269
-
!! Writes the arrival data (Amplitude, delay for each eigenray); ASCII output file
271
-
INTEGER, INTENT( IN ) :: Ntheta, Nrd, Nr
272
-
REAL, INTENT( IN ) :: r( Nr )
273
-
INTEGER :: itheta, ir, id, iArr
275
#####
WRITE( ARRFile, * ) MAXVAL( NArr3D( 1 : Ntheta, 1 : Nrd, 1 : Nr ) )
277
#####
DO itheta = 1, Ntheta
280
#####
IF ( Beam%RunType( 6 : 6 ) == '2' ) THEN ! 2D run?
281
#####
IF ( r ( ir ) == 0 ) THEN
282
#####
factor = 1e5 ! avoid /0 at origin
284
#####
factor = 1. / SQRT( r( ir ) ) ! cyl. spreading
288
#####
WRITE( ARRFile, * ) NArr3D( itheta, id, ir )
290
#####
DO iArr = 1, NArr3D( itheta, id, ir )
291
-
! you can compress the output file a lot by putting in an explicit format statement here ...
292
-
! However, you'll need to make sure you keep adequate precision
293
-
WRITE( ARRFile, * ) &
294
#####
factor * Arr3D( itheta, id, ir, iArr )%A, &
295
#####
RadDeg * Arr3D( itheta, id, ir, iArr )%Phase, &
296
#####
REAL( Arr3D( itheta, id, ir, iArr )%delay ), &
297
#####
AIMAG( Arr3D( itheta, id, ir, iArr )%delay ), &
298
#####
Arr3D( itheta, id, ir, iArr )%SrcDeclAngle, &
299
#####
Arr3D( itheta, id, ir, iArr )%SrcAzimAngle, &
300
#####
Arr3D( itheta, id, ir, iArr )%RcvrDeclAngle, &
301
#####
Arr3D( itheta, id, ir, iArr )%RcvrAzimAngle, &
302
#####
Arr3D( itheta, id, ir, iArr )%NTopBnc, &
303
#####
Arr3D( itheta, id, ir, iArr )%NBotBnc
304
-
END DO ! next arrival
305
-
END DO ! next receiver depth
306
-
END DO ! next receiver range
307
-
END DO ! next receiver angle
310
-
END SUBROUTINE WriteArrivalsASCII3D
312
-
! **********************************************************************!
314
#####
SUBROUTINE WriteArrivalsBinary3D( r, Ntheta, Nrd, Nr )
315
-
!! Writes the arrival data (amplitude, delay for each eigenray); Binary output file
317
-
INTEGER, INTENT( IN ) :: Ntheta, Nrd, Nr
318
-
REAL, INTENT( IN ) :: r( Nr )
319
-
INTEGER :: itheta, ir, id, iArr
321
#####
WRITE( ARRFile ) MAXVAL( NArr3D( 1 : Ntheta, 1 : Nrd, 1 : Nr ) )
323
#####
DO itheta = 1, Ntheta
326
#####
IF ( Beam%RunType( 6 : 6 ) == '2' ) THEN ! 2D run?
327
#####
IF ( r ( ir ) == 0 ) THEN
328
#####
factor = 1e5 ! avoid /0 at origin
330
#####
factor = 1. / SQRT( r( ir ) ) ! cyl. spreading
334
#####
WRITE( ARRFile ) NArr3D( itheta, id, ir )
336
#####
DO iArr = 1, NArr3D( itheta, id, ir )
337
-
! integers written out as reals below for fast reading in Matlab
339
#####
factor * Arr3D( itheta, id, ir, iArr )%A, &
340
#####
SNGL( RadDeg * Arr3D( itheta, id, ir, iArr )%Phase ), &
341
#####
Arr3D( itheta, id, ir, iArr )%delay, &
342
#####
Arr3D( itheta, id, ir, iArr )%SrcDeclAngle, &
343
#####
Arr3D( itheta, id, ir, iArr )%SrcAzimAngle, &
344
#####
Arr3D( itheta, id, ir, iArr )%RcvrDeclAngle, &
345
#####
Arr3D( itheta, id, ir, iArr )%RcvrAzimAngle, &
346
#####
REAL( Arr3D( itheta, id, ir, iArr )%NTopBnc ), &
347
#####
REAL( Arr3D( itheta, id, ir, iArr )%NBotBnc )
348
-
END DO ! next arrival
349
-
END DO ! next receiver depth
350
-
END DO ! next receiver range
351
-
END DO ! next receiver angle
354
-
END SUBROUTINE WriteArrivalsBinary3D
356
#####
END MODULE ArrMod