PROGRAM EQ_classification_II ! ! Reads: (1) PB2002_poles.dat (derived from PB2002_poles.xls by dropping headers, names, and areas) ! and: (2) PB2002_steps.dig (see Table 2 from Bird [2003]: step characteristics from model PB2002) ! and: (3) PB2002_orogens.dig (CCW outlines of orogens; events and steps here are *-ed) ! and: (4) XXXX.eqc (catalog of shallow earthquakes: e.g., CMT, or Pacheco and Sykes [1992]) ! ! Creates 2 * 8 = 16 .eqc files: (Note: "Pure" .eqc's don't include *-ed EQs or steps.) ! class 0: XXXX_PB2002_INT_pure.eqc and XXXX_PB2002_INT_all.eqc INTraplate (plate-INTerior) ! class 1: XXXX_PB2002_CCB_pure.eqc and XXXX_PB2002_CCB_all.eqc Continental Convergent Boundary ! class 2: XXXX_PB2002_CTF_pure.eqc and XXXX_PB2002_CTF_all.eqc Continental Transform Fault ! class 3: XXXX_PB2002_CRB_pure.eqc and XXXX_PB2002_CRB_all.eqc Continental Rift Boundary ! class 4: XXXX_PB2002_OSR_pure.eqc and XXXX_PB2002_OSR_all.eqc Oceanic Spreading Ridge ! class 5: XXXX_PB2002_OTF_pure.eqc and XXXX_PB2002_OTF_all.eqc Oceanic Transform Fault ! class 6: XXXX_PB2002_OCB_pure.eqc and XXXX_PB2002_OCB_all.eqc Oceanic Convergent Boundary ! class 7: XXXX_PB2002_SUB_pure.eqc and XXXX_PB2002_SUB_all.eqc SUBduction zone ! ! by Peter Bird, UCLA, 2003.02.14-2003.04.07 ! This is the second attempt at a classification scheme for shallow earthquakes. ! This method is based on the assessment of the relative probabilities that ! a given actual earthquake was caused by each of the plate boundary steps in PB2002. ! Factors considered include: ! A: relative seismicity of each step, based on its length, velocity, and class. ! B: spatial PDF around each boundary step based on known apparent half-widths, ! and earthquake and step location errors around its ends; ! And for each of a set of (up to) 5 model earthquakes for each boundary class: ! C: relative probability of this particular model earthquake; ! D: depth PDF for this model earthquake (if depth is known); ! E: rotation-angle PDF to test match between actual and model moment tensor; ! for Pacheco & Sykes [1992] catalog this factor must be simplified or dropped. ! ! Addition by Peter Bird, UCLA, in 2003.06: ! A set of 7 files "PB2002_XXX_pure.dat" (where XXX is CCB, CTF, CRB, OSR, OTF, OCB, SUB) ! are also created to record earthquake numbers and total moments associated with each ! pure plate boundary step of type XXX. ! A threshhold magnitude "class_threshhold magnitude" is imposed to make the sums consistent worldwide. ! After running this, the file names should probably be modified to show the ! origin of the catalog that was used (e.g., add "_CMT" to the file names, just before ".dat"). ! (It is understood that when creating these files, parameter Monte_Carlo_method should be .FALSE.) ! ! **** Read the REAL, PARAMETER section below and adjust the values! ***************** USE Sphere ! Peter Bird's personal library of spherical-trigonometry and Cartesian-vector routines USE Numerical_Libraries ! IMSL Library, used for ANORDF = distribution function of a standard normal (Gaussian) variable; ! and also for RNOPT/RNSET/RNUN if Monte_Carlo_method = .TRUE. USE Quaternion ! for DCROT function, from Kagan [1991], Geophys. J. Int., v. 106, p. 709-716. IMPLICIT NONE INTEGER, PARAMETER :: nPlates = 52 ! referring to PB2002 model CHARACTER*1 :: eq_tenths, pure_epicenter_c1, pure_step_c1 CHARACTER*2 :: eq_month, eq_day, eq_hour, eq_minute, eq_second CHARACTER*2, DIMENSION(nPlates) :: ID CHARACTER*3 :: c3 CHARACTER*5 :: zone ! time zone CHARACTER*8 :: date ! date program is run CHARACTER*9 :: catalog_name, prefix CHARACTER*10 :: clock_time ! wall clock time CHARACTER*27 :: c27 CHARACTER*80 :: appended_data, catalog_file_name, out_file_name CHARACTER*3, DIMENSION(0:7) :: class_c3 ! = INT, plus boundary classes 1-7 CHARACTER*1, DIMENSION(:), ALLOCATABLE :: step_continuity_c1, class_continuity_c1, star_c1 CHARACTER*3, DIMENSION(:), ALLOCATABLE :: class CHARACTER*5, DIMENSION(:), ALLOCATABLE :: c5 INTEGER, PARAMETER :: nOrogens = 13, mostInOneOrogen = 500 ! referring to PB2002_orogens.dig; really, most is 315 INTEGER :: i ! = indentifier for the PB2002 plate boundary step being considered (up to 5819 = nSteps) INTEGER :: j ! = indentifier for the model EQ being considered (1 to 4) INTEGER :: k ! = indentifier of the class of plate boundary step i; range 1..7 = CCB, CTF, CRB, OSR, OTF, OCB, SUB INTEGER :: best_i, best_k, catalog_ID, crossstrike_dip_degrees, & & eq_year, eq_depth_int, e1_plunge, e1_azimuth, & & e2_plunge, e2_azimuth, e3_plunge, e3_azimuth, & & i0, iEvent, iLeftPlate, iRightPlate, ios, iseed, & & n, nEvents, nSteps, & & slab_velocity_azimuth_integer, slab_downdip_azimuth_integer, & & P_azimuth_degrees, P_plunge_degrees, T_azimuth_degrees, T_plunge_degrees, & & velocity_dip_degrees INTEGER*2, DIMENSION(4) :: actual_TpaPpa_degrees, model_TpaPpa_degrees ! TYPE *must* agree with MODULE Quaternion! INTEGER, DIMENSION(7) :: best_i_in_class INTEGER, DIMENSION(7) :: N_over_mt ! corresponds to N_k in paper INTEGER, DIMENSION(7) :: relative_class_probability_int ! relative % likelihood of 7 classes, output for each EQ except INT's INTEGER, DIMENSION(0:7) :: count_all, count_pure, percentages ! note: 0 subscript corresponds to INT subcatalogs INTEGER, DIMENSION(8) :: datetimenumber ! for output from DATE_AND_TIME INTEGER, DIMENSION(nOrogens) :: nInEachOrogen INTEGER, DIMENSION(:), ALLOCATABLE :: azimuth_integer, age_Ma, & & elevation, eq_count_over_threshhold, & & k_of, & & sequence_number, velocity_azimuth_integer LOGICAL :: dip_is_to_right, eq_depth_known, inside, mechanism_known, normal, & & proximal, pure_epicenter, pure_step, relative_velocity_is_divergent, & & strikeslip, thrust, unknown LOGICAL, DIMENSION(7) :: in_competition REAL, PARAMETER :: radius_km = 6371.0 ! of the spherical model of the Earth !********************** USER SELECTIONS: REVIEW THESE CAREFULLY! ******************************************** !All boundaries: LOGICAL, PARAMETER :: Monte_Carlo_method = .FALSE. ! (alternative is assignment to maximum-probability step) REAL, PARAMETER :: alongStep_sigma_km = 32.5 ! so combined EQ mislocation and step-mislocation unlikely to exceed twice this value REAL, PARAMETER :: earthquake_depth_sigma_km = 15.0 ! always *some* probability down to 70 km when class123456_cutoff_depth_km = 25.0 REAL, PARAMETER :: Phi_max_degrees = 60.0 ! cut-off rotation for matching model and actual moment tensors REAL, PARAMETER :: class123456_cutoff_depth_km = 25.0 INTEGER, PARAMETER :: CCB_pure_totalEvents = 274 ! N_k values for m_t = 5.66, Harvard CMT 1977.01.01-2002.09.30 INTEGER, PARAMETER :: CTF_pure_totalEvents = 198 ! These values last adjusted 2003.04.08, 12:45, based on INTEGER, PARAMETER :: CRB_pure_totalEvents = 134 ! fifth iteration of boot-strap method! INTEGER, PARAMETER :: OSR_pure_totalEvents = 142 ! This iteration was run with Monte_Carlo_method = .FALSE. INTEGER, PARAMETER :: OTF_pure_totalEvents = 838 ! These are suggested for processing of the full, incomplete CMT catalog. INTEGER, PARAMETER :: OCB_pure_totalEvents = 105 ! INTEGER, PARAMETER :: SUB_pure_totalEvents = 2049 ! !INTEGER, PARAMETER :: CCB_pure_totalEvents = 10 ! N_k values for m_t = 6.99, Harvard CMT 1977.01.01-2002.09.30 !INTEGER, PARAMETER :: CTF_pure_totalEvents = 9 ! and Ekstrom and Nettles [1997] 1976 events. !INTEGER, PARAMETER :: CRB_pure_totalEvents = 4 ! These values last adjusted 2003.04.08, 14:18, based on !INTEGER, PARAMETER :: OSR_pure_totalEvents = 1 ! fifth iteration of boot-strap method !INTEGER, PARAMETER :: OTF_pure_totalEvents = 6 ! This iteration was run with Monte_Carlo_method = .FALSE. !INTEGER, PARAMETER :: OCB_pure_totalEvents = 10 ! These are suggested for max-prob processing of Pacheco & Sykes, 1900-1975. !INTEGER, PARAMETER :: SUB_pure_totalEvents = 111 ! ! V !INTEGER, PARAMETER :: CCB_pure_totalEvents = 237 ! 249 247 245 229 237 ! Record of 5 consecutive (post-5-for-convergence) iterations !INTEGER, PARAMETER :: CTF_pure_totalEvents = 202 ! 209 195 204 205 202 ! of the Monte Carlo method applied to CMT_shallow_complete.eqc !INTEGER, PARAMETER :: CRB_pure_totalEvents = 150 ! 140 138 136 144 150 ! (m_t = 5.66; complete). Computed 2003.04.08, 15:35-15:40. !INTEGER, PARAMETER :: OSR_pure_totalEvents = 153 ! 157 158 153 150 153 ! These can be recycled in classifications of the full !INTEGER, PARAMETER :: OTF_pure_totalEvents = 809 ! 819 811 827 816 809 ! CMT_shallow.eqc, to capture the effects of the !INTEGER, PARAMETER :: OCB_pure_totalEvents = 141 ! 128 124 122 132 141 ! uncertainties in the N_k under the Monte Carlo regime. !INTEGER, PARAMETER :: SUB_pure_totalEvents = 2046 ! 2037 2065 2051 2061 2046 ! ! V !INTEGER, PARAMETER :: CCB_pure_totalEvents = 10 ! 10 12 10 10 10 ! Record of 5 consecutive (post-5-for-convergence) iterations !INTEGER, PARAMETER :: CTF_pure_totalEvents = 6 ! 11 11 6 10 6 ! of the Monte Carlo method applied to CMT_shallow_m7_1976-2002.eqc !INTEGER, PARAMETER :: CRB_pure_totalEvents = 5 ! 4 3 5 4 5 ! (m_t = 6.99; Ekstrom & Nettles [1997] for 1976, + CMT)). !INTEGER, PARAMETER :: OSR_pure_totalEvents = 1 ! 1 1 1 1 1 ! These can be recycled in classifications of the Pacheco !INTEGER, PARAMETER :: OTF_pure_totalEvents = 6 ! 6 6 8 6 6 ! & Sykes catalog, to capture the effects of the !INTEGER, PARAMETER :: OCB_pure_totalEvents = 11 ! 20 8 11 10 11 ! uncertainties in the N_k under the Monte Carlo regime. !INTEGER, PARAMETER :: SUB_pure_totalEvents = 112 ! 109 110 110 110 112 ! REAL, PARAMETER :: CCB_pure_totalLength_km = 12516.0 REAL, PARAMETER :: CTF_pure_totalLength_km = 19375.0 REAL, PARAMETER :: CRB_pure_totalLength_km = 18126.0 REAL, PARAMETER :: OSR_pure_totalLength_km = 61807.0 ! these values last adjusted 2003.02.14, afternoon, REAL, PARAMETER :: OTF_pure_totalLength_km = 43902.0 ! based on PB2002_XXX_pure_lineIntegral.xls, same date REAL, PARAMETER :: OCB_pure_totalLength_km = 13236.0 REAL, PARAMETER :: SUB_pure_totalLength_km = 38990.0 REAL, PARAMETER :: CCB_pure_meanVelocity_mmpa = 18.2 REAL, PARAMETER :: CTF_pure_meanVelocity_mmpa = 21.5 REAL, PARAMETER :: CRB_pure_meanVelocity_mmpa = 19.0 REAL, PARAMETER :: OSR_pure_meanVelocity_mmpa = 48.3 ! these values last adjusted 2003.02.14, afternoon, REAL, PARAMETER :: OTF_pure_meanVelocity_mmpa = 40.4 ! based on PB2002_XXX_pure_lineIntegral.xls, same date REAL, PARAMETER :: OCB_pure_meanVelocity_mmpa = 19.2 REAL, PARAMETER :: SUB_pure_meanVelocity_mmpa = 61.5 !non-SUB boundaries (symmetrical): REAL, PARAMETER :: CCB_halfwidth_km = 189.0 REAL, PARAMETER :: CTF_halfwidth_km = 257.0 REAL, PARAMETER :: CRB_halfwidth_km = 154.0 REAL, PARAMETER :: OSR_halfwidth_km = 132.0 REAL, PARAMETER :: OTF_halfwidth_km = 128.0 REAL, PARAMETER :: OCB_halfwidth_km = 186.0 ! these values last adjusted 2003.02.12, 4:22 PM. !SUB boundaries (asymmetrical): REAL, PARAMETER :: SUB_landward_halfwidth_km = 220.0 ! landward width of subduction lanes, in km from trench REAL, PARAMETER :: SUB_seaward_halfwidth_km = 135.0 ! seaward half-width of subduction lanes, in km from trench REAL, PARAMETER :: SUB_peakSeismicity_km = 55.0 ! location of seismicity peak, relative to trench !The following lines create a standard quadratic model of depth to the slab top, !which is used (only) in depth PDF "D" in connection with model EQs on SUB steps: REAL, PARAMETER :: trench_depth_km = 8.25 ! p.221 of Le Pichon et al. [1976]; measured from sea level REAL, PARAMETER :: slope_at_trench = 0.1400 ! = 8 degrees; ibid (not a great source!) REAL, PARAMETER :: slab_depth_under_arc_km = 100.0 ! reference? Measured from sea level. REAL, PARAMETER :: arc_distance_km = 200.0 ! used in conjunction with above line to pin quadratic model of slab-top depth REAL, PARAMETER :: interplate_thrust_depth_sigma_fraction = 0.10 ! uncertainty in standard quadratic model of slab-top depth !Note: Use SUB_quadratic_profile.xls to experiment with these parameters. !Threshhold magnitudes by class: ! (Note: These values are used only in creating the 7 files PB2002_XXX_pure.dat, ! but when creating the subcatalog (.eqc) files, no threshhold is imposed. ! These following lines were added in the 2003.06 extension of this program.) REAL, PARAMETER :: CCB_threshhold_magnitude = 5.66 ! from Table 5 of Bird & Kagan, BSSA, 2003(?) REAL, PARAMETER :: CTF_threshhold_magnitude = 5.66 REAL, PARAMETER :: CRB_threshhold_magnitude = 5.33 REAL, PARAMETER :: OSR_threshhold_magnitude = 5.33 REAL, PARAMETER :: OTF_threshhold_magnitude = 5.50 REAL, PARAMETER :: OCB_threshhold_magnitude = 5.66 REAL, PARAMETER :: SUB_threshhold_magnitude = 5.66 ! ************************************************************************************************************ REAL :: A ! relative number (or rate) of EQs (over m_t) produced by the current plate boundary step REAL :: B ! PDF (per square km) that an EQ produced by this step is at the actual (longitude, latitude) REAL :: C ! relative probability of this model earthquake, compared to other (up to 3) models REAL :: D ! PDF (per km) that an EQ of this model occured at the actual EQ depth (if known; otherwise punt). REAL :: E ! PDF (per steradian) that this actual EQ mechanism (if known) matches the model EQ REAL :: sum_CDE ! SUM(j=1,4) {C * D * E} for all model earthquakes on this step REAL :: P_prime ! relative probability that this step produced the EQ in question REAL :: s_km ! local coordinate, measured along direction of plate boundary step, from 0 at initial point. REAL :: X ! cross-trace component of spatial PDF B; a function of cross-step offset (from peak of seismicity) REAL :: Y ! along-trace component of spatial PDF B; a function of along-step distance s REAL :: angle, angle_sum, argument, azimuth_radians, & & basis_length_km, & & closing_angle_radians, crossstrike_dip_radians, & & distance_km, distance_at_peak_km, ds, & & eq_Elon, eq_Nlat, eq_mag, eq_moment_Nm, & & fault_dip_degrees, fault_strike_degrees, fraction_toward_uvec1, from_trench_azimuth_radians, & & highest_P_prime, integral, & & interplate_thrust_depth_km, interplate_thrust_depth_sigma_km, & & lat, lane_width_km, lon, & & midpoint_compass, minimum_depth_km, & & offset_km, offside_radians, opening_angle_radians, & & partial_sum, & & quadratic, & & random, relative_velocity_azimuth_degrees, rotation_degpMa, & & s_radians, s1, s2, scalar_product, & & SUB_landward_radians, SUB_landward_sigma_km, SUB_seaward_radians, SUB_seaward_sigma_km, & & sum_P_prime_all_classes, & & to_uvec1_radians, to_uvec2_radians, t_latitude, t_longitude, t1, t2, & & velocity_dip_radians, velocity_East, velocity_North REAL*8 :: minimum_angle_degrees ! TYPE *must* agree with MODULE Quaternion! REAL, DIMENSION(3) :: c1_uvec, c2_uvec, c3_uvec, c4_uvec, & & eq_uvec, inward_uvec, omega_uvec, pole_uvec, tEuler, trench_uvec, tvec, & & uvec, uvec1, uvec2, velocity REAL, DIMENSION(4) :: dot_side ! sine of angle between EQ and sides of a subduction lane; positive inward REAL, DIMENSION(7) :: class_threshhold_magnitude REAL, DIMENSION(7) :: highest_P_prime_in_class REAL, DIMENSION(7) :: L_km ! corresponds to L_k in paper. REAL, DIMENSION(7) :: sum_P_prime_in_class ! sums of P_prime for all steps in one class REAL, DIMENSION(7) :: upper_fraction REAL, DIMENSION(7) :: V_mmpa ! corresponds to V_k in paper REAL, DIMENSION(6) :: h_km ! corresponds to h_k in paper; no entry for SUB because that is asymmetrical REAL, DIMENSION(3, nPlates) :: Euler REAL, DIMENSION(3, mostInOneOrogen, nOrogens) :: orogen_uvecs REAL, DIMENSION(:), ALLOCATABLE :: arc_km_from_step, & & dextral_mmpa, distance_km_from_step, divergence_mmpa, & & latitude, length_km, longitude, & & moment_sum_over_threshhold, & & old_longitude, old_latitude, & & subduction_azimuth_1, subduction_azimuth_2, & & velocity_mmpa, Y_factor_of_step REAL, DIMENSION(:,:), ALLOCATABLE :: begin_uvec, end_uvec REAL, DIMENSION(:,:,:), ALLOCATABLE :: lane_uvecs !======================================================================================================== WRITE (*, "(' Running EQ_classification_II.exe, from EQ_classification_II.f90....')") class_c3(0) = "INT" class_c3(1) = "CCB" class_c3(2) = "CTF" class_c3(3) = "CRB" class_c3(4) = "OSR" class_c3(5) = "OTF" class_c3(6) = "OCB" class_c3(7) = "SUB" N_over_mt(1) = CCB_pure_totalEvents N_over_mt(2) = CTF_pure_totalEvents N_over_mt(3) = CRB_pure_totalEvents N_over_mt(4) = OSR_pure_totalEvents N_over_mt(5) = OTF_pure_totalEvents N_over_mt(6) = OCB_pure_totalEvents N_over_mt(7) = SUB_pure_totalEvents L_km(1) = CCB_pure_totalLength_km L_km(2) = CTF_pure_totalLength_km L_km(3) = CRB_pure_totalLength_km L_km(4) = OSR_pure_totalLength_km L_km(5) = OTF_pure_totalLength_km L_km(6) = OCB_pure_totalLength_km L_km(7) = SUB_pure_totalLength_km V_mmpa(1) = CCB_pure_meanVelocity_mmpa V_mmpa(2) = CTF_pure_meanVelocity_mmpa V_mmpa(3) = CRB_pure_meanVelocity_mmpa V_mmpa(4) = OSR_pure_meanVelocity_mmpa V_mmpa(5) = OTF_pure_meanVelocity_mmpa V_mmpa(6) = OCB_pure_meanVelocity_mmpa V_mmpa(7) = SUB_pure_meanVelocity_mmpa h_km(1) = CCB_halfwidth_km h_km(2) = CTF_halfwidth_km h_km(3) = CRB_halfwidth_km h_km(4) = OSR_halfwidth_km h_km(5) = OTF_halfwidth_km h_km(6) = OCB_halfwidth_km ! no entry for SUB because it is asymmetrical SUB_landward_radians = SUB_landward_halfwidth_km / radius_km ! landward width of subduction lanes, in radians, from trench SUB_seaward_radians = SUB_seaward_halfwidth_km / radius_km ! seaward half-width of subduction lanes, in radians, from trench SUB_landward_sigma_km = 0.5 * (SUB_landward_halfwidth_km - SUB_peakSeismicity_km) ! sigmas for Gaussian approximation of B SUB_seaward_sigma_km = 0.5 * (SUB_seaward_halfwidth_km + SUB_peakSeismicity_km) class_threshhold_magnitude(1) = CCB_threshhold_magnitude class_threshhold_magnitude(2) = CTF_threshhold_magnitude class_threshhold_magnitude(3) = CRB_threshhold_magnitude class_threshhold_magnitude(4) = OSR_threshhold_magnitude class_threshhold_magnitude(5) = OTF_threshhold_magnitude class_threshhold_magnitude(6) = OCB_threshhold_magnitude class_threshhold_magnitude(7) = SUB_threshhold_magnitude !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! Read 1: PB2002_poles.dat (derived from PB2002_poles.xls by dropping headers, names, and areas) OPEN (UNIT = 1, FILE = 'PB2002_poles.dat', STATUS = 'OLD', IOSTAT = ios) IF (ios /= 0) THEN WRITE (*,"(' ERROR: input file PB2002_poles.dat could not be opened.')") CALL Pause() STOP END IF WRITE(*, "(' Reading PB2002_poles.dat...')") DO i = 1, nPlates READ (1, "(A2,F9.3,F10.3,F9.4)", IOSTAT = ios) ID(i), lat, lon, rotation_degpMa IF (ios /= 0) THEN WRITE (*,"(' ERROR: could not read Euler pole for plate', I3)") i CALL Traceback() STOP END IF CALL LonLat_2_Uvec (lon, lat, uvec) uvec(1:3) = uvec(1:3) * rotation_degpMa Euler(1:3, i) = uvec(1:3) END DO ! i = 1, nPlates CLOSE (1) ! read (2) PB2002_steps.dat ----------------------------------------------------------------- ! first reading is just to count steps OPEN (UNIT = 2, FILE = "PB2002_steps.dat", STATUS = "OLD", IOSTAT = ios) IF (ios /= 0) THEN WRITE (*,"(' ERROR: PB2002_steps.dat not available to read in.')") CALL Pause() END IF nSteps = 0 count_steps: DO READ (2, *, IOSTAT = ios) i ! the sequence number; might not be in order(?) IF (ios /= 0) EXIT count_steps nSteps = nSteps + 1 END DO count_steps CLOSE (2) ALLOCATE ( sequence_number(nSteps) ) ALLOCATE ( step_continuity_c1(nSteps) ) ALLOCATE ( c5(nSteps) ) ALLOCATE ( old_longitude(nSteps) ) ALLOCATE ( old_latitude(nSteps) ) ALLOCATE ( longitude(nSteps) ) ALLOCATE ( latitude(nSteps) ) ALLOCATE ( length_km(nSteps) ) ALLOCATE ( azimuth_integer(nSteps) ) ALLOCATE ( velocity_mmpa(nSteps) ) ALLOCATE ( velocity_azimuth_integer(nSteps) ) ALLOCATE ( divergence_mmpa(nSteps) ) ALLOCATE ( dextral_mmpa(nSteps) ) ALLOCATE ( elevation(nSteps) ) ALLOCATE ( age_Ma(nSteps) ) ALLOCATE ( class_continuity_c1(nSteps) ) ALLOCATE ( class(nSteps) ) ALLOCATE ( star_c1(nSteps) ) ALLOCATE ( begin_uvec(3, nSteps) ) ALLOCATE ( end_uvec (3, nSteps) ) ALLOCATE ( k_of(nSteps) ) ALLOCATE ( lane_uvecs(3, 5, nSteps) ) ALLOCATE ( subduction_azimuth_1(nSteps) ) ALLOCATE ( subduction_azimuth_2(nSteps) ) ALLOCATE ( Y_factor_of_step(nSteps) ) ALLOCATE ( distance_km_from_step(nSteps) ) ! used only to output distance from classes 1..7 ALLOCATE ( arc_km_from_step(nSteps) ) ! used only to output great-circle-arc-distance from INT event to nearest plate boundary !The following arrays added 2003.06 to support creation of "PB2002_XXX_pure.dat" files: ALLOCATE ( eq_count_over_threshhold(nSteps) ) ALLOCATE ( moment_sum_over_threshhold(nSteps) ) ! second reading is to record the contents: OPEN (UNIT = 2, FILE = "PB2002_steps.dat", STATUS = "OLD", IOSTAT = ios) DO i = 1, nSteps READ (2, 1001) sequence_number(i), step_continuity_c1(i), c5(i), & & old_longitude(i), old_latitude(i), longitude(i), latitude(i), & & length_km(i), azimuth_integer(i), & & velocity_mmpa(i), velocity_azimuth_integer(i), & & divergence_mmpa(i), dextral_mmpa(i), & & elevation(i), age_Ma(i), & & class_continuity_c1(i), class(i), star_c1(i) 1001 FORMAT (I4, 1X, A1, A5, & & 1X, F8.3, 1X, F7.3, 1X, F8.3, 1X, F7.3, & & 1X, F5.1, 1X, I3, & & 1X, F5.1, 1X, I3, & & 1X, F6.1, 1X, F6.1, & & 1X, I6, 1X, I3, & & 1X, A1, A3, A1) CALL LonLat_2_Uvec(old_longitude(i), old_latitude(i), uvec) begin_uvec(1:3, i) = uvec(1:3) CALL LonLat_2_Uvec(longitude(i), latitude(i), uvec) end_uvec(1:3, i) = uvec(1:3) !determine class k (= 1..7) for this step: k_of(i) = 0 look_up: DO n = 1, 7 IF (class(i) == class_c3(n)) THEN k_of(i) = n EXIT look_up END IF END DO look_up IF (k_of(i) == 0) THEN WRITE (*, "(' ERROR: Illegal class ',A,' for step ',I6)") class(i), i CALL Pause() STOP END IF IF (class(i) == "SUB") THEN ! determine corners of this lane !define lane (parallelogram of great circle arcs) in counterclockwise direction: azimuth_radians = azimuth_integer(i) * radians_per_degree IF (c5(i)(3:3) == '/') THEN uvec1(1:3) = begin_uvec(1:3, i) uvec2(1:3) = end_uvec(1:3, i) ELSE ! (c5(i)(3:3) == '\') uvec1(1:3) = end_uvec(1:3, i) uvec2(1:3) = begin_uvec(1:3, i) END IF !compute subduction_azimuth_1(i) at location uvec1: iLeftPlate = iPlate(c5(i)(1:2)) iRightPlate = iPlate(c5(i)(4:5)) IF ((iLeftPlate == 0).OR.(iRightPlate == 0)) THEN WRITE (*, "(' Error: Segment title ',A,' includes invalid plate identifier.')") c5(i) CALL Pause() STOP END IF !Euler vector for this step, converting "degrees per Ma" to "km per Ma" or "mm/a" on a unit sphere: tEuler(1:3) = (radius_km / 57.29577) * (Euler(1:3, iLeftPlate) - Euler(1:3, iRightPlate)) !velocity vector of left plate wrt right plate, in mm/a (but in Cartesian coordinates): CALL Cross (tEuler, uvec1, velocity) CALL Local_Theta(uvec1, tvec) ! returns S-pointing vector in tvec velocity_North = -Dot(velocity, tvec) CALL Local_Phi(uvec1, tvec) ! returns E-pointing vector in tvec velocity_East = Dot(velocity, tvec) IF (c5(i)(3:3) == '/') THEN ! left plate is overriding subduction_azimuth_1(i) = Pi + ATAN2(velocity_East, velocity_North) ELSE ! (c5(i)(3:3) == '\'); left plate is subducting subduction_azimuth_1(i) = ATAN2(velocity_East, velocity_North) END IF !compute subduction_azimuth_2(i) at location uvec2 [re-using tEuler]: !velocity vector of left plate wrt right plate, in mm/a (but in Cartesian coordinates): CALL Cross (tEuler, uvec2, velocity) CALL Local_Theta(uvec2, tvec) ! returns S-pointing vector in tvec velocity_North = -Dot(velocity, tvec) CALL Local_Phi(uvec2, tvec) ! returns E-pointing vector in tvec velocity_East = Dot(velocity, tvec) IF (c5(i)(3:3) == '/') THEN ! left plate is overriding subduction_azimuth_2(i) = Pi + ATAN2(velocity_East, velocity_North) ELSE ! (c5(i)(3:3) == '\'); left plate is subducting subduction_azimuth_2(i) = ATAN2(velocity_East, velocity_North) END IF !find corner points of this lane: CALL Turn_To (azimuth_radians = subduction_azimuth_1(i) + Pi, & & base_uvec = uvec1, & & far_radians = SUB_seaward_radians, & ! inputs & omega_uvec = omega_uvec, result_uvec = c1_uvec) lane_uvecs(1:3, 1, i) = c1_uvec(1:3) CALL Turn_To (azimuth_radians = subduction_azimuth_2(i) + Pi, & & base_uvec = uvec2, & & far_radians = SUB_seaward_radians, & ! inputs & omega_uvec = omega_uvec, result_uvec = c2_uvec) lane_uvecs(1:3, 2, i) = c2_uvec(1:3) CALL Turn_To (azimuth_radians = subduction_azimuth_2(i), & & base_uvec = uvec2, & & far_radians = SUB_landward_radians, & ! inputs & omega_uvec = omega_uvec, result_uvec = c3_uvec) lane_uvecs(1:3, 3, i) = c3_uvec(1:3) CALL Turn_To (azimuth_radians = subduction_azimuth_1(i), & & base_uvec = uvec1, & & far_radians = SUB_landward_radians, & ! inputs & omega_uvec = omega_uvec, result_uvec = c4_uvec) lane_uvecs(1:3, 4, i) = c4_uvec(1:3) lane_uvecs(1:3, 5, i) = lane_uvecs(1:3, 1, i) lane_width_km = length_km(i) * ABS(SIN(subduction_azimuth_1(i) - (azimuth_integer(i) * radians_per_degree))) lane_width_km = MAX(lane_width_km, 1.0) ! protect against singularity in case of extremely oblique "subduction" basis_length_km = lane_width_km ELSE basis_length_km = length_km(i) lane_uvecs(1:3, 1:5, i) = 0.0 ! just to be tidy; should never be used! END IF ! class(i) == "SUB", or not !Precompute Y_factor_of_step, to save time: integral = 0.0 s1 = 0.0 - 3.0 * alongStep_sigma_km s2 = basis_length_km + 3.0 * alongStep_sigma_km ds = (s2 - s1) / 100 DO n = 0, 100 s_km = s1 + (n / 100.0) * (s2 - s1) integral = integral + ds * ANORDF(s_km / alongStep_sigma_km) * ANORDF((basis_length_km - s_km) / alongStep_sigma_km) END DO Y_factor_of_step(i) = 1 / integral END DO ! i = 1, nSteps CLOSE (2) WRITE (*, "(' Finished reading and memorizing PB2002_steps.dat.')") ! Read (3): PB2002_orogens.dig (and store in memory) WRITE (*, "(' Begin reading and memorizing PB2002_orogens.dat...')") OPEN (UNIT = 3, FILE = 'PB2002_orogens.dig', STATUS = 'OLD', IOSTAT = ios) IF (ios /= 0) THEN WRITE (*,"(' ERROR: input file PB2002_orogens could not be opened.')") CALL Pause() END IF DO j = 1, nOrogens READ (3,"(A)", IOSTAT = ios) c27 IF (ios /= 0) THEN WRITE (*,"(' ERROR: could not read (all?) of PB2002_orogens.dig')") CALL Traceback() STOP END IF WRITE (*, "(' ',A)") TRIM(c27) points: DO i = 1, mostInOneOrogen + 1 READ (3, *, IOSTAT = ios) t_longitude, t_latitude IF (ios /= 0) THEN ! hit "*** end of line segment ***" nInEachOrogen(j) = i - 1 EXIT points END IF CALL LonLat_2_Uvec(t_longitude, t_latitude, uvec) orogen_uvecs(1:3, i, j) = uvec(1:3) END DO points END DO ! j = 1, norogens CLOSE (3) WRITE (*, "(' Finished reading and memorizing PB2002_orogens.dat.')") ! open the 16 .eqc files for the output that will soon follow ------------------------- 1100 WRITE (*, "(' Which type of seismic catalog will be processed in this run?')") WRITE (*, "(' (must always be a .eqc file, but formats vary for focal mechanism)')") WRITE (*, "(' (1) Harvard CMT')") WRITE (*, "(' (2) Pacheco and Sykes [1992]')") WRITE (*, "(' Enter integer to select: '\)") READ (*, *) catalog_ID IF ((catalog_ID < 1).OR.(catalog_ID > 2)) THEN WRITE (*, "(' ERROR: Illegal integer value; try again...')") GO TO 1100 END IF IF (catalog_ID == 1) THEN prefix = "CMT" ELSE IF (catalog_ID == 2) THEN prefix = "Pacheco" ELSE prefix = "other" END IF WRITE (*, "(' Enter name of seismic catalog (.eqc) file: '\)") READ (*, "(A)") catalog_file_name WRITE (*, "(' Opening 16 new .eqc files to be gradually filled with EQs...')") !class 1: XXXX_PB2002_CCB_pure.eqc and XXXX_PB2002_CCB_all.eqc Continental Convergent Boundary out_file_name = TRIM(prefix) // "_PB2002_CCB_pure.eqc" OPEN (UNIT = 11, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_CCB_all.eqc" OPEN (UNIT = 12, FILE = out_file_name) !class 2: XXXX_PB2002_CTF_pure.eqc and XXXX_PB2002_CTF_all.eqc Continental Transform Fault out_file_name = TRIM(prefix) // "_PB2002_CTF_pure.eqc" OPEN (UNIT = 21, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_CTF_all.eqc" OPEN (UNIT = 22, FILE = out_file_name) !class 3: XXXX_PB2002_CRB_pure.eqc and XXXX_PB2002_CRB_all.eqc Continental Rift Boundary out_file_name = TRIM(prefix) // "_PB2002_CRB_pure.eqc" OPEN (UNIT = 31, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_CRB_all.eqc" OPEN (UNIT = 32, FILE = out_file_name) !class 4: XXXX_PB2002_OSR_pure.eqc and XXXX_PB2002_OSR_all.eqc Oceanic Spreading Ridge out_file_name = TRIM(prefix) // "_PB2002_OSR_pure.eqc" OPEN (UNIT = 41, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_OSR_all.eqc" OPEN (UNIT = 42, FILE = out_file_name) !class 5: XXXX_PB2002_OTF_pure.eqc and XXXX_PB2002_OTF_all.eqc Oceanic Transform Fault out_file_name = TRIM(prefix) // "_PB2002_OTF_pure.eqc" OPEN (UNIT = 51, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_OTF_all.eqc" OPEN (UNIT = 52, FILE = out_file_name) !class 6: XXXX_PB2002_OCB_pure.eqc and XXXX_PB2002_OCB_all.eqc Oceanic Convergent Boundary out_file_name = TRIM(prefix) // "_PB2002_OCB_pure.eqc" OPEN (UNIT = 61, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_OCB_all.eqc" OPEN (UNIT = 62, FILE = out_file_name) !class 7: XXXX_PB2002_SUB_pure.eqc and XXXX_PB2002_SUB_all.eqc SUBduction zone out_file_name = TRIM(prefix) // "_PB2002_SUB_pure.eqc" OPEN (UNIT = 71, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_SUB_all.eqc" OPEN (UNIT = 72, FILE = out_file_name) !class 0 (or "10" for I/O purposes): XXXX_PB2002_INT_pure.eqc and XXXX_PB2002_INT_all.eqc INTraplate (plate-INTerior) out_file_name = TRIM(prefix) // "_PB2002_INT_pure.eqc" OPEN (UNIT = 101, FILE = out_file_name) out_file_name = TRIM(prefix) // "_PB2002_INT_all.eqc" OPEN (UNIT = 102, FILE = out_file_name) !common format for subcatalogs: 3002 FORMAT (A, & & I5,'.',A2,'.',A2, 1X, & & A2,':',A2,':',A2,'.',A1, 1X, & & F8.3, 1X, F7.3, 1X, & & I3, F6.2, & & A21, & ! up to here, a normal .eqc format (with or w/o FPS) [ WRITE (...)..., TRIM(appended_data)! ] & 1X,A1,A3,A1,1X,I5, & ! additional information: " *SUB* 4392" & 7(1X,I3), & ! additional information: " 1 2 3 4 5 6 79" & F8.1) ! additional information: distance_km from most relevant step ! read (4) XXXX_shallow.eqc and process events (don't store them) ------------------------- count_all = 0 ! each of the (0:7) values, for "all" subcatalogs count_pure = 0 ! each of the (0:7) values, for "pure" subcatalogs eq_count_over_threshhold = 0 ! initialize count for each plate boundary step moment_sum_over_threshhold = 0 ! initialize sum for each plate boundary step WRITE (*, "(' Reading and classifying ', A, ' catalog...')") TRIM(prefix) iEvent = 0 ! just for displaying progress OPEN (UNIT = 4, FILE = catalog_file_name, STATUS = "OLD", IOSTAT = ios, PAD = "YES") ! PAD needed to read appended_data IF (ios /= 0) THEN WRITE (*,"(' ERROR: ', A, ' not available to read in.')") TRIM(catalog_file_name) CALL Pause() END IF WRITE (*, *) CALL DATE_AND_TIME (date, clock_time, zone, datetimenumber) IF (Monte_Carlo_method) THEN CALL RNOPT(1) ! Select type of random number generator: 1 = congruential, multiplier 16807, no shuffling [default]. iseed = (datetimenumber(1) - 2001) * 31557600 + & ! not precise; ignores leap years (datetimenumber(2) - 1) * 2629800 + & ! not precise; all months are not really the same length! (datetimenumber(3) - 1) * 86400 + & datetimenumber(5) * 3600 + & datetimenumber(6) * 60 + & datetimenumber(7) iseed = MOD(iseed, 2147483646) CALL RNSET(iseed) ! Seed the random number generator; iseed must be in the range (0, 2147483646) ! which is equivalent to the number of seconds in a span of 68 years or less. END IF next_event: DO READ (4, 3001, IOSTAT = ios) catalog_name, & & eq_year, eq_month, eq_day, & & eq_hour, eq_minute, eq_second, eq_tenths, & & eq_Elon, eq_Nlat, & & eq_depth_int, eq_mag, & & appended_data 3001 FORMAT ( A9, & & I5,'.',A2,'.',A2, 1X, & ! using I5 for negative years (B.C.) & A2,':',A2,':',A2,'.',A1, 1X, & & F8.3, 1X, F7.3, 1X, & & I3, F6.2, & & A ) IF (ios /= 0) EXIT next_event iEvent = iEvent + 1 WRITE (*, "('+ processing event ',I10)") iEvent ! ===== heart of this program ================================================ !test whether earthquake is in any orogen: CALL LonLat_2_Uvec(eq_Elon, eq_Nlat, eq_uvec) pure_epicenter = .TRUE. ! initialization, before testing check_orogens: DO j = 1, nOrogens angle_sum = 0.0 ! initialize sum of angles subtended by orogen steps, as seen from test point: DO i = 2, nInEachOrogen(j) uvec1(1:3) = orogen_uvecs(1:3, i-1, j) uvec2(1:3) = orogen_uvecs(1:3, i , j) t1 = Relative_Compass(from_uvec = eq_uvec, to_uvec = uvec1) t2 = Relative_Compass(from_uvec = eq_uvec, to_uvec = uvec2) IF ((t2 - t1) > Pi) t2 = t2 - Two_Pi IF ((t2 - t1) < -Pi) t2 = t2 + Two_Pi angle_sum = angle_sum + t2 - t1 END DO ! i = 2, nInEachOrogen(j) inside = ((angle_sum < -6.0).AND.(angle_sum > -6.6)) ! inside a counterclockwise circuit !Note: Generalizing formula to allow for being inside a clockwise circuit will unfortunately ! cast virtual images of each orogen on the far side of the Earth! IF (inside) THEN pure_epicenter = .FALSE. EXIT check_orogens END IF END DO check_orogens ! j = 1, nOrogens IF (pure_epicenter) THEN pure_epicenter_c1 = ' ' ELSE ! in some orogen pure_epicenter_c1 = '*' END IF highest_P_prime = 0.0 ! initialization; if still true after loop, then EQ is an INT best_i = 0 ! will remember i index of step associated with highest_P_prime best_k = 0 ! will remember k index of class of the step associated with highest_P_prime, if any; ! if no association found, best_k remains 0, which is a signal for an INT EQ. highest_P_prime_in_class = 0.0 ! for all 7 classes best_i_in_class = 0 ! for all 7 classes sum_P_prime_in_class = 0.0 ! for all 7 classes sum_P_prime_all_classes = 0.0 distance_km_from_step = Pi * radius_km ! whole array (1:nSteps) arc_km_from_step = Pi * radius_km ! whole array (1:nSteps) DO i = 1, nSteps k = k_of(i) !------------------------------------------------------------------------------ ! A factor: relative number (or rate) of EQs (over m_t) produced by this step: A = N_over_mt(k) * (length_km(i) / L_km(k)) * (velocity_mmpa(i) / V_mmpa(k)) !------------------------------------------------------------------------------ !distances to end points: uvec1(1:3) = begin_uvec(1:3, i) to_uvec1_radians = Arc(eq_uvec, uvec1) uvec2(1:3) = end_uvec(1:3, i) to_uvec2_radians = Arc(eq_uvec, uvec2) !great-circle-arc distance computed ONLY to output for earthquakes that end up as INT's: arc_km_from_step(i) = radius_km * MIN(to_uvec1_radians, to_uvec2_radians) !Note that this may be reduced below to distance_km, if within end-points. IF (k < 7) THEN ! step is not a SUB; use normal distance/offset logic: !distance and offset measured via perpendicular great circle: CALL Cross(uvec1, uvec2, tvec) CALL Make_Uvec(tvec, pole_uvec) ! pole of the great-circle for this step offside_radians = ABS(Arc(pole_uvec, eq_uvec) - Pi_over_2) distance_km = radius_km * offside_radians ! always positive offset_km = distance_km ! no distinction for classes other than SUB !s_km measured along length of step (using longitudes relative to pole of step's great circle): t1 = Relative_Compass(from_uvec = pole_uvec, to_uvec = uvec1) t2 = Relative_Compass(from_uvec = pole_uvec, to_uvec = uvec2) !note: normally, t2 is slightly less than t1 IF (t2 > t1) t2 = t2 - Two_Pi angle = Relative_Compass(from_uvec = pole_uvec, to_uvec = eq_uvec) ! to the earthquake !check that angle is on the same cycle as t1, t2: midpoint_compass = (t1 + t2) / 2 IF ((angle - midpoint_compass) > Pi) angle = angle - Two_Pi IF ((midpoint_compass - angle) > Pi) angle = angle + Two_Pi s_radians = t1 - angle s_km = s_radians * radius_km !-------------------------------------------------------------------------------------------------------- ! X factor = cross-strike component of spatial PDF B: IF (offset_km > h_km(k)) THEN X = 0.0 ELSE X = (1.0 / 0.95) *(0.797885 / h_km(k)) * EXP(-2 * (offset_km / h_km(k))**2) END IF !-------------------------------------------------------------------------------------------------------- !------------------------------------------------------------------------------------------------------- ! Y factor causes PDF to fall off to ~0.5 as ends of step are approached (and even more beyond the ends) IF ((s_km > (-3.0 * alongStep_sigma_km)).AND.(s_km < (length_km(i) + 3.0 * alongStep_sigma_km))) THEN ! use complex formula: Y = Y_factor_of_step(i) * ANORDF(s_km / alongStep_sigma_km) * ANORDF((length_km(i) - s_km) / alongStep_sigma_km) distance_km_from_step(i) = distance_km ! save for possible output, if this step is selected ELSE ! too far away; don't risk numerical problems within ANORDF: Y = 0.0 END IF !------------------------------------------------------------------------------------------------------- IF ((s_km > 0.0).AND.(s_km < length_km(i))) THEN ! use perpendicular distance as shortest great-circle-arc: arc_km_from_step(i) = distance_km !Notes: Used only for output in the case that this earthquake ends up as an INT. ! Also, arc_km_from_step(i) was previously set to the lesser of the distance to the 2 endpoints of this step. END IF ELSE ! this is a SUB (k = 7) step; special offset logic is used, and - distances/offsets mean seaward of the trench! proximal = .TRUE. ! unless (usually) negated below: DO n = 1, 4 ! sides uvec1(1:3) = lane_uvecs(1:3, n, i) uvec2(1:3) = lane_uvecs(1:3, n+1, i) CALL Cross (uvec1, uvec2, tvec) ! direction toward pole is direction into the lane CALL Make_Uvec(tvec, inward_uvec) scalar_product = Dot(eq_uvec, inward_uvec) dot_side(n) = scalar_product proximal = proximal .AND. (scalar_product > -0.01) ! 63.7 km tolerance END DO ! n = 1, 4 sides ! Note: EQ is inside the lane if all 4 values in dot_side(1:4) are postive; ! these values are sines of angles from the sides, measured inwards. IF (proximal) THEN ! compute + or - distance/offset from trench, in km (even if slightly to one side of the lane): IF (c5(i)(3:3) == '/') THEN uvec1(1:3) = begin_uvec(1:3, i) uvec2(1:3) = end_uvec(1:3, i) ELSE ! (c5(i)(3:3) == '\') uvec1(1:3) = end_uvec(1:3, i) uvec2(1:3) = begin_uvec(1:3, i) END IF fraction_toward_uvec1 = dot_side(2) / (dot_side(2) + dot_side(4)) ! where all dot's are positive if inside; ! note that denominator is positive even if EQ (slightly) outside lane. fraction_toward_uvec1 = MAX(0.0, MIN(1.0, fraction_toward_uvec1)) ! This kludge is necessary to prevent pathalogical ! behavior when SUB steps are very short and oblique. tvec(1:3) = fraction_toward_uvec1 * uvec1(1:3) + & & (1.0 - fraction_toward_uvec1) * uvec2(1:3) CALL Make_Uvec(tvec, trench_uvec) ! at same relative left-right position in this lane distance_km = radius_km * Arc(eq_uvec, trench_uvec) ! always positive; must apply sign now: from_trench_azimuth_radians = Relative_Compass (from_uvec = trench_uvec, to_uvec = eq_uvec) IF (COS(from_trench_azimuth_radians - subduction_azimuth_1(i)) < 0.0) THEN ! eq_is on seaward side of trench; convert distance to negative: distance_km = -distance_km END IF !Note that "distance" is positive on landward side of trench, but negative on seaward side. distance_km_from_step(i) = distance_km ! save for possible output offset_km = distance_km - SUB_peakSeismicity_km ! preserving possibility of negative values; just shifting origin !-------------------------------------------------------------------------------------------------------- ! X factor = along-lane component of spatial PDF function B: IF (offset_km >= 0.0) THEN ! landward side of seismicity peak: IF (distance_km <= SUB_landward_halfwidth_km) THEN X = (1.0 / 0.95) * & & (2 * SUB_landward_sigma_km / (SUB_landward_sigma_km + SUB_seaward_sigma_km)) * & & (0.797885 / (2.0 * SUB_landward_sigma_km)) * & & EXP(-0.5 * (offset_km / SUB_landward_sigma_km)**2) ELSE X = 0.0 END IF ELSE ! seaward side of seismicity peak (but may not be seaward of the trench!) IF (distance_km >= -SUB_seaward_halfwidth_km) THEN X = (1.0 / 0.95) * & & (2 * SUB_seaward_sigma_km / (SUB_landward_sigma_km + SUB_seaward_sigma_km)) * & & (0.797885 / (2.0 * SUB_seaward_sigma_km )) * & & EXP(-0.5 * (offset_km / SUB_seaward_sigma_km)**2) ELSE X = 0.0 END IF END IF ! which side of seismicity peak? !-------------------------------------------------------------------------------------------------------- !-------------------------------------------------------------------------------------------------------- ! Y factor = cross-lane (orthogonal to X factor) component of spatial PDF function B: ! To evaluate Y(s_km), note that length_km(i) is not the basis length that we want to use, ! but rather the lane width: lane_width_km = radius_km * (dot_side(2) + dot_side(4)) lane_width_km = MAX(lane_width_km, 1.0) ! protect against singularity in case of extremely oblique "subduction" s_km = radius_km * dot_side(4) ! distance (if +) into lane, starting on the uvec1 end IF ((s_km > (-3.0 * alongStep_sigma_km)).AND.(s_km < (lane_width_km + 3.0 * alongStep_sigma_km))) THEN ! use complex formula: Y = Y_factor_of_step(i) * ANORDF(s_km / alongStep_sigma_km) * ANORDF((lane_width_km - s_km) / alongStep_sigma_km) ELSE ! too far away; don't risk numerical problems within ANORDF: Y = 0.0 END IF !-------------------------------------------------------------------------------------------------------- ELSE ! not proximal; punt X = 0.0 Y = 0.0 !Note: distance_km_from_step(i) was initialized as Pi * radius_km END IF END IF ! "normal" offset/distance logic (k = 1-6), or special logic for SUB steps (k = 7) B = X * Y ! spatial PDF is a product of cross-trace function and along-trace function IF ((A * B) > 0.0) THEN ! continue investigating this step; P_prime should be positive !------------------------------------------------------------------------------------ !Compute SUM (j=1,5) {C * D * E} for this step !extract depth reliability and mechanism classification, depending on catalog: IF (catalog_ID == 1) THEN ! CMT, has orientations of principal strain axes eq_depth_known = (eq_depth_int /= 33) READ (appended_data, "(3(1X,I2,1X,I3))", IOSTAT = ios) e1_plunge, e1_azimuth, e2_plunge, e2_azimuth, e3_plunge, e3_azimuth IF (ios == 0) THEN mechanism_known = .TRUE. actual_TpaPpa_degrees(1) = e3_plunge ! plunge of T axis, in degrees actual_TpaPpa_degrees(2) = e3_azimuth ! azimuth of T axix, in degrees actual_TpaPpa_degrees(3) = e1_plunge ! plunge of P axis, in degrees actual_TpaPpa_degrees(4) = e1_azimuth ! azimuth of P axis, in degrees ELSE mechanism_known = .FALSE. WRITE (*, "(' Bad mechanism found in CMT-format file: ',A)") TRIM(appended_data) CALL Pause() STOP END IF ELSE IF (catalog_ID == 2) THEN ! Pacheco and Sykes [1992], has (some) type indicators eq_depth_known = (eq_depth_int /= 0) c3 = appended_data ! left-most 3 bytes, such as: " n", " u", " ts" IF (INDEX(c3, 'n') > 0) THEN !this is a NORMAL faulting event mechanism_known = .TRUE. unknown = .FALSE.; normal = .TRUE.; strikeslip = .FALSE.; thrust = .FALSE. ELSE IF ((INDEX(c3, 't') > 0).OR.(INDEX(c3, 'r') > 0).OR.(INDEX(c3, 'c') > 0)) THEN !this is a THRUST or REVERSE or COMPRESSIONAL faulting event mechanism_known = .TRUE. unknown = .FALSE.; normal = .FALSE.; strikeslip = .FALSE.; thrust = .TRUE. ELSE IF (INDEX(c3, 's') > 0) THEN !this is a STRIKE-SLIP faulting event mechanism_known = .TRUE. unknown = .FALSE.; normal = .FALSE.; strikeslip = .TRUE.; thrust = .FALSE. ELSE mechanism_known = .FALSE. unknown = .TRUE.; normal = .FALSE.; strikeslip = .FALSE.; thrust = .FALSE. END IF ELSE WRITE (*, "(' Rules not known for interpreting earthquake type in this catalog.')") CALL Traceback() END IF ! CMT, Pacheco and Sykes [1992], or other type of catalog sum_CDE = 0.0 ! initializing DO j = 1, 5 ! model earthquakes for this step (to skip unneeded ones, set C = 0.0) ! Assignment of C, the relative probability of this model EQ: SELECT CASE (k) CASE (1, 6) ! CCB and OCB: closing_angle_radians = ATAN2(-divergence_mmpa(i), dextral_mmpa(i)) ! syntax: ATAN2(y, x) !which will be close to +Pi/2 if convergence_mmpa >> ABS(dextral_mmpa) SELECT CASE (j) CASE (1) ! oblique thrust on fault dipping to left C = 0.333 * (1.0 - ABS(COS(closing_angle_radians))) CASE (2) ! oblique thrust on fault dipping to right C = 0.333 * (1.0 - ABS(COS(closing_angle_radians))) CASE (3) ! pure thrust with shortening perpendicular to plate boundary: C = 0.333 * (1.0 - ABS(COS(closing_angle_radians))) !Note: Distinction between the j=1 and j=2 models is academic for near-othogonal convergence. CASE (4) ! pure strike-slip on plane striking parallel to plate boundary: C = ABS(COS(closing_angle_radians)) CASE (5) ! (not used) C = 0.0 END SELECT ! on j CASE (2, 5) ! CTF and OTF: SELECT CASE (j) CASE (1) ! strike-slip on vertical plane of plate boundary: C = 0.830 ! = 1.00 - C_22 - C_23 CASE (2) ! normal on plane striking parallel to plate boundary: C = 0.085 ! limited, due to definition that CTF, OTF boundaries are within 20 deg. of plate velocity CASE (3) ! thrust on plane striking parallel to plate boundary: C = 0.085 ! limited, due to definition that CTF, OTF boundaries are within 20 deg. of plate velocity CASE (4) ! (not used) C = 0.0 CASE (5) ! (not used) C = 0.0 END SELECT ! on j CASE (3, 4) ! CRB and OSR: opening_angle_radians = ATAN2(divergence_mmpa(i), dextral_mmpa(i)) ! syntax: ATAN2(y, x) !which will be close to +Pi/2 if divergence_mmpa >> ABS(dextral_mmpa) SELECT CASE (j) CASE (1) ! oblique normal faulting, on plane to left of trace C = 0.333 * (1.0 - ABS(COS(opening_angle_radians))) CASE (2) ! oblique normal faulting, on plane to right of trace C = 0.333 * (1.0 - ABS(COS(opening_angle_radians))) !Note: Distinction between the j=1 and j=2 models is academic for near-othogonal spreading. CASE (3) ! pure normal faulting C = 0.333 * (1.0 - ABS(COS(opening_angle_radians))) CASE (4) ! pure strike-slip C = ABS(COS(opening_angle_radians)) CASE (5) ! (not used) C = 0.0 END SELECT ! on j CASE (7) ! SUB: SELECT CASE (j) CASE (1) ! oblique slip on main inter-plate thrust fault: C = 1689./6274. ! = 1.0 - C_72 - C_73 - C_74 CASE (2) ! pure dip-slip on main inter-plate thrust fault: C = 1689./6274. ! = 1.0 - C_72 - C_73 - C_74 CASE (3) ! strike-slip parallel to arc: C = 690./6274. ! based on CMT_PB2002_pure_SUB_breakdown.xls (from old EQ_classification.f90) CASE (4) ! down-dip extension due to bending and/or stress-guide: C = 1103./6274. ! based on CMT_PB2002_pure_SUB_breakdown.xls (from old EQ_classification.f90) CASE (5) ! down-dip compression due to bending and/or stress-guide: C = 1103./6274. ! arbitrarily assumed = to C_74, since hard to distinguish from C_71 and C_72 END SELECT ! on j END SELECT ! on k; END of C (relative probabilities of models) section IF (C > 0.0) THEN ! this model has a chance of happening ! Compute D, the depth PDF of this model EQ evaluated at the actual EQ depth: IF (eq_depth_known) THEN SELECT CASE (k) CASE (1:6) ! all EXCEPT SUB are the same, regardless of model (j): argument = (class123456_cutoff_depth_km - eq_depth_int) / earthquake_depth_sigma_km IF (argument > -3.0) THEN ! safe to call ANORDF: D = (1. / class123456_cutoff_depth_km) * ANORDF( argument ) ELSE ! ANORDF might underflow D = 0.0 END IF CASE (7) ! SUB is different quadratic = (slab_depth_under_arc_km - trench_depth_km - (slope_at_trench*arc_distance_km)) / arc_distance_km**2 distance_at_peak_km = -slope_at_trench / (2.0 * quadratic) minimum_depth_km = trench_depth_km + distance_at_peak_km * slope_at_trench + quadratic * distance_at_peak_km**2 IF (distance_km > distance_at_peak_km) THEN interplate_thrust_depth_km = trench_depth_km + distance_km * slope_at_trench + quadratic * distance_km**2 ELSE interplate_thrust_depth_km = minimum_depth_km END IF interplate_thrust_depth_sigma_km = interplate_thrust_depth_sigma_fraction * interplate_thrust_depth_km !Note: Use SUB_quadratic_profile.xls to experiment with these functions and parameters. SELECT CASE (j) CASE (1:2) ! main inter-plate thrust fault D = (1.0 / SQRT( Two_Pi * (earthquake_depth_sigma_km**2 + interplate_thrust_depth_sigma_km**2) )) * & & EXP( -(eq_depth_int - interplate_thrust_depth_km)**2 / & & (2 * (earthquake_depth_sigma_km**2 + interplate_thrust_depth_sigma_km**2)) ) CASE (3) ! strike-slip parallel to arc (same as classes 1-6 above) argument = (class123456_cutoff_depth_km - eq_depth_int) / earthquake_depth_sigma_km IF (argument > -3.0) THEN ! safe to call ANORDF: D = (1. / class123456_cutoff_depth_km) * ANORDF( argument ) ELSE ! ANORDF might underflow D = 0.0 END IF CASE (4:5) ! down-dip extension or compression due to bending and/or stress-guid argument = (eq_depth_int - interplate_thrust_depth_km) / earthquake_depth_sigma_km IF (argument > -3.0) THEN ! safe to call ANORDF: D = (1. / 60.0) * ANORDF( argument ) !where 60 km is the typical thickness of the slab stress guide ELSE ! ANORDF might underflow D = 0.0 END IF END SELECT ! on j END SELECT ! on k ELSE ! EQ depth is NOT known: D = 1./70. ! in units of /km END IF ! end of D (depth PDF) section IF (D > 0.0) THEN ! this EQ depth could match this model ! Compute E, the angular PDF of this model EQ evaluated at the actual EQ mechanism orientation: IF (mechanism_known) THEN ! use it to evaluate E: SELECT CASE (catalog_ID) CASE (1) ! CMT: SELECT CASE(k) ! boundary class CASE (1, 6) ! CCB or OCB: SELECT CASE (j) CASE (1) ! oblique thrust dipping 20 degrees to left of trace: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = 20.0 dip_is_to_right = .FALSE. relative_velocity_azimuth_degrees = velocity_azimuth_integer(i) relative_velocity_is_divergent = .FALSE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output model_TpaPpa_degrees(1) = e3_plunge model_TpaPpa_degrees(2) = e3_azimuth model_TpaPpa_degrees(3) = e1_plunge model_TpaPpa_degrees(4) = e1_azimuth CASE (2) ! oblique thrust dipping 20 degrees to right of trace: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = 20.0 dip_is_to_right = .TRUE. relative_velocity_azimuth_degrees = velocity_azimuth_integer(i) relative_velocity_is_divergent = .FALSE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output model_TpaPpa_degrees(1) = e3_plunge model_TpaPpa_degrees(2) = e3_azimuth model_TpaPpa_degrees(3) = e1_plunge model_TpaPpa_degrees(4) = e1_azimuth CASE (3) ! pure thrust with shortening perpendicular to plate boundary: model_TpaPpa_degrees(1) = 90 model_TpaPpa_degrees(2) = 0 model_TpaPpa_degrees(3) = 0 model_TpaPpa_degrees(4) = azimuth_integer(i) + 90 CASE (4) ! pure strike-slip on plane striking parallel to plate boundary: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(3) = 0 IF (dextral_mmpa(i) > 0.0) THEN ! right-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 135 model_TpaPpa_degrees(4) = azimuth_integer(i) + 45 ELSE ! left-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 45 model_TpaPpa_degrees(4) = azimuth_integer(i) + 135 END IF END SELECT ! on j CASE (2, 5) ! CTF or OTF: SELECT CASE (j) CASE (1) ! strike-slip on vertical plane of plate boundary: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(3) = 0 IF (dextral_mmpa(i) > 0.0) THEN ! right-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 135 model_TpaPpa_degrees(4) = azimuth_integer(i) + 45 ELSE ! left-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 45 model_TpaPpa_degrees(4) = azimuth_integer(i) + 135 END IF CASE (2) ! normal on plane striking parallel to plate boundary: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(2) = azimuth_integer(i) + 90 model_TpaPpa_degrees(3) = 90 model_TpaPpa_degrees(4) = 0 CASE (3) ! thrust on plane striking parallel to plate boundary: model_TpaPpa_degrees(1) = 90 model_TpaPpa_degrees(2) = 0 model_TpaPpa_degrees(3) = 0 model_TpaPpa_degrees(4) = azimuth_integer(i) + 90 END SELECT ! on j CASE (3, 4) ! CRB or OSR: SELECT CASE (j) CASE (1) ! oblique normal faulting, with dip 55 degrees to left of trace: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = 55.0 dip_is_to_right = .FALSE. relative_velocity_azimuth_degrees = velocity_azimuth_integer(i) relative_velocity_is_divergent = .TRUE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output model_TpaPpa_degrees(1) = e3_plunge model_TpaPpa_degrees(2) = e3_azimuth model_TpaPpa_degrees(3) = e1_plunge model_TpaPpa_degrees(4) = e1_azimuth CASE (2) ! oblique normal faulting, with dip 55 degrees to right of trace: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = 55.0 dip_is_to_right = .TRUE. relative_velocity_azimuth_degrees = velocity_azimuth_integer(i) relative_velocity_is_divergent = .TRUE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output model_TpaPpa_degrees(1) = e3_plunge model_TpaPpa_degrees(2) = e3_azimuth model_TpaPpa_degrees(3) = e1_plunge model_TpaPpa_degrees(4) = e1_azimuth CASE (3) ! pure normal faulting, with extension perpendicular to plate boundary: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(2) = azimuth_integer(i) + 90 model_TpaPpa_degrees(3) = 90 model_TpaPpa_degrees(4) = 0 CASE (4) ! partitioned strike-slip on plane striking parallel to plate boundary: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(3) = 0 IF (dextral_mmpa(i) > 0.0) THEN ! right-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 135 model_TpaPpa_degrees(4) = azimuth_integer(i) + 45 ELSE ! left-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 45 model_TpaPpa_degrees(4) = azimuth_integer(i) + 135 END IF END SELECT ! on j CASE (7) ! SUB: quadratic = (slab_depth_under_arc_km - trench_depth_km - (slope_at_trench*arc_distance_km)) / arc_distance_km**2 distance_at_peak_km = -slope_at_trench / (2.0 * quadratic) IF (distance_km > distance_at_peak_km) THEN velocity_dip_radians = ATAN(slope_at_trench + 2.0 * quadratic * distance_km) ELSE velocity_dip_radians = 0.0 END IF velocity_dip_degrees = NINT(velocity_dip_radians * degrees_per_radian) IF ((velocity_dip_degrees < 0).OR.(velocity_dip_degrees >= 90)) THEN WRITE (*, "(' Bad velocity_dip_degrees: ', I6)") velocity_dip_degrees CALL Traceback() STOP END IF !velocity_dip is measured along the velocity vector (like the quadratic profile); !crossStrike_dip is steeper in the case of oblique subduction, equal for orthogonal subduction: crossStrike_dip_radians = ATAN(TAN(velocity_dip_radians) / & & ABS(SIN((velocity_azimuth_integer(i)-azimuth_integer(i))*radians_per_degree))) crossStrike_dip_degrees = NINT(crossStrike_dip_radians * degrees_per_radian) IF ((crossStrike_dip_degrees < 0).OR.(crossStrike_dip_degrees > 90)) THEN WRITE (*, "(' Bad crossStrike_dip_degrees: ', I6)") crossStrike_dip_degrees CALL Traceback() STOP END IF crossStrike_dip_degrees = MIN(crossStrike_dip_degrees, 89) IF (c5(i)(3:3) == '/') THEN ! velocity_azimuth_integer(i) refers to the LEFT plate, going along the boundary: dip_is_to_right = .FALSE. slab_velocity_azimuth_integer = velocity_azimuth_integer(i) + 180 slab_downdip_azimuth_integer = azimuth_integer(i) - 90 ELSE ! c5(3:3) == '\'; left plate IS the slab: dip_is_to_right = .TRUE. slab_velocity_azimuth_integer = velocity_azimuth_integer(i) slab_downdip_azimuth_integer = azimuth_integer(i) + 90 END IF SELECT CASE (j) CASE (1) ! oblique slip on main inter-plate thrust fault: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = MAX(crossStrike_dip_degrees, 5) ! in case EQ is mislocated in outer rise relative_velocity_azimuth_degrees = velocity_azimuth_integer(i) relative_velocity_is_divergent = .FALSE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output T_plunge_degrees = e3_plunge T_azimuth_degrees = e3_azimuth P_plunge_degrees = e1_plunge P_azimuth_degrees = e1_azimuth IF (T_plunge_degrees > 90) THEN T_plunge_degrees = 180 - T_plunge_degrees T_azimuth_degrees = T_azimuth_degrees + 180 P_plunge_degrees = -P_plunge_degrees P_azimuth_degrees = P_azimuth_degrees - 180 END IF IF ((T_plunge_degrees < 0).OR.(T_plunge_degrees > 90).OR. & (P_plunge_degrees < 0).OR.(P_plunge_degrees > 90)) THEN WRITE (*, "(' Bad plunge')") CALL Traceback() STOP END IF !only truncate to INTEGER*2 (losing sign) *after* testing! model_TpaPpa_degrees(1) = T_plunge_degrees model_TpaPpa_degrees(2) = T_azimuth_degrees model_TpaPpa_degrees(3) = P_plunge_degrees model_TpaPpa_degrees(4) = P_azimuth_degrees CASE (2) ! pure thrust on main inter-plate thrust fault: fault_strike_degrees = azimuth_integer(i) fault_dip_degrees = MAX(crossStrike_dip_degrees, 5) ! in case EQ is mislocated in outer rise relative_velocity_azimuth_degrees = fault_strike_degrees + 90 relative_velocity_is_divergent = .FALSE. CALL Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth, e1_plunge, & & e2_azimuth, e2_plunge, & & e3_azimuth, e3_plunge) ! output T_plunge_degrees = e3_plunge T_azimuth_degrees = e3_azimuth P_plunge_degrees = e1_plunge P_azimuth_degrees = e1_azimuth IF (T_plunge_degrees > 90) THEN T_plunge_degrees = 180 - T_plunge_degrees T_azimuth_degrees = T_azimuth_degrees + 180 P_plunge_degrees = -P_plunge_degrees P_azimuth_degrees = P_azimuth_degrees - 180 END IF IF ((T_plunge_degrees < 0).OR.(T_plunge_degrees > 90).OR. & (P_plunge_degrees < 0).OR.(P_plunge_degrees > 90)) THEN WRITE (*, "(' Bad plunge')") CALL Traceback() STOP END IF !only truncate to INTEGER*2 (losing sign) *after* testing! model_TpaPpa_degrees(1) = T_plunge_degrees model_TpaPpa_degrees(2) = T_azimuth_degrees model_TpaPpa_degrees(3) = P_plunge_degrees model_TpaPpa_degrees(4) = P_azimuth_degrees CASE (3) ! strike-slip parallel to arc: model_TpaPpa_degrees(1) = 0 model_TpaPpa_degrees(3) = 0 IF (dextral_mmpa(i) > 0.0) THEN ! right-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 135 model_TpaPpa_degrees(4) = azimuth_integer(i) + 45 ELSE ! left-lateral: model_TpaPpa_degrees(2) = azimuth_integer(i) + 45 model_TpaPpa_degrees(4) = azimuth_integer(i) + 135 END IF CASE (4) ! down-dip extension due to bending and/or stress-guide: T_plunge_degrees = crossstrike_dip_degrees T_azimuth_degrees = slab_downdip_azimuth_integer P_plunge_degrees = 90 - crossstrike_dip_degrees P_azimuth_degrees = slab_downdip_azimuth_integer + 180 IF ((T_plunge_degrees < 0).OR.(T_plunge_degrees > 90).OR. & (P_plunge_degrees < 0).OR.(P_plunge_degrees > 90)) THEN WRITE (*, "(' Bad plunge')") CALL Traceback() STOP END IF !only truncate to INTEGER*2 (losing sign) *after* testing! model_TpaPpa_degrees(1) = T_plunge_degrees model_TpaPpa_degrees(2) = T_azimuth_degrees model_TpaPpa_degrees(3) = P_plunge_degrees model_TpaPpa_degrees(4) = P_azimuth_degrees CASE (5) ! down-dip compression due to bending and/or stress-guide: T_plunge_degrees = 90 - crossstrike_dip_degrees T_azimuth_degrees = slab_downdip_azimuth_integer + 180 P_plunge_degrees = crossstrike_dip_degrees P_azimuth_degrees = slab_downdip_azimuth_integer IF ((T_plunge_degrees < 0).OR.(T_plunge_degrees > 90).OR. & (P_plunge_degrees < 0).OR.(P_plunge_degrees > 90)) THEN WRITE (*, "(' Bad plunge')") CALL Traceback() STOP END IF !only truncate to INTEGER*2 (losing sign) *after* testing! model_TpaPpa_degrees(1) = T_plunge_degrees model_TpaPpa_degrees(2) = T_azimuth_degrees model_TpaPpa_degrees(3) = P_plunge_degrees model_TpaPpa_degrees(4) = P_azimuth_degrees END SELECT ! on j END SELECT ! on k; boundary class minimum_angle_degrees = DCROT ( actual_TpaPpa_degrees, model_TpaPpa_degrees ) E = (3 / (2 * Phi_max_degrees * radians_per_degree)) * & & MAX( 0.0, (1.0 - (minimum_angle_degrees / Phi_max_degrees)**2) ) CASE (2) ! Pacheco & Sykes [1992]: SELECT CASE(k) ! boundary class CASE (1, 6) ! CCB or OCB: SELECT CASE (j) CASE (1) ! thrust with shortening parallel to relative plate velocity: IF (thrust) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (2) ! thrust with partitioned shortening perpendicular to plate boundary: IF (thrust) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (3) ! partitioned strike-slip on plane striking parallel to plate boundary: IF (strikeslip) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF END SELECT ! on j CASE (2, 5) ! CTF or OTF: SELECT CASE (j) CASE (1) ! strike-slip on vertical plane of plate boundary: IF (strikeslip) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (2) ! normal on plane striking parallel to plate boundary: IF (normal) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (3) ! thrust on plane striking parallel to plate boundary: IF (thrust) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF END SELECT ! on j CASE (3, 4) ! CRB or OSR: SELECT CASE (j) CASE (1) ! normal faulting, with extension in direction of relative plate velocity: IF (normal) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (2) ! normal faulting, with partitioned extension perpendicular to plate boundary: IF (normal) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (3) ! partitioned strike-slip on plane striking parallel to plate boundary: IF (strikeslip) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF END SELECT ! on j CASE (7) ! SUB: SELECT CASE (j) CASE (1) ! main inter-plate thrust fault: IF (thrust) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (2) ! strike-slip parallel to arc: IF (strikeslip) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (3) ! down-dip extension due to bending and/or stress-guide: IF (normal) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF CASE (4) ! down-dip compression due to bending and/or stress-guide: IF (thrust) THEN ; E = 1.0 ; ELSE ; E = 0.0 ; END IF END SELECT ! on j END SELECT ! on k; boundary class END SELECT ! on catalog_ID (CMT, Pacheco & Sykes, ...) ELSE ! no mechanism information; punt: E = 1.0 END IF ! end of E (focal mechanism) section IF (E > 0.0) THEN ! this EQ mechanism could match this model sum_CDE = sum_CDE + C * D * E END IF ! E > 0.0; this EQ mechanism could match this model END IF ! D > 0.0; this EQ depth could match this model END IF ! this model has a chance of happening END DO ! j = 1, 4 ! (up to) 4 model earthquakes for this step !------------------------------------------------------------------------------------ P_prime = A * B * sum_CDE sum_P_prime_in_class(k) = sum_P_prime_in_class(k) + P_prime sum_P_prime_all_classes = sum_P_prime_all_classes + P_prime !Check whether a new overall maximum has been achieved: IF (P_prime > highest_P_prime) THEN highest_P_prime = P_prime best_i = i best_k = k END IF !Check whether a new maximum has been achieved for this class: IF (P_prime > highest_P_prime_in_class(k)) THEN highest_P_prime_in_class(k) = P_prime best_i_in_class(k) = i END IF END IF ! (A * B) > 0.0 (meaning this step has possibilities) END DO ! i = 1, nSteps; testing all steps as possible producers of this EQ IF (Monte_Carlo_method.AND.(best_k > 0)) THEN !Re-determine best_k, and therefore best_i (which often will turn out to be unchanged), !by comparing a random number to a set of adjacent bins whose widths are proportional !to sum_P_prime_in_class(1:7). !Set up the bins for classes which are in competition: partial_sum = 0.0 ! initialization before sum upper_fraction = 0.0 ! whole array; to simplify debugging DO k = 1, 7 in_competition(k) = (sum_P_prime_in_class(k) > 0.0) IF (in_competition(k)) THEN partial_sum = partial_sum + sum_P_prime_in_class(k) / sum_P_prime_all_classes upper_fraction(k) = partial_sum END IF END DO CALL RNUN(1, random) ! Retrieve next random number, in range (0, 1). !Compare random number to upper limit of each active bin. !Note: Order of comparison eliminates the need to test the lower limit. comparing: DO k = 1, 7 IF (in_competition(k)) THEN IF (random <= upper_fraction(k)) THEN best_k = k EXIT comparing END IF END IF END DO comparing best_i = best_i_in_class(best_k) END IF ! =========== end heart of this program ====================================================== ! At this point, critical information is contained in: ! pure_epicenter = .TRUE. if this earthquake was NOT in any orogen ! pure_epicenter_c1 = ' ' (not in any orogen) or '*' (orogen) ! best_k = 1-7 = index of class that this earthquake should be assigned to. ! best_i = 1-nStep = index of the plate boundary step this earthquake should be assigned to. ! sum_P_prime_in_class(1:7) = values of P_prime for steps, aggregated and summed by step class. ! sum_P_prime_all_classes = SUM(sum_P_prime_in_class) ! =========== end heart of this program ====================================================== ! output this event to appropriate catalog(s): SELECT CASE (best_k) CASE (0) ! INT count_all(0) = count_all(0) + 1 i0 = 0 ! place-holder, for name of associated step pure_step_c1 = ' ' ! because it is not associated with any step, step cannot make it impure relative_class_probability_int = 0 ! whole array distance_km = arc_km_from_step(1) DO i = 2, nSteps distance_km = MIN(distance_km, arc_km_from_step(i)) END DO WRITE (102, 3002) catalog_name, & & eq_year, eq_month, eq_day, & & eq_hour, eq_minute, eq_second, eq_tenths, & & eq_Elon, eq_Nlat, & & eq_depth_int, eq_mag, & & TRIM(appended_data), & & pure_epicenter_c1, class_c3(0), pure_step_c1, & & i0, & ! additional information: step number is 0 & (relative_class_probability_int(n), n = 1, 7), & ! additional info: 7 0's (probabilities) & distance_km ! additional info: distance to closest step IF (pure_epicenter) THEN count_pure(0) = count_pure(0) + 1 WRITE (101, 3002) catalog_name, & & eq_year, eq_month, eq_day, & & eq_hour, eq_minute, eq_second, eq_tenths, & & eq_Elon, eq_Nlat, & & eq_depth_int, eq_mag, & & TRIM(appended_data), & & pure_epicenter_c1, class_c3(0), pure_step_c1, & & i0, & ! additional information: step number is 0 & (relative_class_probability_int(n), n = 1, 7), & ! additional info: 7 0's (probabilities) & distance_km ! additional info: distance to closest step END IF CASE (1:7) ! CCB:SUB count_all(best_k) = count_all(best_k) + 1 pure_step_c1 = star_c1(best_i) pure_step = (pure_step_c1 /= '*') relative_class_probability_int = NINT(100 * sum_P_prime_in_class / sum_P_prime_all_classes) ! array of 7 %'s distance_km = distance_km_from_step(best_i) WRITE (10 * best_k + 2, 3002) catalog_name, & & eq_year, eq_month, eq_day, & & eq_hour, eq_minute, eq_second, eq_tenths, & & eq_Elon, eq_Nlat, & & eq_depth_int, eq_mag, & & TRIM(appended_data), & & pure_epicenter_c1, class(best_i), pure_step_c1, best_i, & ! additional info. & (relative_class_probability_int(n), n = 1, 7), & ! additional info. & distance_km ! additional info: distance to closest step !Note: Unless there has been some error, we expect: ! class(best_i) == class_c3(best_k) !Either one could be output. IF (pure_epicenter.AND.pure_step) THEN count_pure(best_k) = count_pure(best_k) + 1 WRITE (10 * best_k + 1, 3002) catalog_name, & & eq_year, eq_month, eq_day, & & eq_hour, eq_minute, eq_second, eq_tenths, & & eq_Elon, eq_Nlat, & & eq_depth_int, eq_mag, & & TRIM(appended_data), & & pure_epicenter_c1, class(best_i), pure_step_c1, best_i, & ! additional info. & (relative_class_probability_int(n), n = 1, 7), & ! additional info. & distance_km ! additional info: distance to closest step !Note: Unless there has been some error, we expect: ! class(best_i) == class_c3(best_k) !Either one could be output. !addition of 2003.06: IF (eq_mag > class_threshhold_magnitude(best_k)) THEN !GPBhere eq_count_over_threshhold(best_i) = eq_count_over_threshhold(best_i) + 1 eq_moment_Nm = 10.0**(9.05 + 1.5 * eq_mag) ! Hanks & Kanamori [1979] moment_sum_over_threshhold(best_i) = moment_sum_over_threshhold(best_i) + eq_moment_Nm END IF END IF END SELECT END DO next_event CLOSE (4) CLOSE (11) CLOSE (12) CLOSE (21) CLOSE (22) CLOSE (31) CLOSE (32) CLOSE (41) CLOSE (42) CLOSE (51) CLOSE (52) CLOSE (61) CLOSE (62) CLOSE (71) CLOSE (72) CLOSE (101) CLOSE (102) !GPBhere !Addition of 2003.06: output the 7 "PB2002_XXX_pure.dat" files with eq counts and moment sums: DO k = 1, 7 ! classes 1-7 = CCB...SUB out_file_name = "PB2002_" // class_c3(k) // "_pure.dat" OPEN (UNIT = 201, FILE = out_file_name) ! unconditional OPEN; overwrites any existing file DO i = 1, nSteps IF (class(i) == class_c3(k)) THEN IF (star_c1(i) == ' ') THEN ! pure step WRITE (201, 9001) sequence_number(i), step_continuity_c1(i), c5(i), & & old_longitude(i), old_latitude(i), longitude(i), latitude(i), & & length_km(i), azimuth_integer(i), & & velocity_mmpa(i), velocity_azimuth_integer(i), & & divergence_mmpa(i), dextral_mmpa(i), & & elevation(i), age_Ma(i), & & class_continuity_c1(i), class(i), star_c1(i), & ! so far, same as READ & eq_count_over_threshhold(i), moment_sum_over_threshhold(i) 9001 FORMAT (I4, 1X, A1, A5, & & 1X, F8.3, 1X, F7.3, 1X, F8.3, 1X, F7.3, & & 1X, F5.1, 1X, I3, & & 1X, F5.1, 1X, I3, & & 1X, F6.1, 1X, F6.1, & & 1X, I6, 1X, I3, & & 1X, A1, A3, A1, & ! so far, same as 1001 used in READ & 1X, I6, 1X, E10.3) END IF ! a pure step END IF ! correct plate boundary class for this file END DO ! i = 1, nSteps CLOSE (201) END DO ! k = 1, 7 !------------- More output to screen ----------------------------------------------- WRITE (*, "(' Finished reading and classifying ', A, ':')") TRIM(catalog_file_name) IF (Monte_Carlo_method) THEN WRITE ( *, "(' using Monte-Carlo randomization of class assignments')") ELSE WRITE ( *, "(' using maximum-probability step assignment to decide class:')") END IF WRITE ( *, *) WRITE ( *, "(' ',8(4X,A3))") (class_c3(n), n = 0, 7) WRITE ( *, "(' pure:',8(1X,I6))") (count_pure(n), n = 0, 7) nEvents = SUM(count_pure) percentages = NINT(100.0 * count_pure / nEvents) WRITE ( *, "(' pure:',8(3X,I3,'%'))") (percentages(n), n = 0, 7) WRITE ( *, *) WRITE ( *, "(' all:',8(1X,I6))") (count_all(n), n = 0, 7) nEvents = SUM(count_all) percentages = NINT(100.0 * count_all / nEvents) WRITE ( *, "(' all:',8(3X,I3,'%'))") (percentages(n), n = 0, 7) WRITE ( *, *) !------------------------------------------------------------------------------------ !------------- Output to log file ------------------------------------------------- out_file_name = TRIM(prefix) // "_PB2002_EQ_classification.txt" OPEN (UNIT = 99, FILE = out_file_name) WRITE (99, "('Running EQ_classification_II.exe, from EQ_classification_II.f90....')") WRITE (99, *) WRITE (99,"('Run on ',I4,'.',I2,'.',I2,' at ',I2,':',I2,':',I2)") & datetimenumber(1), datetimenumber(2), datetimenumber(3), & datetimenumber(5), datetimenumber(6), datetimenumber(7) WRITE (99, *) WRITE (99, "('Catalog file = ',A)") TRIM(catalog_file_name) WRITE (99, *) WRITE (99, "('Parameter values (compiled-in):')") WRITE (99, "('-------------------------------')") WRITE (99, "('All boundaries:')") WRITE (99, "(L10, 2X,'Monte_Carlo_method')") Monte_Carlo_method IF (Monte_Carlo_method) THEN WRITE (99, "(I10, 2X,'iseed')") iseed END IF WRITE (99, "(F10.1,2X,'alongStep_sigma_km')") alongStep_sigma_km WRITE (99, "(F10.1,2X,'earthquake_depth_sigma_km')") earthquake_depth_sigma_km WRITE (99, "(F10.1,2X,'Phi_max_degrees')") Phi_max_degrees WRITE (99, "('Non-SUB boundaries:')") WRITE (99, "(F10.1,2X,'class123456_cutoff_depth_km')") class123456_cutoff_depth_km WRITE (99, "(' - - - - - - - - - - - - - - - - -')") WRITE (99, "(I10, 2X,'CCB_pure_totalEvents')") CCB_pure_totalEvents WRITE (99, "(I10, 2X,'CTF_pure_totalEvents')") CTF_pure_totalEvents WRITE (99, "(I10, 2X,'CRB_pure_totalEvents')") CRB_pure_totalEvents WRITE (99, "(I10, 2X,'OSR_pure_totalEvents')") OSR_pure_totalEvents WRITE (99, "(I10, 2X,'OTF_pure_totalEvents')") OTF_pure_totalEvents WRITE (99, "(I10, 2X,'OCB_pure_totalEvents')") OCB_pure_totalEvents WRITE (99, "(I10, 2X,'SUB_pure_totalEvents')") SUB_pure_totalEvents WRITE (99, "(' - - - - - - - - - - - - - - - - -')") WRITE (99, "(F10.1,2X,'CCB_pure_totalLength_km')") CCB_pure_totalLength_km WRITE (99, "(F10.1,2X,'CTF_pure_totalLength_km')") CTF_pure_totalLength_km WRITE (99, "(F10.1,2X,'CRB_pure_totalLength_km')") CRB_pure_totalLength_km WRITE (99, "(F10.1,2X,'OSR_pure_totalLength_km')") OSR_pure_totalLength_km WRITE (99, "(F10.1,2X,'OTF_pure_totalLength_km')") OTF_pure_totalLength_km WRITE (99, "(F10.1,2X,'OCB_pure_totalLength_km')") OCB_pure_totalLength_km WRITE (99, "(F10.1,2X,'SUB_pure_totalLength_km')") SUB_pure_totalLength_km WRITE (99, "(' - - - - - - - - - - - - - - - - -')") WRITE (99, "(F10.1,2X,'CCB_pure_meanVelocity_mmpa')") CCB_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'CTF_pure_meanVelocity_mmpa')") CTF_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'CRB_pure_meanVelocity_mmpa')") CRB_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'OSR_pure_meanVelocity_mmpa')") OSR_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'OTF_pure_meanVelocity_mmpa')") OTF_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'OCB_pure_meanVelocity_mmpa')") OCB_pure_meanVelocity_mmpa WRITE (99, "(F10.1,2X,'SUB_pure_meanVelocity_mmpa')") SUB_pure_meanVelocity_mmpa WRITE (99, "(' - - - - - - - - - - - - - - - - -')") WRITE (99, "('non-SUB boundaries (symmetrical):')") WRITE (99, "(F10.1,2X,'CCB_halfwidth_km')") CCB_halfwidth_km WRITE (99, "(F10.1,2X,'CTF_halfwidth_km')") CTF_halfwidth_km WRITE (99, "(F10.1,2X,'CRB_halfwidth_km')") CRB_halfwidth_km WRITE (99, "(F10.1,2X,'OSR_halfwidth_km')") OSR_halfwidth_km WRITE (99, "(F10.1,2X,'OTF_halfwidth_km')") OTF_halfwidth_km WRITE (99, "(F10.1,2X,'OCB_halfwidth_km')") OCB_halfwidth_km WRITE (99, "(' - - - - - - - - - - - - - - - - -')") WRITE (99, "('SUB boundaries (asymmetric):')") WRITE (99, "(F10.1,2X,'SUB_landward_halfwidth_km')") SUB_landward_halfwidth_km WRITE (99, "(F10.1,2X,'SUB_seaward_halfwidth_km')") SUB_seaward_halfwidth_km WRITE (99, "(F10.1,2X,'SUB_peakSeismicity_km')") SUB_peakSeismicity_km WRITE (99, "('quadratic model of depth to slab in SUBs:')") WRITE (99, "(F10.2,2X,'trench_depth_km')") trench_depth_km WRITE (99, "(F10.4,2X,'slope_at_trench')") slope_at_trench WRITE (99, "(F10.1,2X,'slab_depth_under_arc_km')") slab_depth_under_arc_km WRITE (99, "(F10.1,2X,'arc_distance_km')") arc_distance_km WRITE (99, "(F10.2,2X,'interplate_thrust_depth_sigma_fraction')") interplate_thrust_depth_sigma_fraction WRITE (99, "('-------------------------------------------------------------------')") WRITE (99, *) IF (Monte_Carlo_method) THEN WRITE (99, "('Using Monte-Carlo randomization of class assignments:')") ELSE WRITE (99, "('Using maximum-probability step assignment to decide class:')") END IF WRITE (99, *) WRITE (99, "(' ',8(4X,A3))") (class_c3(n), n = 0, 7) WRITE (99, "(' pure:',8(1X,I6))") (count_pure(n), n = 0, 7) nEvents = SUM(count_pure) percentages = NINT(100.0 * count_pure / nEvents) WRITE (99, "(' pure:',8(3X,I3,'%'))") (percentages(n), n = 0, 7) WRITE (99, *) WRITE (99, "(' all:',8(1X,I6))") (count_all(n), n = 0, 7) nEvents = SUM(count_all) percentages = NINT(100.0 * count_all / nEvents) WRITE (99, "(' all:',8(3X,I3,'%'))") (percentages(n), n = 0, 7) !------------------------------------------------------------------------------------ CLOSE(99) CALL Pause() CONTAINS INTEGER FUNCTION iPlate(c2) IMPLICIT NONE CHARACTER*2, INTENT(IN) :: c2 INTEGER :: i iPlate = 0 DO i = 1, nPlates IF (ID(i) == c2) THEN iPlate = i RETURN END IF END DO END FUNCTION iPlate SUBROUTINE Oblique_FPS (fault_strike_degrees, fault_dip_degrees, dip_is_to_right, & & relative_velocity_azimuth_degrees, relative_velocity_is_divergent, & ! input & e1_azimuth_degrees, e1_plunge_degrees, & & e2_azimuth_degrees, e2_plunge_degrees, & & e3_azimuth_degrees, e3_plunge_degrees) ! output !Computes principal strain axes (e1 most compressive, e2 neutral, e3 most extensional) !of the double-couple moment tensor produced by oblique slip on a dipping fault plane. !Warning: Do NOT call this routine with fault_dip_degrees = 90.0! Dip should be in range: 0.0 < dip < 90.0 ! Also, do NOT call this routine for events exactly at the N (or S) pole! USE Sphere ! Sphere.f90 by Peter Bird, UCLA IMPLICIT NONE LOGICAL, INTENT(IN) :: dip_is_to_right, relative_velocity_is_divergent REAL, INTENT(IN) :: fault_strike_degrees, fault_dip_degrees, relative_velocity_azimuth_degrees INTEGER, INTENT(OUT) :: e1_azimuth_degrees, e1_plunge_degrees, & & e2_azimuth_degrees, e2_plunge_degrees, & & e3_azimuth_degrees, e3_plunge_degrees INTEGER :: t_azimuth_degrees, t_plunge_degrees REAL :: crossStrike_component, downDip_component, strike_component, vertical_component REAL, DIMENSION(3) :: backSlip_uvec, & & crossStrike_uvec, & & downDip_uvec, & & e1_uvec, e2_uvec, e3_uvec, eX_uvec, & & faultNormal_uvec, & & heave_uvec, & & phi_uvec, & & slip_uvec, strike_uvec, & & tvec, theta_uvec, & & up_uvec !Validate input values: IF ((fault_dip_degrees <= 0.0).OR.(fault_dip_degrees >= 90.0)) THEN WRITE (*, "(' ERROR: Oblique_FPS requires 0.0 < fault_dip_degrees < 90.0')") CALL Traceback() END IF !Note: Without loss of generality, earthquake is assumed to be at (0 E, 0 N): up_uvec = (/ 1.0, 0.0, 0.0 /) !Rest of code should be correct, regardless of earthquake location. !Finish local coordinate system: CALL Local_Theta(up_uvec, theta_uvec) ! South CALL Local_Phi (up_uvec, phi_uvec) ! East !Describe orientation of fault: strike_uvec(1:3) = -COS(fault_strike_degrees * radians_per_degree) * theta_uvec(1:3) + & & SIN(fault_strike_degrees * radians_per_degree) * phi_uvec(1:3) IF (dip_is_to_right) THEN crossStrike_uvec(1:3) = -COS((fault_strike_degrees + 90.0) * radians_per_degree) * theta_uvec(1:3) + & & SIN((fault_strike_degrees + 90.0) * radians_per_degree) * phi_uvec(1:3) ELSE crossStrike_uvec(1:3) = -COS((fault_strike_degrees - 90.0) * radians_per_degree) * theta_uvec(1:3) + & & SIN((fault_strike_degrees - 90.0) * radians_per_degree) * phi_uvec(1:3) END IF ! Note: crossStrike_uvec is horizontal, and lies above the dipping fault. downDip_uvec(1:3) = COS(fault_dip_degrees * radians_per_degree) * crossStrike_uvec(1:3) - & & SIN(fault_dip_degrees * radians_per_degree) * up_uvec(1:3) IF (dip_is_to_right) THEN CALL Cross(downDip_uvec, strike_uvec, faultNormal_uvec) ELSE CALL Cross(strike_uvec, downDip_uvec, faultNormal_uvec) END IF !Note: faultNormal_uvec always has a positive (upward) vertical component. !Describe slip vector: heave_uvec(1:3) = -COS(relative_velocity_azimuth_degrees * radians_per_degree) * theta_uvec(1:3) + & & SIN(relative_velocity_azimuth_degrees * radians_per_degree) * phi_uvec(1:3) !Note: At this point, heave_uvec has same sense as input relative_velocity_azimuth_degrees IF (relative_velocity_is_divergent) THEN IF (Dot(heave_uvec, crossStrike_uvec) < 0.0) heave_uvec = -heave_uvec ELSE ! relative velocity is convergent IF (Dot(heave_uvec, crossStrike_uvec) > 0.0) heave_uvec = -heave_uvec END IF !Note: At this point, heave_uvec refers to motion of the hanging wall, relative to the footwall. strike_component = Dot(heave_uvec, strike_uvec) ! may be negative crossStrike_component = Dot(heave_uvec, crossStrike_uvec) ! positive for extension; negative for thrusting vertical_component = -crossStrike_component * TAN(fault_dip_degrees * radians_per_degree) ! negative for extension; positive for thrusting !Note: vertical_component magnitude is relative to ||heave_uvec|| = 1.0 downDip_component = crossStrike_component / COS(fault_dip_degrees * radians_per_degree) ! positive for extension; negative for thrusting !Note: downDip_component magnitude is relative to ||heave_uvec|| = 1.0 tvec(1:3) = strike_component * strike_uvec(1:3) + downDip_component * downDip_uvec(1:3) CALL Make_Uvec(tvec, slip_uvec) ! refers to motion of hanging wall relative to footwall !Describe moment tensor by its principal axes, getting e2 first: CALL Cross(faultNormal_uvec, slip_uvec, e2_uvec) !Find a vector normal to e2 (composed from slip_uvec and faultNormal_uvec) which is nearly horizontal: IF (Dot(slip_uvec, up_uvec) > 0.0) THEN backSlip_uvec = -slip_uvec ELSE backSlip_uvec = slip_uvec END IF !Note: backSlip_uvec points (obliquely) down in the fault plane; it might be parallel, or opposite, to slip_uvec. tvec(1:3) = (backSlip_uvec(1:3) + faultNormal_uvec(1:3)) / 2.0 ! averaging one pointing down with one pointing up. CALL Make_Uvec(tvec, eX_uvec) !Note: eX_uvec is normal to e2_uvec, and 45 degrees from both slip_uvec and faultNormal_uvec; ! therefore it should be either e1_uvec or e3_uvec. ! Choose the name of the principal axis which is closest to horizontal: IF (relative_velocity_is_divergent) THEN e3_uvec = eX_uvec CALL Cross (e3_uvec, e2_uvec, e1_uvec) ELSE ! relative velocity is convergent; a thrust e1_uvec = eX_uvec CALL Cross (e1_uvec, e2_uvec, e3_uvec) END IF !Be sure all principal axes have positive plunge, then convert to azimuth and plunge: IF (Dot(e1_uvec, up_uvec) > 0.0) e1_uvec = -e1_uvec IF (Dot(e2_uvec, up_uvec) > 0.0) e2_uvec = -e2_uvec IF (Dot(e3_uvec, up_uvec) > 0.0) e3_uvec = -e3_uvec CALL Uvec_2_PlungeAzimuth(up_uvec, e1_uvec, e1_plunge_degrees, e1_azimuth_degrees) CALL Uvec_2_PlungeAzimuth(up_uvec, e2_uvec, e2_plunge_degrees, e2_azimuth_degrees) CALL Uvec_2_PlungeAzimuth(up_uvec, e3_uvec, e3_plunge_degrees, e3_azimuth_degrees) END SUBROUTINE Oblique_FPS SUBROUTINE Pause () IMPLICIT NONE WRITE (*, "(/' Press [Enter] to continue...')") READ (*, *) RETURN END SUBROUTINE Pause END PROGRAM EQ_classification_II