diff --git a/tests/test_hf.py b/tests/test_hf.py index 417a75c9..8988d720 100644 --- a/tests/test_hf.py +++ b/tests/test_hf.py @@ -64,6 +64,7 @@ def test_build_hf_input_serialisation() -> None: shallow_transition_range=1, deep_depth=2.0, deep_transition_range=1, + rvfrac_slip_sig=None ) # Rather than create DomainParameters with a bounding box, we simplify with a mock object domain = SimpleNamespace(duration=100.0) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index 89a23191..57b9ea0c 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -135,6 +135,93 @@ def test_srf_config_example(tmp_path: Path) -> None: xmag_exp=None, kx_corner=None, ky_corner=None, + beta_asp=0.3, + beta_deep=0.13, + beta_mid=0.13, + beta_mid_depth=6.5, + beta_mid_depth_range=1.5, + beta_shal=0.5, + beta_shal_depth=2.0, + beta_shal_depth_range=1.0, + beta_subevt=0.1, + deep_risetimedep=17.5, + deep_risetimedep_range=2.5, + deep_risetimefac=2.0, + risetimedep=6.5, + risetimedep_range=1.5, + risetimefac=2.0, + rt_rand=0.0, + rt_scalefac=1.0, + stype=None, + hyb_corlen_deep_wt_end=1.0, + hyb_corlen_deep_wt_start=0.0, + hyb_corlen_dep=6.5, + hyb_corlen_dep_range=1.5, + hyb_corlen_fac=2.0, + hyb_corlen_flag=False, + hyb_corlen_kmodel=schemas.KModel.SUZUKI, + hyb_corlen_shal_wt_end=0.0, + hyb_corlen_shal_wt_start=1.0, + hyb_corlen_side_taper=0.08, + fdrup_scale_slip=False, + fdrup_time=False, + rupture_delay=0.0, + rvfmax=1.414, + rvfmin=0.25, + truncate_zero_slip=True, + slip_water_level=None, + rake_sigma=15.0, + fractal_rake=False, + tsfac1_scor=0.8, + tsfac1_sigma=1.0, + tsfac2_lambda_max=5.0, + tsfac2_lambda_min=None, + tsfac2_scor=0.5, + tsfac2_sigma=1.0, + tsfac_bzero=-0.1, + tsfac_coef=1.1, + tsfac_main=None, + tsfac_slope=-0.5, + circular_average=False, + kmodel=schemas.KModel.MAI, + kord=4, + magC=6.3, + mag_area_Acoef=None, + mag_area_Bcoef=None, + mai_wt=0.5, + modified_corners=False, + somerville_wt=0.5, + stretch_kcorner=False, + use_gaus=True, + use_median_mag=False, + lambda_max=None, + lambda_min=None, + wavelength_max=None, + wavelength_min=None, + asp_taper_fac=0.05, + extend_fac=None, + flen_max=None, + fwid_max=None, + moment_fraction=None, + perturb_subfault_location=True, + rand_rake_degs=60.0, + rtime1_depth=2.0, + rtime1_depth_range=1.0, + rtime1_scor=0.8, + rtime1_sigma=0.85, + rtime2_scor=0.5, + rtime2slip_exp=0.5, + rtime_rand=None, + set_rake=None, + svr_wt=0.0, + target_savg=None, + use_Mw=True, + aseis_flag=False, + aseis_smooth=False, + aseis_dep=10.0, + aseis_fac=None, + xshift=0.0, + yshift=0.0, ) realisation_ffp = tmp_path / "realisation.json" @@ -174,6 +261,93 @@ def test_srf_config_example(tmp_path: Path) -> None: "xmag_exp": None, "kx_corner": None, "ky_corner": None, + "beta_asp": 0.3, + "beta_deep": 0.13, + "beta_mid": 0.13, + "beta_mid_depth": 6.5, + "beta_mid_depth_range": 1.5, + "beta_shal": 0.5, + "beta_shal_depth": 2.0, + "beta_shal_depth_range": 1.0, + "beta_subevt": 0.1, + "deep_risetimedep": 17.5, + "deep_risetimedep_range": 2.5, + "deep_risetimefac": 2.0, + "risetimedep": 6.5, + "risetimedep_range": 1.5, + "risetimefac": 2.0, + "rt_rand": 0.0, + "rt_scalefac": 1.0, + "stype": None, + "hyb_corlen_deep_wt_end": 1.0, + "hyb_corlen_deep_wt_start": 0.0, + "hyb_corlen_dep": 6.5, + "hyb_corlen_dep_range": 1.5, + "hyb_corlen_fac": 2.0, + "hyb_corlen_flag": False, + "hyb_corlen_kmodel": schemas.KModel.SUZUKI, + "hyb_corlen_shal_wt_end": 0.0, + "hyb_corlen_shal_wt_start": 1.0, + "hyb_corlen_side_taper": 0.08, + "fdrup_scale_slip": False, + "fdrup_time": False, + "rupture_delay": 0.0, + "rvfmax": 1.414, + "rvfmin": 0.25, + "truncate_zero_slip": True, + "slip_water_level": None, + "rake_sigma": 15.0, + "fractal_rake": False, + "tsfac1_scor": 0.8, + "tsfac1_sigma": 1.0, + "tsfac2_lambda_max": 5.0, + "tsfac2_lambda_min": None, + "tsfac2_scor": 0.5, + "tsfac2_sigma": 1.0, + "tsfac_bzero": -0.1, + "tsfac_coef": 1.1, + "tsfac_main": None, + "tsfac_slope": -0.5, + "circular_average": False, + "kmodel": 2, + "kord": 4, + "magC": 6.3, + "mag_area_Acoef": None, + "mag_area_Bcoef": None, + "mai_wt": 0.5, + "modified_corners": False, + "somerville_wt": 0.5, + "stretch_kcorner": False, + "use_gaus": True, + "use_median_mag": False, + "lambda_max": None, + "lambda_min": None, + "wavelength_max": None, + "wavelength_min": None, + "asp_taper_fac": 0.05, + "extend_fac": None, + "flen_max": None, + "fwid_max": None, + "moment_fraction": None, + "perturb_subfault_location": True, + "rand_rake_degs": 60.0, + "rtime1_depth": 2.0, + "rtime1_depth_range": 1.0, + "rtime1_scor": 0.8, + "rtime1_sigma": 0.85, + "rtime2_scor": 0.5, + "rtime2slip_exp": 0.5, + "rtime_rand": None, + "set_rake": None, + "svr_wt": 0.0, + "target_savg": None, + "use_Mw": True, + "aseis_flag": False, + "aseis_smooth": False, + "aseis_dep": 10.0, + "aseis_fac": None, + "xshift": 0.0, + "yshift": 0.0, }, } diff --git a/tests/test_realisation_to_srf.py b/tests/test_realisation_to_srf.py index c5632cd6..c6525ffc 100644 --- a/tests/test_realisation_to_srf.py +++ b/tests/test_realisation_to_srf.py @@ -28,6 +28,93 @@ def test_build_genslip_command_static_args() -> None: xmag_exp=1.0, kx_corner=None, ky_corner=None, + beta_asp=0.3, + beta_deep=0.13, + beta_mid=0.13, + beta_mid_depth=6.5, + beta_mid_depth_range=1.5, + beta_shal=0.5, + beta_shal_depth=2.0, + beta_shal_depth_range=1.0, + beta_subevt=0.1, + deep_risetimedep=17.5, + deep_risetimedep_range=2.5, + deep_risetimefac=2.0, + risetimedep=6.5, + risetimedep_range=1.5, + risetimefac=2.0, + rt_rand=0.0, + rt_scalefac=1.0, + stype=None, + hyb_corlen_deep_wt_end=1.0, + hyb_corlen_deep_wt_start=0.0, + hyb_corlen_dep=6.5, + hyb_corlen_dep_range=1.5, + hyb_corlen_fac=2.0, + hyb_corlen_flag=False, + hyb_corlen_kmodel=schemas.KModel.SUZUKI, + hyb_corlen_shal_wt_end=0.0, + hyb_corlen_shal_wt_start=1.0, + hyb_corlen_side_taper=0.08, + fdrup_scale_slip=False, + fdrup_time=False, + rupture_delay=0.0, + rvfmax=1.414, + rvfmin=0.25, + truncate_zero_slip=True, + slip_water_level=None, + rake_sigma=15.0, + fractal_rake=False, + tsfac1_scor=0.8, + tsfac1_sigma=1.0, + tsfac2_lambda_max=5.0, + tsfac2_lambda_min=None, + tsfac2_scor=0.5, + tsfac2_sigma=1.0, + tsfac_bzero=-0.1, + tsfac_coef=1.1, + tsfac_main=None, + tsfac_slope=-0.5, + circular_average=False, + kmodel=schemas.KModel.MAI, + kord=4, + magC=6.3, + mag_area_Acoef=None, + mag_area_Bcoef=None, + mai_wt=0.5, + modified_corners=False, + somerville_wt=0.5, + stretch_kcorner=False, + use_gaus=True, + use_median_mag=False, + lambda_max=None, + lambda_min=None, + wavelength_max=None, + wavelength_min=None, + asp_taper_fac=0.05, + extend_fac=None, + flen_max=None, + fwid_max=None, + moment_fraction=None, + perturb_subfault_location=True, + rand_rake_degs=60.0, + rtime1_depth=2.0, + rtime1_depth_range=1.0, + rtime1_scor=0.8, + rtime1_sigma=0.85, + rtime2_scor=0.5, + rtime2slip_exp=0.5, + rtime_rand=None, + set_rake=None, + svr_wt=0.0, + target_savg=None, + use_Mw=True, + aseis_flag=False, + aseis_smooth=False, + aseis_dep=10.0, + aseis_fac=None, + xshift=0.0, + yshift=0.0, ) genslip_path = Path("genslip_v5.6.2") gsf_path = Path("/tmp/fault.gsf") @@ -35,6 +122,7 @@ def test_build_genslip_command_static_args() -> None: rupture_velocity = RuptureVelocity( rvfrac=1.0, rvfrac_shal=0.6, + rvfrac_slip_sig=None, rvfrac_deep=0.7, shallow_depth=15.0, shallow_transition_range=5.0, @@ -94,4 +182,74 @@ def test_build_genslip_command_static_args() -> None: "deep_vrup=0.7", "deep_vrup_dep=20.0", "deep_vrup_deprange=2.5", + # New genslip parameters + "beta_asp=0.3", + "beta_deep=0.13", + "beta_mid=0.13", + "beta_mid_depth=6.5", + "beta_mid_depth_range=1.5", + "beta_shal=0.5", + "beta_shal_depth=2.0", + "beta_shal_depth_range=1.0", + "beta_subevt=0.1", + "deep_risetimedep=17.5", + "deep_risetimedep_range=2.5", + "deep_risetimefac=2.0", + "risetimedep=6.5", + "risetimedep_range=1.5", + "risetimefac=2.0", + "rt_rand=0.0", + "rt_scalefac=1.0", + "hyb_corlen_deep_wt_end=1.0", + "hyb_corlen_deep_wt_start=0.0", + "hyb_corlen_dep=6.5", + "hyb_corlen_dep_range=1.5", + "hyb_corlen_fac=2.0", + "hyb_corlen_flag=0", + "hyb_corlen_kmodel=5", + "hyb_corlen_shal_wt_end=0.0", + "hyb_corlen_shal_wt_start=1.0", + "hyb_corlen_side_taper=0.08", + "fdrup_scale_slip=0", + "fdrup_time=0", + "rupture_delay=0.0", + "rvfmax=1.414", + "rvfmin=0.25", + "truncate_zero_slip=1", + "rake_sigma=15.0", + "fractal_rake=0", + "tsfac1_scor=0.8", + "tsfac1_sigma=1.0", + "tsfac2_lambda_max=5.0", + "tsfac2_scor=0.5", + "tsfac2_sigma=1.0", + "tsfac_bzero=-0.1", + "tsfac_coef=1.1", + "tsfac_slope=-0.5", + "circular_average=0", + "kmodel=2", + "kord=4", + "magC=6.3", + "mai_wt=0.5", + "modified_corners=0", + "somerville_wt=0.5", + "stretch_kcorner=0", + "use_gaus=1", + "use_median_mag=0", + "asp_taper_fac=0.05", + "perturb_subfault_location=1", + "rand_rake_degs=60.0", + "rtime1_depth=2.0", + "rtime1_depth_range=1.0", + "rtime1_scor=0.8", + "rtime1_sigma=0.85", + "rtime2_scor=0.5", + "rtime2slip_exp=0.5", + "svr_wt=0.0", + "use_Mw=1", + "aseis_flag=0", + "aseis_smooth=0", + "aseis_dep=10.0", + "xshift=0.0", + "yshift=0.0", } diff --git a/workflow/default_parameters/root/defaults.yaml b/workflow/default_parameters/root/defaults.yaml index b5015d07..adc638a0 100644 --- a/workflow/default_parameters/root/defaults.yaml +++ b/workflow/default_parameters/root/defaults.yaml @@ -99,6 +99,7 @@ rupture_velocity: rvfrac: 0.8 rvfrac_shal: 0.6 rvfrac_deep: 0.6 + rvfrac_slip_sig: null shallow_depth: 6.5 deep_depth: 17.5 shallow_transition_range: 1.5 @@ -118,6 +119,102 @@ srf: resolution: 0.1 slip_sigma: 0.75 risetime_coef: 1.6 + # Rise time and source time function values + beta_asp: 0.3 + beta_deep: 0.13 + beta_mid: 0.13 + beta_mid_depth: 6.5 + beta_mid_depth_range: 1.5 + beta_shal: 0.5 + beta_shal_depth: 2.0 + beta_shal_depth_range: 1.0 + beta_subevt: 0.1 + deep_risetimedep: 17.5 + deep_risetimedep_range: 2.5 + deep_risetimefac: 2.0 + risetimedep: 6.5 + risetimedep_range: 1.5 + risetimefac: 2.0 + rt_rand: 0.0 + rt_scalefac: 1.0 + stype: null + # Hybrid Correlation Length (hyb_corlen) Parameters + hyb_corlen_deep_wt_end: 1.0 + hyb_corlen_deep_wt_start: 0.0 + hyb_corlen_dep: 6.5 + hyb_corlen_dep_range: 1.5 + hyb_corlen_fac: 2.0 + hyb_corlen_flag: false + hyb_corlen_kmodel: 5 + hyb_corlen_shal_wt_end: 0.0 + hyb_corlen_shal_wt_start: 1.0 + hyb_corlen_side_taper: 0.08 + # Rupture Velocity & Fault Dimensions + fdrup_scale_slip: false + fdrup_time: false + rupture_delay: 0.0 + rvfmax: 1.414 + rvfmin: 0.25 + # Tapering & Slip Level Adjustments + truncate_zero_slip: true + slip_water_level: null + rake_sigma: 15.0 + fractal_rake: false + # Time Shift Factors (tsfac) + tsfac1_scor: 0.8 + tsfac1_sigma: 1.0 + tsfac2_lambda_max: 5.0 + tsfac2_lambda_min: null + tsfac2_scor: 0.5 + tsfac2_sigma: 1.0 + tsfac_bzero: -0.1 + tsfac_coef: 1.1 + tsfac_main: null + tsfac_slope: -0.5 + # Kinematic Models & Corner Frequencies + circular_average: false + kmodel: 2 + kord: 4 + magC: 6.3 + mag_area_Acoef: null + mag_area_Bcoef: null + mai_wt: 0.5 + modified_corners: false + somerville_wt: 0.5 + stretch_kcorner: false + use_gaus: true + use_median_mag: false + # Roughness & Wavelength Limits + lambda_max: null + lambda_min: null + wavelength_max: null + wavelength_min: null + # Miscellaneous Slip/Rupture/Rake Vars + asp_taper_fac: 0.05 + extend_fac: null + flen_max: null + fwid_max: null + moment_fraction: null + perturb_subfault_location: true + rand_rake_degs: 60.0 + rtime1_depth: 2.0 + rtime1_depth_range: 1.0 + rtime1_scor: 0.8 + rtime1_sigma: 0.85 + rtime2_scor: 0.5 + rtime2slip_exp: 0.5 + rtime_rand: null + set_rake: null + svr_wt: 0.0 + target_savg: null + use_Mw: true + # Aseismic & Segment Settings + aseis_flag: false + aseis_smooth: false + aseis_dep: 10.0 + aseis_fac: null + xshift: 0.0 + yshift: 0.0 # The following parameters are only used for the point source approximation. point_source_params: # Valid options for the slip time function (stype) are: diff --git a/workflow/realisations.py b/workflow/realisations.py index 080c4663..2889a4eb 100644 --- a/workflow/realisations.py +++ b/workflow/realisations.py @@ -399,15 +399,206 @@ class SRFConfig(RealisationConfiguration): risetime_coef: float """Risetime scaling coefficient.""" - ymag_exp: float | None = None + ymag_exp: float | None """Corner magnitude exponent for along-strike slip correlation length. See genslip_v5.6.2c:1385""" - xmag_exp: float | None = None + xmag_exp: float | None """Corner magnitude exponent for down-dip slip correlation length. See genslip_v5.6.2c:1385""" - kx_corner: float | None = None + kx_corner: float | None """Corner wavenumber for along-strike slip correlation length. See genslip_v5.6.2c:1385""" - ky_corner: float | None = None + ky_corner: float | None """Corner wavenumber for down-dip slip correlation length. See genslip_v5.6.2c:1385""" + # Rise time and source time function values + beta_asp: float + """Asperity beta parameter.""" + beta_deep: float + """Deep beta parameter for rise time.""" + beta_mid: float + """Mid-depth beta parameter for rise time.""" + beta_mid_depth: float + """Mid-depth level for beta depth scaling.""" + beta_mid_depth_range: float + """Mid-depth range for beta depth scaling.""" + beta_shal: float + """Shallow beta parameter for rise time.""" + beta_shal_depth: float + """Shallow depth level for beta depth scaling.""" + beta_shal_depth_range: float + """Shallow depth range for beta depth scaling.""" + beta_subevt: float + """Sub-event beta parameter for rise time.""" + deep_risetimedep: float + """Deep rise time depth dependency level.""" + deep_risetimedep_range: float + """Deep rise time depth dependency range.""" + deep_risetimefac: float + """Deep rise time scaling factor.""" + risetimedep: float + """Rise time depth dependency level.""" + risetimedep_range: float + """Rise time depth dependency range.""" + risetimefac: float + """Rise time scaling factor.""" + rt_rand: float + """Rise time randomness factor (0.0 = deterministic).""" + rt_scalefac: float + """Rise time scale factor.""" + stype: str | None + """Slip time function type for genslip (None = use genslip default).""" + + # Hybrid Correlation Length (hyb_corlen) Parameters + hyb_corlen_deep_wt_end: float + """Hybrid correlation length deep weight end.""" + hyb_corlen_deep_wt_start: float + """Hybrid correlation length deep weight start.""" + hyb_corlen_dep: float + """Hybrid correlation length depth scaling level.""" + hyb_corlen_dep_range: float + """Hybrid correlation length depth scaling range.""" + hyb_corlen_fac: float + """Hybrid correlation length factor.""" + hyb_corlen_flag: bool + """Enable hybrid correlation length model.""" + hyb_corlen_kmodel: schemas.KModel + """Hybrid correlation length k-model index. Stored as float for schema compatibility.""" + hyb_corlen_shal_wt_end: float + """Hybrid correlation length shallow weight end.""" + hyb_corlen_shal_wt_start: float + """Hybrid correlation length shallow weight start.""" + hyb_corlen_side_taper: float + """Hybrid correlation length side taper.""" + + # Rupture Velocity & Fault Dimensions + fdrup_scale_slip: bool + """Scale slip by fault rupture area.""" + fdrup_time: bool + """Use fault rupture time.""" + rupture_delay: float + """Delay (in seconds) before rupture starts.""" + rvfmax: float + """Maximum rupture velocity fraction.""" + rvfmin: float + """Minimum rupture velocity fraction.""" + # Tapering & Slip Level Adjustments + truncate_zero_slip: bool + """Truncate subfaults with zero slip.""" + slip_water_level: float | None + """Water level for slip distribution (None = disabled).""" + rake_sigma: float + """Standard deviation of rake perturbation (degrees).""" + fractal_rake: bool + """Use fractal rake distribution.""" + + # Time Shift Factors (tsfac) + tsfac1_scor: float + """Time shift factor 1 spatial correlation.""" + tsfac1_sigma: float + """Time shift factor 1 sigma.""" + tsfac2_lambda_max: float + """Time shift factor 2 maximum wavelength.""" + tsfac2_lambda_min: float | None + """Time shift factor 2 minimum wavelength (None = disabled).""" + tsfac2_scor: float + """Time shift factor 2 spatial correlation.""" + tsfac2_sigma: float + """Time shift factor 2 sigma.""" + tsfac_bzero: float + """Time shift factor b0 coefficient.""" + tsfac_coef: float + """Time shift factor coefficient.""" + tsfac_main: float | None + """Main time shift factor (None = use computed value).""" + tsfac_slope: float + """Time shift factor slope.""" + + # Kinematic Models & Corner Frequencies + circular_average: bool + """Use circular average for slip correlation.""" + kmodel: schemas.KModel + """Kinematic model index.""" + kord: int + """Wavenumber filter order.""" + magC: float + """Magnitude corner frequency coefficient.""" + mag_area_Acoef: float | None + """Magnitude-area scaling A coefficient (None = disabled).""" + mag_area_Bcoef: float | None + """Magnitude-area scaling B coefficient (None = disabled).""" + mai_wt: float + """MAI model weight.""" + modified_corners: bool + """Use modified corner frequencies.""" + somerville_wt: float + """Somerville model weight.""" + stretch_kcorner: bool + """Stretch corner wavenumber.""" + use_gaus: bool + """Use Gaussian slip distribution.""" + use_median_mag: bool + """Use median magnitude for scaling.""" + + # Roughness & Wavelength Limits + lambda_max: float | None + """Maximum wavelength for slip correlation (None = no limit).""" + lambda_min: float | None + """Minimum wavelength for slip correlation (None = no limit).""" + wavelength_max: float | None + """Maximum wavelength limit (None = no limit).""" + wavelength_min: float | None + """Minimum wavelength limit (None = no limit).""" + + # Miscellaneous Slip/Rupture/Rake Vars + asp_taper_fac: float + """Asperity taper factor.""" + extend_fac: float | None + """Fault extension factor (None = disabled).""" + flen_max: float | None + """Maximum fault length (None = no limit).""" + fwid_max: float | None + """Maximum fault width (None = no limit).""" + moment_fraction: float | None + """Fraction of seismic moment (None = use all).""" + perturb_subfault_location: bool + """Perturb subfault locations.""" + rand_rake_degs: float + """Range of random rake perturbation (degrees).""" + rtime1_depth: float + """Rise time 1 depth level.""" + rtime1_depth_range: float + """Rise time 1 depth range.""" + rtime1_scor: float + """Rise time 1 spatial correlation.""" + rtime1_sigma: float + """Rise time 1 sigma.""" + rtime2_scor: float + """Rise time 2 spatial correlation.""" + rtime2slip_exp: float + """Rise time 2 slip exponent.""" + rtime_rand: float | None + """Rise time randomness (None = disabled).""" + set_rake: float | None + """Fixed rake angle (None = use fault rake).""" + svr_wt: float + """SVR model weight.""" + target_savg: float | None + """Target average slip (None = compute from magnitude).""" + use_Mw: bool + """Use moment magnitude for scaling.""" + + # Aseismic & Segment Settings + aseis_flag: bool + """Enable aseismic zone correction.""" + aseis_smooth: bool + """Enable smoothing of aseismic zones.""" + aseis_dep: float + """Aseismic zone depth.""" + aseis_fac: float | None + """Aseismic zone factor (None = disabled).""" + xshift: float + """Along-strike shift of slip distribution.""" + yshift: float + """Down-dip shift of slip distribution.""" + def to_dict(self) -> dict[str, Any]: """ Convert the object to a dictionary representation. @@ -736,6 +927,8 @@ class RuptureVelocity(RealisationConfiguration): """Rupture velocity factor (rupture : Vs)""" rvfrac_shal: float """Rupture velocity at shallow depths""" + rvfrac_slip_sig: float | None + """Rupture velocity fraction slip sigma (None = disabled).""" rvfrac_deep: float """Rupture velocity at depth""" shallow_depth: float diff --git a/workflow/schemas.py b/workflow/schemas.py index 0c55f9a7..53a6a870 100644 --- a/workflow/schemas.py +++ b/workflow/schemas.py @@ -7,7 +7,7 @@ """ import dataclasses -from enum import StrEnum +from enum import StrEnum, IntEnum import numpy as np import pandas as pd @@ -31,6 +31,14 @@ class Stype(StrEnum): cos = "cos" seki = "seki" +class KModel(IntEnum): + SOMERVILLE = 1 + MAI = 2 + FRANKEL = 3 + MAI_SOMERVILLE = 4 + SUZUKI = 5 + INPUT_CORNERS = -1 + @dataclasses.dataclass class PointSourceParams: @@ -389,6 +397,11 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: Literal("rvfrac_deep", description="Rupture velocity at depth"): And( NUMBER, _is_positive ), + Literal( + "rvfrac_slip_sig", + description="Rupture velocity fraction slip sigma (null = disabled)."): Or( + NUMBER, None + ), Literal( "shallow_depth", description="Shallow transition depth.", @@ -471,6 +484,359 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: "risetime_coef", description="Risetime scaling coefficient.", ): And(NUMBER, _is_positive), + # Rise time and source time function values + Literal("beta_asp", description="Asperity beta parameter."): And( + NUMBER, _is_positive + ), + Literal( + "beta_deep", description="Deep beta parameter for rise time." + ): And(NUMBER, _is_positive), + Literal( + "beta_mid", description="Mid-depth beta parameter for rise time." + ): And(NUMBER, _is_positive), + Literal( + "beta_mid_depth", + description="Mid-depth level for beta depth scaling.", + ): And(NUMBER, _is_positive), + Literal( + "beta_mid_depth_range", + description="Mid-depth range for beta depth scaling.", + ): And(NUMBER, _is_positive), + Literal( + "beta_shal", description="Shallow beta parameter for rise time." + ): And(NUMBER, _is_positive), + Literal( + "beta_shal_depth", + description="Shallow depth level for beta depth scaling.", + ): And(NUMBER, _is_positive), + Literal( + "beta_shal_depth_range", + description="Shallow depth range for beta depth scaling.", + ): And(NUMBER, _is_positive), + Literal( + "beta_subevt", description="Sub-event beta parameter for rise time." + ): And(NUMBER, _is_positive), + Literal( + "deep_risetimedep", + description="Deep rise time depth dependency level.", + ): And(NUMBER, _is_positive), + Literal( + "deep_risetimedep_range", + description="Deep rise time depth dependency range.", + ): And(NUMBER, _is_positive), + Literal( + "deep_risetimefac", + description="Deep rise time scaling factor.", + ): And(NUMBER, _is_positive), + Literal( + "risetimedep", + description="Rise time depth dependency level.", + ): And(NUMBER, _is_positive), + Literal( + "risetimedep_range", + description="Rise time depth dependency range.", + ): And(NUMBER, _is_positive), + Literal( + "risetimefac", + description="Rise time scaling factor.", + ): And(NUMBER, _is_positive), + Literal( + "rt_rand", + description="Rise time randomness factor (0.0 = deterministic).", + ): And(NUMBER, _is_non_negative), + Literal( + "rt_scalefac", + description="Rise time scale factor.", + ): And(NUMBER, _is_positive), + Literal( + "stype", + description="Slip time function type for genslip (null = use genslip default).", + ): Or(Use(Stype),None), + # Hybrid Correlation Length (hyb_corlen) Parameters + Literal( + "hyb_corlen_deep_wt_end", + description="Hybrid correlation length deep weight end.", + ): NUMBER, + Literal( + "hyb_corlen_deep_wt_start", + description="Hybrid correlation length deep weight start.", + ): NUMBER, + Literal( + "hyb_corlen_dep", + description="Hybrid correlation length depth scaling level.", + ): And(NUMBER, _is_positive), + Literal( + "hyb_corlen_dep_range", + description="Hybrid correlation length depth scaling range.", + ): And(NUMBER, _is_positive), + Literal( + "hyb_corlen_fac", + description="Hybrid correlation length factor.", + ): And(NUMBER, _is_positive), + Literal( + "hyb_corlen_flag", + description="Enable hybrid correlation length model.", + ): bool, + Literal( + "hyb_corlen_kmodel", + description="Hybrid correlation length k-model index.", + ): And(NUMBER, _is_positive), + Literal( + "hyb_corlen_shal_wt_end", + description="Hybrid correlation length shallow weight end.", + ): NUMBER, + Literal( + "hyb_corlen_shal_wt_start", + description="Hybrid correlation length shallow weight start.", + ): NUMBER, + Literal( + "hyb_corlen_side_taper", + description="Hybrid correlation length side taper.", + ): And(NUMBER, _is_non_negative), + # Rupture Velocity & Fault Dimensions + Literal( + "fdrup_scale_slip", + description="Scale slip by fault rupture area.", + ): bool, + Literal( + "fdrup_time", + description="Use fault rupture time.", + ): bool, + Literal( + "rupture_delay", + description="Delay (in seconds) before rupture starts.", + ): And(NUMBER, _is_non_negative), + Literal( + "rvfmax", + description="Maximum rupture velocity fraction.", + ): And(NUMBER, _is_positive), + Literal( + "rvfmin", + description="Minimum rupture velocity fraction.", + ): And(NUMBER, _is_positive), + + # Tapering & Slip Level Adjustments + Literal( + "truncate_zero_slip", + description="Truncate subfaults with zero slip.", + ): bool, + Literal( + "slip_water_level", + description="Water level for slip distribution (null = disabled).", + ): Or(NUMBER, None), + Literal( + "rake_sigma", + description="Standard deviation of rake perturbation (degrees).", + ): And(NUMBER, _is_positive), + Literal( + "fractal_rake", + description="Use fractal rake distribution.", + ): bool, + # Time Shift Factors (tsfac) + Literal( + "tsfac1_scor", + description="Time shift factor 1 spatial correlation.", + ): NUMBER, + Literal( + "tsfac1_sigma", + description="Time shift factor 1 sigma.", + ): And(NUMBER, _is_positive), + Literal( + "tsfac2_lambda_max", + description="Time shift factor 2 maximum wavelength.", + ): NUMBER, + Literal( + "tsfac2_lambda_min", + description="Time shift factor 2 minimum wavelength (null = disabled).", + ): Or(NUMBER, None), + Literal( + "tsfac2_scor", + description="Time shift factor 2 spatial correlation.", + ): NUMBER, + Literal( + "tsfac2_sigma", + description="Time shift factor 2 sigma.", + ): And(NUMBER, _is_positive), + Literal( + "tsfac_bzero", + description="Time shift factor b0 coefficient.", + ): NUMBER, + Literal( + "tsfac_coef", + description="Time shift factor coefficient.", + ): NUMBER, + Literal( + "tsfac_main", + description="Main time shift factor (null = use computed value).", + ): Or(NUMBER, None), + Literal( + "tsfac_slope", + description="Time shift factor slope.", + ): NUMBER, + # Kinematic Models & Corner Frequencies + Literal( + "circular_average", + description="Use circular average for slip correlation.", + ): bool, + Literal( + "kmodel", + description="Kinematic model index: 1=SOMERVILLE, 2=MAI, 3=FRANKEL, 4=MAI_SOMERVILLE, 5=SUZUKI, -1=INPUT_CORNERS", + ): Use(KModel), + Literal( + "kord", + description="Wavenumber filter order.", + ): And(int, _is_positive), + Literal( + "magC", + description="Magnitude corner frequency coefficient.", + ): NUMBER, + Literal( + "mag_area_Acoef", + description="Magnitude-area scaling A coefficient (null = disabled).", + ): Or(NUMBER, None), + Literal( + "mag_area_Bcoef", + description="Magnitude-area scaling B coefficient (null = disabled).", + ): Or(NUMBER, None), + Literal( + "mai_wt", + description="MAI model weight.", + ): And(NUMBER, _is_proportion), + Literal( + "modified_corners", + description="Use modified corner frequencies.", + ): bool, + Literal( + "somerville_wt", + description="Somerville model weight.", + ): And(NUMBER, _is_proportion), + Literal( + "stretch_kcorner", + description="Stretch corner wavenumber.", + ): bool, + Literal( + "use_gaus", + description="Use Gaussian slip distribution.", + ): bool, + Literal( + "use_median_mag", + description="Use median magnitude for scaling.", + ): bool, + # Roughness & Wavelength Limits + Literal( + "lambda_max", + description="Maximum wavelength for slip correlation (null = no limit).", + ): Or(NUMBER, None), + Literal( + "lambda_min", + description="Minimum wavelength for slip correlation (null = no limit).", + ): Or(NUMBER, None), + Literal( + "wavelength_max", + description="Maximum wavelength limit (null = no limit).", + ): Or(NUMBER, None), + Literal( + "wavelength_min", + description="Minimum wavelength limit (null = no limit).", + ): Or(NUMBER, None), + # Miscellaneous Slip/Rupture/Rake Vars + Literal( + "asp_taper_fac", + description="Asperity taper factor.", + ): And(NUMBER, _is_non_negative), + Literal( + "extend_fac", + description="Fault extension factor (null = disabled).", + ): Or(NUMBER, None), + Literal( + "flen_max", + description="Maximum fault length (null = no limit).", + ): Or(NUMBER, None), + Literal( + "fwid_max", + description="Maximum fault width (null = no limit).", + ): Or(NUMBER, None), + Literal( + "moment_fraction", + description="Fraction of seismic moment (null = use all).", + ): Or(NUMBER, None), + Literal( + "perturb_subfault_location", + description="Perturb subfault locations.", + ): bool, + Literal( + "rand_rake_degs", + description="Range of random rake perturbation (degrees).", + ): And(NUMBER, _is_non_negative), + Literal( + "rtime1_depth", + description="Rise time 1 depth level.", + ): And(NUMBER, _is_positive), + Literal( + "rtime1_depth_range", + description="Rise time 1 depth range.", + ): And(NUMBER, _is_positive), + Literal( + "rtime1_scor", + description="Rise time 1 spatial correlation.", + ): NUMBER, + Literal( + "rtime1_sigma", + description="Rise time 1 sigma.", + ): And(NUMBER, _is_positive), + Literal( + "rtime2_scor", + description="Rise time 2 spatial correlation.", + ): NUMBER, + Literal( + "rtime2slip_exp", + description="Rise time 2 slip exponent.", + ): NUMBER, + Literal( + "rtime_rand", + description="Rise time randomness (null = disabled).", + ): Or(NUMBER, None), + Literal( + "set_rake", + description="Fixed rake angle (null = use fault rake).", + ): Or(NUMBER, None), + Literal( + "svr_wt", + description="SVR model weight.", + ): And(NUMBER, _is_non_negative), + Literal( + "target_savg", + description="Target average slip (null = compute from magnitude).", + ): Or(NUMBER, None), + Literal( + "use_Mw", + description="Use moment magnitude for scaling.", + ): bool, + # Aseismic & Segment Settings + Literal( + "aseis_flag", + description="Enable aseismic zone correction.", + ): bool, + Literal( + "aseis_smooth", + description="Enable smoothing of aseismic zones.", + ): bool, + Literal( + "aseis_dep", + description="Aseismic zone depth.", + ): And(NUMBER, _is_positive), + Literal( + "aseis_fac", + description="Aseismic zone factor (null = disabled).", + ): Or(NUMBER, None), + Literal( + "xshift", + description="Along-strike shift of slip distribution.", + ): NUMBER, + Literal( + "yshift", + description="Down-dip shift of slip distribution.", + ): NUMBER, } ) diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 10c6754c..e5729e50 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -37,12 +37,14 @@ """ import dataclasses +from enum import Enum import functools import multiprocessing import re import shutil import subprocess from collections.abc import Iterable +from enum import Enum from pathlib import Path from typing import Annotated @@ -479,6 +481,10 @@ def _build_genslip_command( f"deep_vrup_dep={rupture_velocity.deep_depth}", f"deep_vrup_deprange={rupture_velocity.deep_transition_range}", ] + + if rupture_velocity.rvfrac_slip_sig is not None: + cmd.append(f"rvfrac_slip_sig={rupture_velocity.rvfrac_slip_sig}") + skipped_fields = {"point_source_params"} for field in dataclasses.fields(srf_config): key = field.name @@ -490,6 +496,8 @@ def _build_genslip_command( serialised_value = ",".join([str(v) for v in value]) elif isinstance(value, bool): serialised_value = "1" if value else "0" + elif isinstance(value, Enum): + serialised_value = str(value.value) elif dataclasses.is_dataclass(value): continue else: