From d77bdb70d5c7ba00f0ef91185a84d812a021acbd Mon Sep 17 00:00:00 2001 From: Rick-Methot-NOAA Date: Thu, 15 Jan 2026 15:58:38 -0800 Subject: [PATCH 1/4] revise benchmark code for SRR 7 --- SS_recruit.tpl | 25 ++++++++++++++++++++----- SS_write_report.tpl | 4 ++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/SS_recruit.tpl b/SS_recruit.tpl index 9a1ab894..ab75fa2b 100644 --- a/SS_recruit.tpl +++ b/SS_recruit.tpl @@ -377,11 +377,26 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm, // SS_Label_44.1.7 3 parameter survival based case 7: // survival { - SRZ_0 = log(1.0 / (SSB_virgin_use / Recr_virgin_use)); - srz_min = SRZ_0 * (1.0 - steepness); - B_equil = SSB_virgin_use * (1. - (log(1. / SSBpR_current) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3)))); - SRZ_surv = mfexp((1. - pow((B_equil / SSB_virgin_use), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); // survival - R_equil = B_equil * SRZ_surv; + // z_frac is steepness +// incorrect code below was used prior to Jan 2026 revision +// SRZ_0 = log(1.0 / (SSB_virgin_use / Recr_virgin_use)); +// srz_min = SRZ_0 * (1.0 - steepness); +// B_equil = SSB_virgin_use * (1. - (log(1. / SSBpR_current) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3)))); +// SRZ_surv = mfexp((1. - pow((B_equil / SSB_virgin_use), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); // survival +// R_equil = B_equil * SRZ_surv; + dvariable SPR0 = SSB_virgin_use / Recr_virgin_use; +// warning << "SPR: " << SSBpR_current / SPR0 << " Old: " << B_equil << " " << R_equil; + +// formula: pow( (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )), (1. / SRparm(3))); +// use a join fxn to keep the quantity above 0.01, which is enough above 0.0 to assure no negative + dvariable temp = (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )); + dvariable join1 = 1. / (1. + mfexp(100. * (temp - 0.01))); // steep logistic joiner + dvariable temp1 = join1 * 0.01 + (1. - join1) * (temp - 0.01); + B_equil = Recr_virgin_use * SPR0 * + pow( temp1, (1. / SRparm(3))); + R_equil = B_equil / SSBpR_current; +// warning << " log(SPR): " << log (SPR0 / SSBpR_current) << " denom " << steepness * log (SPR0) << " base: " << +// (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )) << " temp: " << temp << " " << join1 << " " << temp1 << " New: " << B_equil << " " << R_equil << endl; break; } diff --git a/SS_write_report.tpl b/SS_write_report.tpl index c2242670..87cb8d21 100644 --- a/SS_write_report.tpl +++ b/SS_write_report.tpl @@ -4754,7 +4754,7 @@ FUNCTION void SPR_profile() } // do not recalculate here so force using values from benchmark SS2out << "unfished values for SRR: SSB " << SSB0_4_SRR << " R " << R0_4_SRR << " SSBpR " << " SSBpR: " << SSB0_4_SRR / R0_4_SRR << endl; - SS2out << "SPRloop Iter Bycatch Fmult F_std SSBpR YpR_dead YpR_dead*Recr YpR_ret*Recr Revenue Cost Profit SSB Recruits SSB/Bzero Tot_Catch "; + SS2out << "SPRloop Iter Bycatch Fmult F_std SSBpR SPR YpR_dead YpR_dead*Recr YpR_ret*Recr Revenue Cost Profit SSB Recruits SSB/Bzero Tot_Catch "; for (f = 1; f <= Nfleet; f++) { if (fleet_type(f) <= 2) @@ -4921,7 +4921,7 @@ FUNCTION void SPR_profile() if (SPRloop1 == 0) Fcrash = Fmult2; } - SS2out << SPRloop1 << " " << SPRloop << " " << with_BYC << " " << Fmult2 << " " << equ_F_std << " " << SSB_equil / (SSB0_4_SRR / R0_4_SRR) << " " << YPR_dead << " " + SS2out << SPRloop1 << " " << SPRloop << " " << with_BYC << " " << Fmult2 << " " << equ_F_std << " " << SSB_equil << " " << SSB_equil / (SSB0_4_SRR / R0_4_SRR) << " " << YPR_dead << " " << YPR_dead * Btgt_prof_rec << " " << YPR_ret * Btgt_prof_rec << " " << (PricePerF * YPR_val_vec) * Btgt_prof_rec << " " << Cost << " " << (PricePerF * YPR_val_vec) * Btgt_prof_rec - Cost << " " << Btgt_prof << " " << Btgt_prof_rec << " " << Btgt_prof / SSB0_4_SRR << " " << value(sum(equ_catch_fleet(2)) * Btgt_prof_rec); From 9eb75349109c7d7a34aadc151dc932f9c02d83e5 Mon Sep 17 00:00:00 2001 From: Rick-Methot-NOAA Date: Wed, 4 Feb 2026 21:53:26 -0800 Subject: [PATCH 2/4] revise join function in equil spawn-recr --- SS_recruit.tpl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/SS_recruit.tpl b/SS_recruit.tpl index ab75fa2b..924636fe 100644 --- a/SS_recruit.tpl +++ b/SS_recruit.tpl @@ -388,15 +388,14 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm, // warning << "SPR: " << SSBpR_current / SPR0 << " Old: " << B_equil << " " << R_equil; // formula: pow( (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )), (1. / SRparm(3))); -// use a join fxn to keep the quantity above 0.01, which is enough above 0.0 to assure no negative +// use a join fxn to keep the quantity positive dvariable temp = (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )); - dvariable join1 = 1. / (1. + mfexp(100. * (temp - 0.01))); // steep logistic joiner - dvariable temp1 = join1 * 0.01 + (1. - join1) * (temp - 0.01); - B_equil = Recr_virgin_use * SPR0 * - pow( temp1, (1. / SRparm(3))); + dvariable join1 = 1. / (1. + mfexp(100. * (-temp))); // steep logistic joiner + dvariable temp1 = join1 * temp; + B_equil = Recr_virgin_use * SPR0 * pow( temp1, (1. / SRparm(3))); R_equil = B_equil / SSBpR_current; // warning << " log(SPR): " << log (SPR0 / SSBpR_current) << " denom " << steepness * log (SPR0) << " base: " << -// (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )) << " temp: " << temp << " " << join1 << " " << temp1 << " New: " << B_equil << " " << R_equil << endl; +// (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )) << " temp: " << temp << " join " << join1 << " temp1: " << temp1 << " New: " << B_equil << " " << R_equil << endl; break; } From 4a34dd90871021bff1f324645d64c98e921df577 Mon Sep 17 00:00:00 2001 From: Rick-Methot-NOAA Date: Fri, 6 Feb 2026 10:47:01 -0800 Subject: [PATCH 3/4] add tiny constant in join to prevent negatives --- SS_recruit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SS_recruit.tpl b/SS_recruit.tpl index 924636fe..d03a96be 100644 --- a/SS_recruit.tpl +++ b/SS_recruit.tpl @@ -391,7 +391,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm, // use a join fxn to keep the quantity positive dvariable temp = (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )); dvariable join1 = 1. / (1. + mfexp(100. * (-temp))); // steep logistic joiner - dvariable temp1 = join1 * temp; + dvariable temp1 = join1 * temp + 1.0e-06; B_equil = Recr_virgin_use * SPR0 * pow( temp1, (1. / SRparm(3))); R_equil = B_equil / SSBpR_current; // warning << " log(SPR): " << log (SPR0 / SSBpR_current) << " denom " << steepness * log (SPR0) << " base: " << From ee38a5d745bae204584e88b3c65bc8c2d6a0fd24 Mon Sep 17 00:00:00 2001 From: Rick-Methot-NOAA Date: Fri, 6 Feb 2026 11:47:57 -0800 Subject: [PATCH 4/4] another join approach using sqrt(square( --- SS_recruit.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SS_recruit.tpl b/SS_recruit.tpl index d03a96be..73f1d102 100644 --- a/SS_recruit.tpl +++ b/SS_recruit.tpl @@ -390,8 +390,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm, // formula: pow( (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )), (1. / SRparm(3))); // use a join fxn to keep the quantity positive dvariable temp = (1.0 - (log (SPR0 / SSBpR_current)) / (steepness * log (SPR0) )); - dvariable join1 = 1. / (1. + mfexp(100. * (-temp))); // steep logistic joiner - dvariable temp1 = join1 * temp + 1.0e-06; + dvariable join1 = 1. / (1. + mfexp(40. * (-temp))); // steep logistic joiner + dvariable temp1 = sqrt( square( join1 * temp)); // to make small negative values positive B_equil = Recr_virgin_use * SPR0 * pow( temp1, (1. / SRparm(3))); R_equil = B_equil / SSBpR_current; // warning << " log(SPR): " << log (SPR0 / SSBpR_current) << " denom " << steepness * log (SPR0) << " base: " <<