From 3dcde70f683010e8a0d2a67e85c34ad9aa452d0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:10:27 +0000 Subject: [PATCH 1/9] Initial plan From c6744a3b2487e263f051c0445dd9001962b7e266 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:23:19 +0000 Subject: [PATCH 2/9] Add remaining genslip parameters to defaults, schema, SRFConfig, and tests Co-authored-by: lispandfound <12835929+lispandfound@users.noreply.github.com> --- tests/test_realisation.py | 182 +++++++++ tests/test_realisation_to_srf.py | 162 ++++++++ .../default_parameters/root/defaults.yaml | 100 +++++ workflow/realisations.py | 200 ++++++++++ workflow/schemas.py | 368 ++++++++++++++++++ 5 files changed, 1012 insertions(+) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index 89a2319..a4dfc9b 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -135,6 +135,97 @@ 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=5.0, + 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, + rvfrac_slip_sig=None, + 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.0, + kord=4.0, + 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, + roughnessfile=None, + wavelength_max=None, + wavelength_min=None, + asp_taper_fac=0.05, + extend_fac=None, + flen_max=None, + fwid_max=None, + init_slip_file=None, + moment_fraction=None, + perturb_subfault_location=True, + rand_rake_degs=60.0, + read_slip_file=False, + 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 +265,97 @@ 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": 5.0, + "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, + "rvfrac_slip_sig": None, + "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.0, + "kord": 4.0, + "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, + "roughnessfile": None, + "wavelength_max": None, + "wavelength_min": None, + "asp_taper_fac": 0.05, + "extend_fac": None, + "flen_max": None, + "fwid_max": None, + "init_slip_file": None, + "moment_fraction": None, + "perturb_subfault_location": True, + "rand_rake_degs": 60.0, + "read_slip_file": False, + "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 c5632cd..16ef7b2 100644 --- a/tests/test_realisation_to_srf.py +++ b/tests/test_realisation_to_srf.py @@ -28,6 +28,97 @@ 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=5.0, + 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, + rvfrac_slip_sig=None, + 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.0, + kord=4.0, + 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, + roughnessfile=None, + wavelength_max=None, + wavelength_min=None, + asp_taper_fac=0.05, + extend_fac=None, + flen_max=None, + fwid_max=None, + init_slip_file=None, + moment_fraction=None, + perturb_subfault_location=True, + rand_rake_degs=60.0, + read_slip_file=False, + 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") @@ -94,4 +185,75 @@ 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.0", + "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.0", + "kord=4.0", + "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", + "read_slip_file=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 b5015d0..5af670b 100644 --- a/workflow/default_parameters/root/defaults.yaml +++ b/workflow/default_parameters/root/defaults.yaml @@ -118,6 +118,106 @@ 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 + rvfrac_slip_sig: null + # 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 + roughnessfile: 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 + init_slip_file: null + moment_fraction: null + perturb_subfault_location: true + rand_rake_degs: 60.0 + read_slip_file: false + 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 080c466..ae0097d 100644 --- a/workflow/realisations.py +++ b/workflow/realisations.py @@ -408,6 +408,206 @@ class SRFConfig(RealisationConfiguration): ky_corner: float | None = 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 = 0.3 + """Asperity beta parameter.""" + beta_deep: float = 0.13 + """Deep beta parameter for rise time.""" + beta_mid: float = 0.13 + """Mid-depth beta parameter for rise time.""" + beta_mid_depth: float = 6.5 + """Mid-depth level for beta depth scaling.""" + beta_mid_depth_range: float = 1.5 + """Mid-depth range for beta depth scaling.""" + beta_shal: float = 0.5 + """Shallow beta parameter for rise time.""" + beta_shal_depth: float = 2.0 + """Shallow depth level for beta depth scaling.""" + beta_shal_depth_range: float = 1.0 + """Shallow depth range for beta depth scaling.""" + beta_subevt: float = 0.1 + """Sub-event beta parameter for rise time.""" + deep_risetimedep: float = 17.5 + """Deep rise time depth dependency level.""" + deep_risetimedep_range: float = 2.5 + """Deep rise time depth dependency range.""" + deep_risetimefac: float = 2.0 + """Deep rise time scaling factor.""" + risetimedep: float = 6.5 + """Rise time depth dependency level.""" + risetimedep_range: float = 1.5 + """Rise time depth dependency range.""" + risetimefac: float = 2.0 + """Rise time scaling factor.""" + rt_rand: float = 0.0 + """Rise time randomness factor (0.0 = deterministic).""" + rt_scalefac: float = 1.0 + """Rise time scale factor.""" + stype: str | None = None + """Slip time function type for genslip (None = use genslip default).""" + + # Hybrid Correlation Length (hyb_corlen) Parameters + hyb_corlen_deep_wt_end: float = 1.0 + """Hybrid correlation length deep weight end.""" + hyb_corlen_deep_wt_start: float = 0.0 + """Hybrid correlation length deep weight start.""" + hyb_corlen_dep: float = 6.5 + """Hybrid correlation length depth scaling level.""" + hyb_corlen_dep_range: float = 1.5 + """Hybrid correlation length depth scaling range.""" + hyb_corlen_fac: float = 2.0 + """Hybrid correlation length factor.""" + hyb_corlen_flag: bool = False + """Enable hybrid correlation length model.""" + hyb_corlen_kmodel: float = 5.0 + """Hybrid correlation length k-model index. Stored as float for schema compatibility.""" + hyb_corlen_shal_wt_end: float = 0.0 + """Hybrid correlation length shallow weight end.""" + hyb_corlen_shal_wt_start: float = 1.0 + """Hybrid correlation length shallow weight start.""" + hyb_corlen_side_taper: float = 0.08 + """Hybrid correlation length side taper.""" + + # Rupture Velocity & Fault Dimensions + fdrup_scale_slip: bool = False + """Scale slip by fault rupture area.""" + fdrup_time: bool = False + """Use fault rupture time.""" + rupture_delay: float = 0.0 + """Delay (in seconds) before rupture starts.""" + rvfmax: float = 1.414 + """Maximum rupture velocity fraction.""" + rvfmin: float = 0.25 + """Minimum rupture velocity fraction.""" + rvfrac_slip_sig: float | None = None + """Rupture velocity fraction slip sigma (None = disabled).""" + + # Tapering & Slip Level Adjustments + truncate_zero_slip: bool = True + """Truncate subfaults with zero slip.""" + slip_water_level: float | None = None + """Water level for slip distribution (None = disabled).""" + rake_sigma: float = 15.0 + """Standard deviation of rake perturbation (degrees).""" + fractal_rake: bool = False + """Use fractal rake distribution.""" + + # Time Shift Factors (tsfac) + tsfac1_scor: float = 0.8 + """Time shift factor 1 spatial correlation.""" + tsfac1_sigma: float = 1.0 + """Time shift factor 1 sigma.""" + tsfac2_lambda_max: float = 5.0 + """Time shift factor 2 maximum wavelength.""" + tsfac2_lambda_min: float | None = None + """Time shift factor 2 minimum wavelength (None = disabled).""" + tsfac2_scor: float = 0.5 + """Time shift factor 2 spatial correlation.""" + tsfac2_sigma: float = 1.0 + """Time shift factor 2 sigma.""" + tsfac_bzero: float = -0.1 + """Time shift factor b0 coefficient.""" + tsfac_coef: float = 1.1 + """Time shift factor coefficient.""" + tsfac_main: float | None = None + """Main time shift factor (None = use computed value).""" + tsfac_slope: float = -0.5 + """Time shift factor slope.""" + + # Kinematic Models & Corner Frequencies + circular_average: bool = False + """Use circular average for slip correlation.""" + kmodel: float = 2.0 + """Kinematic model index: 1=SOMERVILLE_FLAG, 2=MAI_FLAG, -1=INPUT_CORNERS_FLAG. Stored as float for schema compatibility.""" + kord: float = 4.0 + """Wavenumber filter order. Stored as float for schema compatibility.""" + magC: float = 6.3 + """Magnitude corner frequency coefficient.""" + mag_area_Acoef: float | None = None + """Magnitude-area scaling A coefficient (None = disabled).""" + mag_area_Bcoef: float | None = None + """Magnitude-area scaling B coefficient (None = disabled).""" + mai_wt: float = 0.5 + """MAI model weight.""" + modified_corners: bool = False + """Use modified corner frequencies.""" + somerville_wt: float = 0.5 + """Somerville model weight.""" + stretch_kcorner: bool = False + """Stretch corner wavenumber.""" + use_gaus: bool = True + """Use Gaussian slip distribution.""" + use_median_mag: bool = False + """Use median magnitude for scaling.""" + + # Roughness & Wavelength Limits + lambda_max: float | None = None + """Maximum wavelength for slip correlation (None = no limit).""" + lambda_min: float | None = None + """Minimum wavelength for slip correlation (None = no limit).""" + roughnessfile: str | None = None + """Path to roughness file (None = no file).""" + wavelength_max: float | None = None + """Maximum wavelength limit (None = no limit).""" + wavelength_min: float | None = None + """Minimum wavelength limit (None = no limit).""" + + # Miscellaneous Slip/Rupture/Rake Vars + asp_taper_fac: float = 0.05 + """Asperity taper factor.""" + extend_fac: float | None = None + """Fault extension factor (None = disabled).""" + flen_max: float | None = None + """Maximum fault length (None = no limit).""" + fwid_max: float | None = None + """Maximum fault width (None = no limit).""" + init_slip_file: str | None = None + """Path to initial slip file (None = no file).""" + moment_fraction: float | None = None + """Fraction of seismic moment (None = use all).""" + perturb_subfault_location: bool = True + """Perturb subfault locations.""" + rand_rake_degs: float = 60.0 + """Range of random rake perturbation (degrees).""" + read_slip_file: bool = False + """Read slip distribution from file.""" + rtime1_depth: float = 2.0 + """Rise time 1 depth level.""" + rtime1_depth_range: float = 1.0 + """Rise time 1 depth range.""" + rtime1_scor: float = 0.8 + """Rise time 1 spatial correlation.""" + rtime1_sigma: float = 0.85 + """Rise time 1 sigma.""" + rtime2_scor: float = 0.5 + """Rise time 2 spatial correlation.""" + rtime2slip_exp: float = 0.5 + """Rise time 2 slip exponent.""" + rtime_rand: float | None = None + """Rise time randomness (None = disabled).""" + set_rake: float | None = None + """Fixed rake angle (None = use fault rake).""" + svr_wt: float = 0.0 + """SVR model weight.""" + target_savg: float | None = None + """Target average slip (None = compute from magnitude).""" + use_Mw: bool = True + """Use moment magnitude for scaling.""" + + # Aseismic & Segment Settings + aseis_flag: bool = False + """Enable aseismic zone correction.""" + aseis_smooth: bool = False + """Enable smoothing of aseismic zones.""" + aseis_dep: float = 10.0 + """Aseismic zone depth.""" + aseis_fac: float | None = None + """Aseismic zone factor (None = disabled).""" + xshift: float = 0.0 + """Along-strike shift of slip distribution.""" + yshift: float = 0.0 + """Down-dip shift of slip distribution.""" + def to_dict(self) -> dict[str, Any]: """ Convert the object to a dictionary representation. diff --git a/workflow/schemas.py b/workflow/schemas.py index 0c55f9a..ee944b6 100644 --- a/workflow/schemas.py +++ b/workflow/schemas.py @@ -471,6 +471,374 @@ 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(str, 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), + Literal( + "rvfrac_slip_sig", + description="Rupture velocity fraction slip sigma (null = disabled).", + ): Or(NUMBER, None), + # 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_FLAG, 2=MAI_FLAG, -1=INPUT_CORNERS_FLAG.", + ): And(NUMBER, _is_positive), + Literal( + "kord", + description="Wavenumber filter order (integer stored as float for schema compatibility).", + ): And(NUMBER, _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( + "roughnessfile", + description="Path to roughness file (null = no file).", + ): Or(str, 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( + "init_slip_file", + description="Path to initial slip file (null = no file).", + ): Or(str, 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( + "read_slip_file", + description="Read slip distribution from file.", + ): bool, + 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, } ) From 68341473abb3d017e94dcf430b1f00d651cf8ba7 Mon Sep 17 00:00:00 2001 From: Sung Bae Date: Wed, 4 Mar 2026 16:37:42 +1300 Subject: [PATCH 3/9] Apply suggestion from @lispandfound Co-authored-by: Jake Faulkner --- tests/test_realisation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index a4dfc9b..24618cb 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -159,7 +159,7 @@ def test_srf_config_example(tmp_path: Path) -> None: hyb_corlen_dep_range=1.5, hyb_corlen_fac=2.0, hyb_corlen_flag=False, - hyb_corlen_kmodel=5.0, + hyb_corlen_kmodel=KModel.SUZUKI, hyb_corlen_shal_wt_end=0.0, hyb_corlen_shal_wt_start=1.0, hyb_corlen_side_taper=0.08, From 5968e3ed5e8196ff669782680204482b8669eb2c Mon Sep 17 00:00:00 2001 From: sungeunbae Date: Wed, 4 Mar 2026 17:03:29 +1300 Subject: [PATCH 4/9] Updated handlings of KModel, kord, roughtnessfile, init_slip_file, read_slip_file, rvfrac_slip_sig --- tests/test_realisation.py | 11 +- tests/test_realisation_to_srf.py | 15 +- .../default_parameters/root/defaults.yaml | 5 +- workflow/realisations.py | 195 +++++++++--------- workflow/schemas.py | 40 ++-- 5 files changed, 124 insertions(+), 142 deletions(-) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index a4dfc9b..9191659 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -159,7 +159,7 @@ def test_srf_config_example(tmp_path: Path) -> None: hyb_corlen_dep_range=1.5, hyb_corlen_fac=2.0, hyb_corlen_flag=False, - hyb_corlen_kmodel=5.0, + 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, @@ -184,8 +184,8 @@ def test_srf_config_example(tmp_path: Path) -> None: tsfac_main=None, tsfac_slope=-0.5, circular_average=False, - kmodel=2.0, - kord=4.0, + kmodel=schemas.KModel.MAI, + kord=4, magC=6.3, mag_area_Acoef=None, mag_area_Bcoef=None, @@ -197,18 +197,15 @@ def test_srf_config_example(tmp_path: Path) -> None: use_median_mag=False, lambda_max=None, lambda_min=None, - roughnessfile=None, wavelength_max=None, wavelength_min=None, asp_taper_fac=0.05, extend_fac=None, flen_max=None, fwid_max=None, - init_slip_file=None, moment_fraction=None, perturb_subfault_location=True, rand_rake_degs=60.0, - read_slip_file=False, rtime1_depth=2.0, rtime1_depth_range=1.0, rtime1_scor=0.8, @@ -289,7 +286,7 @@ def test_srf_config_example(tmp_path: Path) -> None: "hyb_corlen_dep_range": 1.5, "hyb_corlen_fac": 2.0, "hyb_corlen_flag": False, - "hyb_corlen_kmodel": 5.0, + "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, diff --git a/tests/test_realisation_to_srf.py b/tests/test_realisation_to_srf.py index 16ef7b2..5dcdd7d 100644 --- a/tests/test_realisation_to_srf.py +++ b/tests/test_realisation_to_srf.py @@ -52,7 +52,7 @@ def test_build_genslip_command_static_args() -> None: hyb_corlen_dep_range=1.5, hyb_corlen_fac=2.0, hyb_corlen_flag=False, - hyb_corlen_kmodel=5.0, + 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, @@ -77,8 +77,8 @@ def test_build_genslip_command_static_args() -> None: tsfac_main=None, tsfac_slope=-0.5, circular_average=False, - kmodel=2.0, - kord=4.0, + kmodel=schemas.KModel.MAI, + kord=4, magC=6.3, mag_area_Acoef=None, mag_area_Bcoef=None, @@ -90,18 +90,15 @@ def test_build_genslip_command_static_args() -> None: use_median_mag=False, lambda_max=None, lambda_min=None, - roughnessfile=None, wavelength_max=None, wavelength_min=None, asp_taper_fac=0.05, extend_fac=None, flen_max=None, fwid_max=None, - init_slip_file=None, moment_fraction=None, perturb_subfault_location=True, rand_rake_degs=60.0, - read_slip_file=False, rtime1_depth=2.0, rtime1_depth_range=1.0, rtime1_scor=0.8, @@ -209,7 +206,7 @@ def test_build_genslip_command_static_args() -> None: "hyb_corlen_dep_range=1.5", "hyb_corlen_fac=2.0", "hyb_corlen_flag=0", - "hyb_corlen_kmodel=5.0", + "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", @@ -230,8 +227,8 @@ def test_build_genslip_command_static_args() -> None: "tsfac_coef=1.1", "tsfac_slope=-0.5", "circular_average=0", - "kmodel=2.0", - "kord=4.0", + "kmodel=schemas.KModel.MAI", + "kord=4", "magC=6.3", "mai_wt=0.5", "modified_corners=0", diff --git a/workflow/default_parameters/root/defaults.yaml b/workflow/default_parameters/root/defaults.yaml index 5af670b..adc638a 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 @@ -154,7 +155,6 @@ srf: rupture_delay: 0.0 rvfmax: 1.414 rvfmin: 0.25 - rvfrac_slip_sig: null # Tapering & Slip Level Adjustments truncate_zero_slip: true slip_water_level: null @@ -187,7 +187,6 @@ srf: # Roughness & Wavelength Limits lambda_max: null lambda_min: null - roughnessfile: null wavelength_max: null wavelength_min: null # Miscellaneous Slip/Rupture/Rake Vars @@ -195,11 +194,9 @@ srf: extend_fac: null flen_max: null fwid_max: null - init_slip_file: null moment_fraction: null perturb_subfault_location: true rand_rake_degs: 60.0 - read_slip_file: false rtime1_depth: 2.0 rtime1_depth_range: 1.0 rtime1_scor: 0.8 diff --git a/workflow/realisations.py b/workflow/realisations.py index ae0097d..ffe90f0 100644 --- a/workflow/realisations.py +++ b/workflow/realisations.py @@ -399,213 +399,204 @@ 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 = 0.3 + beta_asp: float """Asperity beta parameter.""" - beta_deep: float = 0.13 + beta_deep: float """Deep beta parameter for rise time.""" - beta_mid: float = 0.13 + beta_mid: float """Mid-depth beta parameter for rise time.""" - beta_mid_depth: float = 6.5 + beta_mid_depth: float """Mid-depth level for beta depth scaling.""" - beta_mid_depth_range: float = 1.5 + beta_mid_depth_range: float """Mid-depth range for beta depth scaling.""" - beta_shal: float = 0.5 + beta_shal: float """Shallow beta parameter for rise time.""" - beta_shal_depth: float = 2.0 + beta_shal_depth: float """Shallow depth level for beta depth scaling.""" - beta_shal_depth_range: float = 1.0 + beta_shal_depth_range: float """Shallow depth range for beta depth scaling.""" - beta_subevt: float = 0.1 + beta_subevt: float """Sub-event beta parameter for rise time.""" - deep_risetimedep: float = 17.5 + deep_risetimedep: float """Deep rise time depth dependency level.""" - deep_risetimedep_range: float = 2.5 + deep_risetimedep_range: float """Deep rise time depth dependency range.""" - deep_risetimefac: float = 2.0 + deep_risetimefac: float """Deep rise time scaling factor.""" - risetimedep: float = 6.5 + risetimedep: float """Rise time depth dependency level.""" - risetimedep_range: float = 1.5 + risetimedep_range: float """Rise time depth dependency range.""" - risetimefac: float = 2.0 + risetimefac: float """Rise time scaling factor.""" - rt_rand: float = 0.0 + rt_rand: float """Rise time randomness factor (0.0 = deterministic).""" - rt_scalefac: float = 1.0 + rt_scalefac: float """Rise time scale factor.""" - stype: str | None = None + 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 = 1.0 + hyb_corlen_deep_wt_end: float """Hybrid correlation length deep weight end.""" - hyb_corlen_deep_wt_start: float = 0.0 + hyb_corlen_deep_wt_start: float """Hybrid correlation length deep weight start.""" - hyb_corlen_dep: float = 6.5 + hyb_corlen_dep: float """Hybrid correlation length depth scaling level.""" - hyb_corlen_dep_range: float = 1.5 + hyb_corlen_dep_range: float """Hybrid correlation length depth scaling range.""" - hyb_corlen_fac: float = 2.0 + hyb_corlen_fac: float """Hybrid correlation length factor.""" - hyb_corlen_flag: bool = False + hyb_corlen_flag: bool """Enable hybrid correlation length model.""" - hyb_corlen_kmodel: float = 5.0 + hyb_corlen_kmodel: schemas.KModel """Hybrid correlation length k-model index. Stored as float for schema compatibility.""" - hyb_corlen_shal_wt_end: float = 0.0 + hyb_corlen_shal_wt_end: float """Hybrid correlation length shallow weight end.""" - hyb_corlen_shal_wt_start: float = 1.0 + hyb_corlen_shal_wt_start: float """Hybrid correlation length shallow weight start.""" - hyb_corlen_side_taper: float = 0.08 + hyb_corlen_side_taper: float """Hybrid correlation length side taper.""" # Rupture Velocity & Fault Dimensions - fdrup_scale_slip: bool = False + fdrup_scale_slip: bool """Scale slip by fault rupture area.""" - fdrup_time: bool = False + fdrup_time: bool """Use fault rupture time.""" - rupture_delay: float = 0.0 + rupture_delay: float """Delay (in seconds) before rupture starts.""" - rvfmax: float = 1.414 + rvfmax: float """Maximum rupture velocity fraction.""" - rvfmin: float = 0.25 + rvfmin: float """Minimum rupture velocity fraction.""" - rvfrac_slip_sig: float | None = None - """Rupture velocity fraction slip sigma (None = disabled).""" - # Tapering & Slip Level Adjustments - truncate_zero_slip: bool = True + truncate_zero_slip: bool """Truncate subfaults with zero slip.""" - slip_water_level: float | None = None + slip_water_level: float | None """Water level for slip distribution (None = disabled).""" - rake_sigma: float = 15.0 + rake_sigma: float """Standard deviation of rake perturbation (degrees).""" - fractal_rake: bool = False + fractal_rake: bool """Use fractal rake distribution.""" # Time Shift Factors (tsfac) - tsfac1_scor: float = 0.8 + tsfac1_scor: float """Time shift factor 1 spatial correlation.""" - tsfac1_sigma: float = 1.0 + tsfac1_sigma: float """Time shift factor 1 sigma.""" - tsfac2_lambda_max: float = 5.0 + tsfac2_lambda_max: float """Time shift factor 2 maximum wavelength.""" - tsfac2_lambda_min: float | None = None + tsfac2_lambda_min: float | None """Time shift factor 2 minimum wavelength (None = disabled).""" - tsfac2_scor: float = 0.5 + tsfac2_scor: float """Time shift factor 2 spatial correlation.""" - tsfac2_sigma: float = 1.0 + tsfac2_sigma: float """Time shift factor 2 sigma.""" - tsfac_bzero: float = -0.1 + tsfac_bzero: float """Time shift factor b0 coefficient.""" - tsfac_coef: float = 1.1 + tsfac_coef: float """Time shift factor coefficient.""" - tsfac_main: float | None = None + tsfac_main: float | None """Main time shift factor (None = use computed value).""" - tsfac_slope: float = -0.5 + tsfac_slope: float """Time shift factor slope.""" # Kinematic Models & Corner Frequencies - circular_average: bool = False + circular_average: bool """Use circular average for slip correlation.""" - kmodel: float = 2.0 - """Kinematic model index: 1=SOMERVILLE_FLAG, 2=MAI_FLAG, -1=INPUT_CORNERS_FLAG. Stored as float for schema compatibility.""" - kord: float = 4.0 + kmodel: schemas.KModel + """Kinematic model index.""" + kord: int """Wavenumber filter order. Stored as float for schema compatibility.""" - magC: float = 6.3 + magC: float """Magnitude corner frequency coefficient.""" - mag_area_Acoef: float | None = None + mag_area_Acoef: float | None """Magnitude-area scaling A coefficient (None = disabled).""" - mag_area_Bcoef: float | None = None + mag_area_Bcoef: float | None """Magnitude-area scaling B coefficient (None = disabled).""" - mai_wt: float = 0.5 + mai_wt: float """MAI model weight.""" - modified_corners: bool = False + modified_corners: bool """Use modified corner frequencies.""" - somerville_wt: float = 0.5 + somerville_wt: float """Somerville model weight.""" - stretch_kcorner: bool = False + stretch_kcorner: bool """Stretch corner wavenumber.""" - use_gaus: bool = True + use_gaus: bool """Use Gaussian slip distribution.""" - use_median_mag: bool = False + use_median_mag: bool """Use median magnitude for scaling.""" # Roughness & Wavelength Limits - lambda_max: float | None = None + lambda_max: float | None """Maximum wavelength for slip correlation (None = no limit).""" - lambda_min: float | None = None + lambda_min: float | None """Minimum wavelength for slip correlation (None = no limit).""" - roughnessfile: str | None = None - """Path to roughness file (None = no file).""" - wavelength_max: float | None = None + wavelength_max: float | None """Maximum wavelength limit (None = no limit).""" - wavelength_min: float | None = None + wavelength_min: float | None """Minimum wavelength limit (None = no limit).""" # Miscellaneous Slip/Rupture/Rake Vars - asp_taper_fac: float = 0.05 + asp_taper_fac: float """Asperity taper factor.""" - extend_fac: float | None = None + extend_fac: float | None """Fault extension factor (None = disabled).""" - flen_max: float | None = None + flen_max: float | None """Maximum fault length (None = no limit).""" - fwid_max: float | None = None + fwid_max: float | None """Maximum fault width (None = no limit).""" - init_slip_file: str | None = None - """Path to initial slip file (None = no file).""" - moment_fraction: float | None = None + moment_fraction: float | None """Fraction of seismic moment (None = use all).""" - perturb_subfault_location: bool = True + perturb_subfault_location: bool """Perturb subfault locations.""" - rand_rake_degs: float = 60.0 + rand_rake_degs: float """Range of random rake perturbation (degrees).""" - read_slip_file: bool = False - """Read slip distribution from file.""" - rtime1_depth: float = 2.0 + rtime1_depth: float """Rise time 1 depth level.""" - rtime1_depth_range: float = 1.0 + rtime1_depth_range: float """Rise time 1 depth range.""" - rtime1_scor: float = 0.8 + rtime1_scor: float """Rise time 1 spatial correlation.""" - rtime1_sigma: float = 0.85 + rtime1_sigma: float """Rise time 1 sigma.""" - rtime2_scor: float = 0.5 + rtime2_scor: float """Rise time 2 spatial correlation.""" - rtime2slip_exp: float = 0.5 + rtime2slip_exp: float """Rise time 2 slip exponent.""" - rtime_rand: float | None = None + rtime_rand: float | None """Rise time randomness (None = disabled).""" - set_rake: float | None = None + set_rake: float | None """Fixed rake angle (None = use fault rake).""" - svr_wt: float = 0.0 + svr_wt: float """SVR model weight.""" - target_savg: float | None = None + target_savg: float | None """Target average slip (None = compute from magnitude).""" - use_Mw: bool = True + use_Mw: bool """Use moment magnitude for scaling.""" # Aseismic & Segment Settings - aseis_flag: bool = False + aseis_flag: bool """Enable aseismic zone correction.""" - aseis_smooth: bool = False + aseis_smooth: bool """Enable smoothing of aseismic zones.""" - aseis_dep: float = 10.0 + aseis_dep: float """Aseismic zone depth.""" - aseis_fac: float | None = None + aseis_fac: float | None """Aseismic zone factor (None = disabled).""" - xshift: float = 0.0 + xshift: float """Along-strike shift of slip distribution.""" - yshift: float = 0.0 + yshift: float """Down-dip shift of slip distribution.""" def to_dict(self) -> dict[str, Any]: @@ -936,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 ee944b6..5406054 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.", @@ -538,7 +551,7 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: Literal( "stype", description="Slip time function type for genslip (null = use genslip default).", - ): Or(str, None), + ): Or(Use(Stype),None), # Hybrid Correlation Length (hyb_corlen) Parameters Literal( "hyb_corlen_deep_wt_end", @@ -601,10 +614,7 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: "rvfmin", description="Minimum rupture velocity fraction.", ): And(NUMBER, _is_positive), - Literal( - "rvfrac_slip_sig", - description="Rupture velocity fraction slip sigma (null = disabled).", - ): Or(NUMBER, None), + # Tapering & Slip Level Adjustments Literal( "truncate_zero_slip", @@ -670,12 +680,12 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: ): bool, Literal( "kmodel", - description="Kinematic model index: 1=SOMERVILLE_FLAG, 2=MAI_FLAG, -1=INPUT_CORNERS_FLAG.", - ): And(NUMBER, _is_positive), + 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 (integer stored as float for schema compatibility).", - ): And(NUMBER, _is_positive), + ): And(int, _is_positive), Literal( "magC", description="Magnitude corner frequency coefficient.", @@ -721,10 +731,6 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: "lambda_min", description="Minimum wavelength for slip correlation (null = no limit).", ): Or(NUMBER, None), - Literal( - "roughnessfile", - description="Path to roughness file (null = no file).", - ): Or(str, None), Literal( "wavelength_max", description="Maximum wavelength limit (null = no limit).", @@ -750,10 +756,6 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: "fwid_max", description="Maximum fault width (null = no limit).", ): Or(NUMBER, None), - Literal( - "init_slip_file", - description="Path to initial slip file (null = no file).", - ): Or(str, None), Literal( "moment_fraction", description="Fraction of seismic moment (null = use all).", @@ -766,10 +768,6 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: "rand_rake_degs", description="Range of random rake perturbation (degrees).", ): And(NUMBER, _is_non_negative), - Literal( - "read_slip_file", - description="Read slip distribution from file.", - ): bool, Literal( "rtime1_depth", description="Rise time 1 depth level.", From beee5efb51e450bee68ccf6d69ab46f8d8104397 Mon Sep 17 00:00:00 2001 From: sungeunbae Date: Thu, 5 Mar 2026 11:19:40 +1300 Subject: [PATCH 5/9] kord is integer 4 --- tests/test_realisation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index 9191659..29a80f1 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -312,7 +312,7 @@ def test_srf_config_example(tmp_path: Path) -> None: "tsfac_slope": -0.5, "circular_average": False, "kmodel": 2.0, - "kord": 4.0, + "kord": 4, "magC": 6.3, "mag_area_Acoef": None, "mag_area_Bcoef": None, From 5401095bc0a1020f890f7606354b4964343b8805 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:31:07 +0000 Subject: [PATCH 6/9] Fix enum serialization, remove stale fields, fix kmodel/kord in tests Co-authored-by: lispandfound <12835929+lispandfound@users.noreply.github.com> --- tests/test_realisation.py | 7 +------ tests/test_realisation_to_srf.py | 7 +++---- workflow/realisations.py | 2 +- workflow/schemas.py | 2 +- workflow/scripts/realisation_to_srf.py | 3 +++ 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/test_realisation.py b/tests/test_realisation.py index 29a80f1..57b9ea0 100644 --- a/tests/test_realisation.py +++ b/tests/test_realisation.py @@ -168,7 +168,6 @@ def test_srf_config_example(tmp_path: Path) -> None: rupture_delay=0.0, rvfmax=1.414, rvfmin=0.25, - rvfrac_slip_sig=None, truncate_zero_slip=True, slip_water_level=None, rake_sigma=15.0, @@ -295,7 +294,6 @@ def test_srf_config_example(tmp_path: Path) -> None: "rupture_delay": 0.0, "rvfmax": 1.414, "rvfmin": 0.25, - "rvfrac_slip_sig": None, "truncate_zero_slip": True, "slip_water_level": None, "rake_sigma": 15.0, @@ -311,7 +309,7 @@ def test_srf_config_example(tmp_path: Path) -> None: "tsfac_main": None, "tsfac_slope": -0.5, "circular_average": False, - "kmodel": 2.0, + "kmodel": 2, "kord": 4, "magC": 6.3, "mag_area_Acoef": None, @@ -324,18 +322,15 @@ def test_srf_config_example(tmp_path: Path) -> None: "use_median_mag": False, "lambda_max": None, "lambda_min": None, - "roughnessfile": None, "wavelength_max": None, "wavelength_min": None, "asp_taper_fac": 0.05, "extend_fac": None, "flen_max": None, "fwid_max": None, - "init_slip_file": None, "moment_fraction": None, "perturb_subfault_location": True, "rand_rake_degs": 60.0, - "read_slip_file": False, "rtime1_depth": 2.0, "rtime1_depth_range": 1.0, "rtime1_scor": 0.8, diff --git a/tests/test_realisation_to_srf.py b/tests/test_realisation_to_srf.py index 5dcdd7d..c6525ff 100644 --- a/tests/test_realisation_to_srf.py +++ b/tests/test_realisation_to_srf.py @@ -61,7 +61,6 @@ def test_build_genslip_command_static_args() -> None: rupture_delay=0.0, rvfmax=1.414, rvfmin=0.25, - rvfrac_slip_sig=None, truncate_zero_slip=True, slip_water_level=None, rake_sigma=15.0, @@ -123,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, @@ -206,7 +206,7 @@ def test_build_genslip_command_static_args() -> None: "hyb_corlen_dep_range=1.5", "hyb_corlen_fac=2.0", "hyb_corlen_flag=0", - "hyb_corlen_kmodel=schemas.KModel.SUZUKI", + "hyb_corlen_kmodel=5", "hyb_corlen_shal_wt_end=0.0", "hyb_corlen_shal_wt_start=1.0", "hyb_corlen_side_taper=0.08", @@ -227,7 +227,7 @@ def test_build_genslip_command_static_args() -> None: "tsfac_coef=1.1", "tsfac_slope=-0.5", "circular_average=0", - "kmodel=schemas.KModel.MAI", + "kmodel=2", "kord=4", "magC=6.3", "mai_wt=0.5", @@ -239,7 +239,6 @@ def test_build_genslip_command_static_args() -> None: "asp_taper_fac=0.05", "perturb_subfault_location=1", "rand_rake_degs=60.0", - "read_slip_file=0", "rtime1_depth=2.0", "rtime1_depth_range=1.0", "rtime1_scor=0.8", diff --git a/workflow/realisations.py b/workflow/realisations.py index ffe90f0..2889a4e 100644 --- a/workflow/realisations.py +++ b/workflow/realisations.py @@ -517,7 +517,7 @@ class SRFConfig(RealisationConfiguration): kmodel: schemas.KModel """Kinematic model index.""" kord: int - """Wavenumber filter order. Stored as float for schema compatibility.""" + """Wavenumber filter order.""" magC: float """Magnitude corner frequency coefficient.""" mag_area_Acoef: float | None diff --git a/workflow/schemas.py b/workflow/schemas.py index 5406054..53a6a87 100644 --- a/workflow/schemas.py +++ b/workflow/schemas.py @@ -684,7 +684,7 @@ def _corners_to_array(corners_spec: list[dict[str, float]]) -> np.ndarray: ): Use(KModel), Literal( "kord", - description="Wavenumber filter order (integer stored as float for schema compatibility).", + description="Wavenumber filter order.", ): And(int, _is_positive), Literal( "magC", diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 10c6754..2802405 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -43,6 +43,7 @@ import shutil import subprocess from collections.abc import Iterable +from enum import Enum from pathlib import Path from typing import Annotated @@ -490,6 +491,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: From 017d3b2446263281534424c2c6c856dae282471d Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Fri, 6 Mar 2026 09:58:42 +1300 Subject: [PATCH 7/9] serialise rvfrac slip sigma --- workflow/scripts/realisation_to_srf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 2802405..42a1023 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -480,6 +480,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 From f0cfeeb6e4fbeaf577fb8eb3d1014370f734ebf9 Mon Sep 17 00:00:00 2001 From: Jake Faulkner Date: Fri, 6 Mar 2026 10:00:28 +1300 Subject: [PATCH 8/9] fix(test_hf): set rvfrac_slip_sig to None --- tests/test_hf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_hf.py b/tests/test_hf.py index 417a75c..8988d72 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) From 7e38639b1be155da3e24f5500091c29ed4b2b9db Mon Sep 17 00:00:00 2001 From: sungeunbae Date: Mon, 23 Mar 2026 13:21:11 +1300 Subject: [PATCH 9/9] Added Enum case check --- workflow/scripts/realisation_to_srf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/workflow/scripts/realisation_to_srf.py b/workflow/scripts/realisation_to_srf.py index 10c6754..7900527 100644 --- a/workflow/scripts/realisation_to_srf.py +++ b/workflow/scripts/realisation_to_srf.py @@ -37,6 +37,7 @@ """ import dataclasses +from enum import Enum import functools import multiprocessing import re @@ -490,6 +491,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 = value.value elif dataclasses.is_dataclass(value): continue else: