From 45e40fce830b89168f40b1f876baec10fd793f13 Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Wed, 8 Feb 2023 16:24:40 -0800
Subject: [PATCH 01/29] first commit for B-H with ab

add S-R option 10 for a,b formulation
---
 SS_benchfore.tpl              | 12 ++---
 SS_param.tpl                  |  1 +
 SS_popdyn.tpl                 | 33 +++++++++++---
 SS_readcontrol_330.tpl        | 11 ++++-
 SS_recruit.tpl                | 85 ++++++++++++++++++-----------------
 SS_write_report.tpl           |  8 +++-
 StockSynthesis.code-workspace |  1 +
 7 files changed, 94 insertions(+), 57 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index ff3f5844..327810cc 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -902,7 +902,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     }
 
     //  SPAWN-RECR:   calc equil spawn-recr in YPR; need to make this area-specific
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SSB_equil); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSB_equil); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
 
     Bspr = Equ_SpawnRecr_Result(1);
     Bspr_rec = Equ_SpawnRecr_Result(2);
@@ -1017,7 +1017,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     if (rundetail > 0 && mceval_counter == 0 && show_MSY == 1)
       echoinput << "Calculated F0.1: " << Btgt_Fmult << endl;
     SPR_temp = SSB_equil;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     Btgt = Equ_SpawnRecr_Result(1);
     Btgt_Rec = Equ_SpawnRecr_Result(2);
     YPR_Btgt_enc = YPR_enc; //  total encountered yield per recruit
@@ -1111,7 +1111,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
         SPR_Btgt = SSB_equil / SPR_unfished;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
 
@@ -1331,7 +1331,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
       MSY_SPR = SSB_equil / SPR_unfished;
       SPR_temp = SSB_equil;
-      Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+      Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
       Bmsy = Equ_SpawnRecr_Result(1);
       Recr_msy = Equ_SpawnRecr_Result(2);
       yld1(1) = YPR_opt * Recr_msy;
@@ -1424,7 +1424,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
           MSY_SPR = SSB_equil / SPR_unfished;
           SPR_temp = SSB_equil;
-          Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+          Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
           Bmsy = Equ_SpawnRecr_Result(1);
           Recr_msy = Equ_SpawnRecr_Result(2);
           Profit = (PricePerF * YPR_val_vec) * Recr_msy - Cost;
@@ -1718,7 +1718,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
         SPR_Btgt2 = SSB_equil / SPR_unfished;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
 
diff --git a/SS_param.tpl b/SS_param.tpl
index d3c43b41..bd21a12b 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -416,6 +416,7 @@ PARAMETER_SECTION
    //  note that bycatch_F(1,Nfleet,1,nseas) has similar role  
    number alpha;
    number beta;
+   number steepness;
    number GenTime;
    vector cumF(1,gmorph);
    vector maxF(1,gmorph);
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index 664bdd5d..70bdc8f9 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -337,17 +337,38 @@ FUNCTION void get_initial_conditions()
   Fishon = 0;
   virg_fec = fec;
   Recr.initialize(); //  will store recruitment by area
+
+  //  SPAWN-RECR:   get expected recruitment globally or by area
+  if (recr_dist_area == 1 || pop == 1) //  do global spawn_recruitment calculations
+  {
+    equ_Recr = 1.0;
+    Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation.  Returns SPR because R = 1.0
+    SPR_virgin = SSB_equil; //  spawners per recruit.  Needed for Sr_fxn = 10
+
+    if(SR_fxn == 10)  // B-H with a,b
+    {
+      alpha = mfexp(SR_parm(3));
+      beta = mfexp(SR_parm(4));
+      steepness = alpha * SPR_virgin / (4.00 + alpha * SPR_virgin);
+      Recr_virgin = 1.0 / beta * (alpha - ( 1.0 / SPR_virgin));
+      SR_parm(1) = log(Recr_virgin);
+      SR_parm(2) = steepness;
+      // warning<< SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
+      //     << " alpha_beta: "<<alpha<<" "<<beta<<endl
+      //   << " spr: "<<SPR_virgin<<endl
+      //    << " der_steep: "<< alpha * SPR_virgin / (4.00 + alpha * SPR_virgin)<<endl
+      //    << "der_R0: "<<  1.0 / beta * (alpha - ( 1.0 / SPR_virgin))<<endl;
+    }
+    else {
+      Recr_virgin = mfexp(SR_parm(1));
+    }
+  
   for (int i = 1; i <= N_SRparm2; i++)
   {
     SR_parm_byyr(eq_yr, i) = SR_parm(i);
     SR_parm_virg(i) = SR_parm(i);
     SR_parm_work(i) = SR_parm(i);
   }
-
-  //  SPAWN-RECR:   get expected recruitment globally or by area
-  if (recr_dist_area == 1 || pop == 1) //  do global spawn_recruitment calculations
-  {
-    Recr_virgin = mfexp(SR_parm(1));
     equ_Recr = Recr_virgin;
     exp_rec(eq_yr, 1) = Recr_virgin; //  expected Recr from s-r parms
     exp_rec(eq_yr, 2) = Recr_virgin;
@@ -507,7 +528,7 @@ FUNCTION void get_initial_conditions()
     CrashPen += Equ_penalty;
     SPR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
     //  get equilibrium SSB and recruitment from SPR_temp, Recr_virgin and virgin steepness
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm(2), SR_parm(3), SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
 
     R1_exp = Equ_SpawnRecr_Result(2); //  set the expected recruitment equal to this equilibrium
     exp_rec(eq_yr, 1) = R1_exp;
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index b1572680..62efbf6b 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1937,13 +1937,13 @@
 !!//  SS_Label_Info_4.6 #Read setup for Spawner-Recruitment parameters
   //  SPAWN-RECR: read setup for SR parameters:  LO, HI, INIT, PRIOR, PRtype, CV, PHASE
   init_int SR_fxn
-!!echoinput<<SR_fxn<<" #_SR_function: 1=NA; 2=Ricker(2 parms); 3=BevHolt(2); 4=SCAA(2); 5=Hockey(3); 6=B-H_flattop(2); 7=Survival(3); 8=Shepherd(3); 9=Ricker_Power(3) "<<endl;
+!!echoinput<<SR_fxn<<" #_SR_function: 1=NA; 2=Ricker(2 parms); 3=BevHolt(2); 4=SCAA(2); 5=Hockey(3); 6=B-H_flattop(2); 7=Survival(3); 8=Shepherd(3); 9=Ricker_Power(3); 10=B-H_a,b(4)"<<endl;
   init_int init_equ_steepness;
 !!echoinput<<init_equ_steepness<<"  # 0/1 to use steepness in initial equ recruitment calculation"<<endl;
   init_int sigmaR_dendep;
 !! echoinput<<sigmaR_dendep<<"  #  future feature:  0/1 to make realized sigmaR a function of SR curvature"<<endl;
   ivector N_SRparm(1,10)
-!!N_SRparm.fill("{0,2,2,2,3,2,3,3,3,3}");
+!!N_SRparm.fill("{0,2,2,2,3,2,3,3,3,4}");
   int N_SRparm2
   int N_SRparm3  //  with timevary links included
 !!N_SRparm2=N_SRparm(SR_fxn)+3;
@@ -2026,6 +2026,13 @@
       ParmLabel += "SR_RkrPower_gamma";
       break;
     }
+    case 10: // Bev-Holt a,b
+    {
+      ParmLabel += "SR_BH_steep_derived";
+      ParmLabel += "SR_BH_ln(alpha)";
+      ParmLabel += "SR_BH_ln(beta)";
+      break;
+    }
   }
   ParmLabel += "SR_sigmaR";
   ParmLabel += "SR_regime";
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 93d3fe73..f6a58c32 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -49,25 +49,14 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 3: // Beverton-Holt
     {
       steepness = SR_parm_work(2);
-      alpha = 4.0 * steepness * Recr_virgin / (5. * steepness - 1.);
-      beta = (SSB_virgin_adj * (1. - steepness)) / (5. * steepness - 1.);
+      dvariable SPR = SSB_virgin_adj / Recr_virgin;
+      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
+      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       NewRecruits = (4. * steepness * Recr_virgin_adj * SSB_curr_adj) /
           (SSB_virgin_adj * (1. - steepness) + (5. * steepness - 1.) * SSB_curr_adj);
       break;
     }
 
-    // Beverton-Holt with alpha beta
-    /*
-      case 3: // Beverton-Holt
-      {
-        steepness=SR_parm_work(2);
-        alpha = 4.0 * steepness*Recr_virgin / (5.*steepness-1.);
-        beta = (SSB_virgin_adj*(1.-steepness)) / (5.*steepness-1.);
-        NewRecruits =  (alpha*SSB_curr_adj) / (beta+SSB_curr_adj);
-        break;
-      }
-   */
-
     //  SS_Label_43.3.4  constant expected recruitment
     case 4: // none
     {
@@ -88,8 +77,9 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 6: //Beverton-Holt constrained
     {
       steepness = SR_parm_work(2);
-      alpha = 4.0 * steepness * Recr_virgin / (5. * steepness - 1.);
-      beta = (SSB_virgin_adj * (1. - steepness)) / (5. * steepness - 1.);
+      dvariable SPR = SSB_virgin_adj / Recr_virgin;
+      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
+      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       if (SSB_curr_adj > SSB_virgin_adj)
       {
         SSB_BH1 = SSB_virgin_adj;
@@ -167,6 +157,14 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
       NewRecruits = Recr_virgin_adj * temp * mfexp(RkrTop);
       break;
     }
+
+      case 10: // Beverton-Holt with alpha beta
+      {
+        alpha = mfexp(SR_parm_work(3));
+        beta = mfexp(SR_parm_work(4));
+        NewRecruits =  (alpha*SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
+        break;
+      }
   }
   RETURN_ARRAYS_DECREMENT();
   return NewRecruits;
@@ -270,7 +268,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
 //********************************************************************
  /*  SS_Label_FUNCTION 44 Equil_Spawn_Recr_Fxn */
 //  SPAWN-RECR:   function  Equil_Spawn_Recr_Fxn
-FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prevariable& SRparm3,
+FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     const prevariable& SSB_virgin, const prevariable& Recr_virgin, const prevariable& SPR_temp)
   {
   RETURN_ARRAYS_INCREMENT();
@@ -286,7 +284,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
   dvariable srz_min;
   dvariable SRZ_surv;
 
-  steepness = SRparm2; //  common usage but some different
+  steepness = SRparm(2); //  common usage but some different
   //  SS_Label_44.1  calc equilibrium SpawnBio and Recruitment from input SPR_temp, which is spawning biomass per recruit at some given F level
   switch (SR_fxn)
   {
@@ -296,16 +294,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
       write_message (FATAL, 0); // EXIT!
       break;
     }
-    //  SS_Label_44.1.1  Beverton-Holt with flattop beyond Bzero
-    case 6: //Beverton-Holt
-    {
-      alpha = 4.0 * steepness * Recr_virgin / (5. * steepness - 1.);
-      beta = (SSB_virgin * (1. - steepness)) / (5. * steepness - 1.);
-      B_equil = alpha * SPR_temp - beta;
-      B_equil = posfun(B_equil, 0.0001, temp);
-      R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil);
-      break;
-    }
+
     //  SS_Label_44.1.2  Ricker
     case 2: // Ricker
     {
@@ -314,17 +303,32 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
 
       break;
     }
-    //  SS_Label_44.1.3  Beverton-Holt
+      //  SS_Label_44.1.1  Beverton-Holt 
+    case 6: //Beverton-Holt with flattop beyond Bzero, but no flattop in equil calcs
+    {
+    }
+  //  SS_Label_44.1.3  Beverton-Holt
     case 3: // same as case 6
     {
-      alpha = 4.0 * steepness * Recr_virgin / (5. * steepness - 1.);
-      beta = (SSB_virgin * (1. - steepness)) / (5. * steepness - 1.);
+      dvariable SPR = SSB_virgin / Recr_virgin;
+      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
+      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       B_equil = alpha * SPR_temp - beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil); //Beverton-Holt
       break;
     }
 
+    case 10: // Beverton-Holt with alpha and beta parameterization
+    {
+      alpha = mfexp(SRparm(3));
+      beta = mfexp(SRparm(4));
+      B_equil = alpha * SPR_temp - beta;
+      B_equil = posfun(B_equil, 0.0001, temp);
+      R_equil =  (alpha * Recr_virgin * B_equil) / (1.0 + beta * Recr_virgin * B_equil);
+      break;
+    }
+
     //  SS_Label_44.1.4  constant recruitment
     case 4: // constant; no bias correction
     {
@@ -335,7 +339,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
     //  SS_Label_44.1.5  Hockey Stick
     case 5: // hockey stick
     {
-      alpha = SRparm3 * Recr_virgin; // min recruitment level
+      alpha = SRparm(3) * Recr_virgin; // min recruitment level
       //        temp=SSB_virgin/R0*steepness;  // spawners per recruit at inflection
       beta = (Recr_virgin - alpha) / (steepness * SSB_virgin); //  slope of recruitment on spawners below the inflection
       B_equil = Join_Fxn(0.0 * SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin * steepness, SPR_temp, alpha / ((1. / SPR_temp) - beta), SPR_temp * Recr_virgin);
@@ -347,9 +351,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
     {
       SRZ_0 = log(1.0 / (SSB_virgin / Recr_virgin));
       srz_min = SRZ_0 * (1.0 - steepness);
-      B_equil = SSB_virgin * (1. - (log(1. / SPR_temp) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm3)));
-      B_equil = posfun(B_equil, 0.0001, temp);
-      SRZ_surv = mfexp((1. - pow((B_equil / SSB_virgin), SRparm3)) * (srz_min - SRZ_0) + SRZ_0); //  survival
+      B_equil = SSB_virgin * (1. - (log(1. / SPR_temp) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3))));
+      SRZ_surv = mfexp((1. - pow((B_equil / SSB_virgin), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
       R_equil = B_equil * SRZ_surv;
       break;
     }
@@ -367,14 +370,14 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
       //       REC = (TOP/BOT)**(1.0/POWER)*SPRF0/SPR
       // Power = exp(logC);
       // Hupper = 1.0/(5.0 * pow(0.2,Power));
-      Shepherd_c = SRparm3;
-      Shepherd_c2 = pow(0.2, SRparm3);
+      Shepherd_c = SRparm(3);
+      Shepherd_c2 = pow(0.2, SRparm(3));
       Hupper = 1.0 / (5.0 * Shepherd_c2);
-      steepness = 0.2 + (SRparm2 - 0.2) / (0.8) * (Hupper - 0.2);
+      steepness = 0.2 + (SRparm(2) - 0.2) / (0.8) * (Hupper - 0.2);
       Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_temp * Recr_virgin) / SSB_virgin - (1.0 - 5.0 * steepness * Shepherd_c2);
       Shep_bot = 5.0 * steepness - 1.0;
       Shep_top2 = posfun(Shep_top, 0.001, temp);
-      R_equil = (SSB_virgin / SPR_temp) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm3));
+      R_equil = (SSB_virgin / SPR_temp) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
       B_equil = R_equil * SPR_temp;
       break;
     }
@@ -382,8 +385,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const prevariable& SRparm2, const prev
     //  SS_Label_43.3.8  Ricker-power
     case 9: // Ricker power 3-parameter SRR.  per Punt & Cope 2017
     {
-      steepness = SRparm2;
-      dvariable RkrPower = SRparm3;
+      steepness = SRparm(2);
+      dvariable RkrPower = SRparm(3);
       temp = SSB_virgin / (SPR_temp * Recr_virgin);
       dvariable RkrTop = pow(0.8, RkrPower) * log(temp) / log(5.0 * steepness);
       RkrTop = posfun(RkrTop, 0.000001, CrashPen);
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index ca3cffec..a1567e8b 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1734,8 +1734,12 @@ FUNCTION void write_bigoutput()
            << pick_report_name(19);
     SS2out << "  Function: " << SR_fxn << "  RecDev_method: " << do_recdev << "   sum_recdev: " << sum_recdev << endl
            << SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
-           << steepness << " steepness" << endl
+           << steepness << " steepness " << "#_derived_alpha_beta: "<<alpha<<" "<<beta<<endl
            << Bmsy / SSB_virgin << " Bmsy/Bzero ";
+        SS2out << " spr: "<<SPR_virgin<<endl;
+         SS2out << " der_steep: "<< alpha * SPR_virgin / (4.00 + alpha * SPR_virgin)<<endl;
+         SS2out << "der_R0: "<<  1.0 / beta * (alpha - ( 1.0 / SPR_virgin))<<endl;;
+
     if (SR_fxn == 8)
     {
       dvariable Shepherd_c;
@@ -4743,7 +4747,7 @@ FUNCTION void SPR_profile()
         Do_Equil_Calc(equ_Recr);
         //  SPAWN-RECR:   calc equil spawn-recr in the SPR loop
         SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work(2), SR_parm_work(3), SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         Btgt_prof = Equ_SpawnRecr_Result(1);
         Btgt_prof_rec = Equ_SpawnRecr_Result(2);
         if (Btgt_prof < 0.001 || Btgt_prof_rec < 0.001)
diff --git a/StockSynthesis.code-workspace b/StockSynthesis.code-workspace
index 2bfc56e8..cdd30489 100644
--- a/StockSynthesis.code-workspace
+++ b/StockSynthesis.code-workspace
@@ -10,6 +10,7 @@
 			"\"*.extension\":": "\"tpl\"",
 			"*.htp": "c",
 			"ostream": "c",
+			"xlocale": "c",
 			"iosfwd": "c"
 		},
 		"explorer.excludeGitIgnore": true

From 94c7b88b9df1108a2caf512f04b3bae5ee61c5c8 Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Mon, 13 Feb 2023 17:36:35 -0800
Subject: [PATCH 02/29] revise to use WHAM syntax

---
 SS_benchfore.tpl    |  5 ++++-
 SS_popdyn.tpl       |  5 ++---
 SS_recruit.tpl      | 43 ++++++++++++++++++++++++++++---------------
 SS_write_report.tpl | 23 +++++++++++++++++------
 4 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 327810cc..9c5c5e37 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -748,6 +748,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   Recr_unf = mfexp(SR_parm_work(1));
   Do_Equil_Calc(Recr_unf);
   SSB_unf = SSB_equil;
+  report5<<" calc SSBunf "<<SSB_unf<<" recr "<<Recr_unf<<" work "<<SR_parm_work<<" parm "<<SR_parm<<endl;
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   if (show_MSY == 1)
     report5 << "SR_parm for benchmark: " << SR_parm_work << endl
@@ -902,7 +903,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     }
 
     //  SPAWN-RECR:   calc equil spawn-recr in YPR; need to make this area-specific
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSB_equil); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    SPR_temp = SSB_equil;  //  based on most recent call to Do_Equil_Calc
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
 
     Bspr = Equ_SpawnRecr_Result(1);
     Bspr_rec = Equ_SpawnRecr_Result(2);
@@ -1111,6 +1113,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
         SPR_Btgt = SSB_equil / SPR_unfished;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
+    
         Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index 70bdc8f9..c5f67be3 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -349,8 +349,8 @@ FUNCTION void get_initial_conditions()
     {
       alpha = mfexp(SR_parm(3));
       beta = mfexp(SR_parm(4));
-      steepness = alpha * SPR_virgin / (4.00 + alpha * SPR_virgin);
-      Recr_virgin = 1.0 / beta * (alpha - ( 1.0 / SPR_virgin));
+      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
       SR_parm(1) = log(Recr_virgin);
       SR_parm(2) = steepness;
       // warning<< SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
@@ -529,7 +529,6 @@ FUNCTION void get_initial_conditions()
     SPR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
     //  get equilibrium SSB and recruitment from SPR_temp, Recr_virgin and virgin steepness
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-
     R1_exp = Equ_SpawnRecr_Result(2); //  set the expected recruitment equal to this equilibrium
     exp_rec(eq_yr, 1) = R1_exp;
 
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index f6a58c32..3b2affb4 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -49,9 +49,10 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 3: // Beverton-Holt
     {
       steepness = SR_parm_work(2);
-      dvariable SPR = SSB_virgin_adj / Recr_virgin;
-      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
-      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
+//      dvariable SPR = SSB_virgin_adj / Recr_virgin;
+//      dvariable alpha = (4.0 * steepness) / ( SPR * (1. - steepness)) ;
+//      dvariable beta = (5.0 * steepness - 1.0 )/((1.0 - steepness ) * Recr_virgin * SPR );
+//      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       NewRecruits = (4. * steepness * Recr_virgin_adj * SSB_curr_adj) /
           (SSB_virgin_adj * (1. - steepness) + (5. * steepness - 1.) * SSB_curr_adj);
       break;
@@ -77,9 +78,9 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 6: //Beverton-Holt constrained
     {
       steepness = SR_parm_work(2);
-      dvariable SPR = SSB_virgin_adj / Recr_virgin;
-      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
-      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
+//      dvariable SPR = SSB_virgin_adj / Recr_virgin;
+//      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
+//      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       if (SSB_curr_adj > SSB_virgin_adj)
       {
         SSB_BH1 = SSB_virgin_adj;
@@ -162,7 +163,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
       {
         alpha = mfexp(SR_parm_work(3));
         beta = mfexp(SR_parm_work(4));
-        NewRecruits =  (alpha*SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
+        NewRecruits =  (alpha * SSB_curr_adj) / (beta + SSB_curr_adj);
         break;
       }
   }
@@ -310,22 +311,34 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
   //  SS_Label_44.1.3  Beverton-Holt
     case 3: // same as case 6
     {
-      dvariable SPR = SSB_virgin / Recr_virgin;
-      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
-      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
-      B_equil = alpha * SPR_temp - beta;
+  // from WHAM per Tim Miller:
+  //  WHAM based on R = A*S/(1+B*S)
+  //  log_SR_a = log(4 * SR_h/(exp(log_SPR0)*(1 - SR_h)));
+  //  log_SR_b = log((5*SR_h - 1)/((1-SR_h)*SR_R0*exp(log_SPR0)));
+  //  SR_h = 0.2 * exp(0.8*log(exp(log_SR_a) * exp(log_SPR0)));
+  //  SR_R0 = log(exp(log_SR_a + log_SPR0))/(exp(log_SR_b + log_SPR0));
+
+  //  SS3 previously used alternative formulation: R = A*S/(B+S)
+  //  converting SS3 to align with WHAM
+      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
+      B_equil = (alpha * SPR_temp - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
-      R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil); //Beverton-Holt
+      R_equil = alpha * B_equil / (1.0 + beta * B_equil);
+//      report5<<" WHAM Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
+//      R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil); //Beverton-Holt
+//      report5<<" SS3 Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
       break;
     }
 
-    case 10: // Beverton-Holt with alpha and beta parameterization
+    case 10: // Beverton-Holt with alpha and beta parameterization using  R = A*S/(B+S) approach
     {
       alpha = mfexp(SRparm(3));
       beta = mfexp(SRparm(4));
-      B_equil = alpha * SPR_temp - beta;
+      B_equil = (alpha * SPR_temp - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
-      R_equil =  (alpha * Recr_virgin * B_equil) / (1.0 + beta * Recr_virgin * B_equil);
+      R_equil = alpha * B_equil / (1.0 + beta * B_equil);
+//      report5<<SPR_temp<<" Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
       break;
     }
 
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index a1567e8b..fcd322ed 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1734,13 +1734,24 @@ FUNCTION void write_bigoutput()
            << pick_report_name(19);
     SS2out << "  Function: " << SR_fxn << "  RecDev_method: " << do_recdev << "   sum_recdev: " << sum_recdev << endl
            << SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
-           << steepness << " steepness " << "#_derived_alpha_beta: "<<alpha<<" "<<beta<<endl
+           << steepness << " steepness " << endl
            << Bmsy / SSB_virgin << " Bmsy/Bzero ";
-        SS2out << " spr: "<<SPR_virgin<<endl;
-         SS2out << " der_steep: "<< alpha * SPR_virgin / (4.00 + alpha * SPR_virgin)<<endl;
-         SS2out << "der_R0: "<<  1.0 / beta * (alpha - ( 1.0 / SPR_virgin))<<endl;;
-
-    if (SR_fxn == 8)
+    SS2out << " SPR_virgin "<<SPR_virgin<<endl;
+    if (SR_fxn == 10)
+    {
+  //  SR_h = 0.2 * exp(0.8*log(exp(log_SR_a) * exp(log_SPR0)));
+  //  SR_R0 = log(exp(log_SR_a + log_SPR0))/(exp(log_SR_b + log_SPR0));
+      SS2out << " derived_steepness "<< 0.2 * mfexp( 0.8 * log( alpha ) * SPR_virgin)<<" using_virgin_SPR; will be time-varying if biology is time-varying"<<endl;
+      SS2out << "derived_R0 "<<  log( alpha * SPR_virgin ) / ( beta * SPR_virgin)<endl;
+    }
+    else if (SR_fxn == 3)
+    {
+      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
+      SS2out << " derived_alpha " << alpha << " using_virgin_SPR" << endl;
+      SS2out << "derived_beta " <<  beta <<endl;
+    }
+    else if (SR_fxn == 8)
     {
       dvariable Shepherd_c;
       dvariable Shepherd_c2;

From 9e6f60fe09f41dc94fef24129a1dd676e231c4e9 Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Mon, 13 Feb 2023 17:43:58 -0800
Subject: [PATCH 03/29] Update .gitignore

---
 .gitignore | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2d39ecb0..a8becca9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,10 +7,9 @@
 *.htp
 *.obj
 *.log
-ss.tpl
-ss3.tpl
-ss_opt.tpl
-ss_trans.tpl
+Compile/ss.tpl
+Compile/ss_opt.tpl
+Compile/ss_trans.tpl
 ~$*.*
 Compile/ss.log
 Compile/ss3.log

From b66b15ff4d55a1cf5666c1a55aebe71b3acdffc6 Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Fri, 19 May 2023 11:14:13 -0700
Subject: [PATCH 04/29] Srr=10 now matching SRR=3

---
 SS_popdyn.tpl          | 15 ++++++++-------
 SS_readcontrol_330.tpl |  2 +-
 SS_recruit.tpl         |  5 ++---
 SS_write_report.tpl    | 10 ++++------
 4 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index c5f67be3..27f41507 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -347,17 +347,18 @@ FUNCTION void get_initial_conditions()
 
     if(SR_fxn == 10)  // B-H with a,b
     {
+  //  WHAM based on R = A*S/(1+B*S)
+  //  log_SR_a = log(4 * SR_h/(exp(log_SPR0)*(1 - SR_h)));
+  //  log_SR_b = log((5*SR_h - 1)/((1-SR_h)*SR_R0*exp(log_SPR0)));
+  //  h = a * SPR0 / (4. + a * SPR0)
+  //  R0 = 1/b * (a-1/SPR0)
+
       alpha = mfexp(SR_parm(3));
       beta = mfexp(SR_parm(4));
-      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
-      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
+      steepness = alpha * SPR_virgin / (4. + alpha * SPR_virgin);
+      Recr_virgin = 1. / beta * (alpha - (1. / SPR_virgin));
       SR_parm(1) = log(Recr_virgin);
       SR_parm(2) = steepness;
-      // warning<< SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
-      //     << " alpha_beta: "<<alpha<<" "<<beta<<endl
-      //   << " spr: "<<SPR_virgin<<endl
-      //    << " der_steep: "<< alpha * SPR_virgin / (4.00 + alpha * SPR_virgin)<<endl
-      //    << "der_R0: "<<  1.0 / beta * (alpha - ( 1.0 / SPR_virgin))<<endl;
     }
     else {
       Recr_virgin = mfexp(SR_parm(1));
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index 62efbf6b..b88046a0 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1972,7 +1972,7 @@
   SR_parm_timevary.initialize();
   SR_env_link = 0;
   SR_env_target = 0;
-  //#_SR_function: 1=null; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=Survival_3Parm "<<endl;
+  //#_SR_function: 1=null; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=Survival_3Parm; 10=B-H with a,b "<<endl;
   ParmLabel += "SR_LN(R0)";
   switch (SR_fxn)
   {
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 3b2affb4..86604f67 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -161,9 +161,10 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
 
       case 10: // Beverton-Holt with alpha beta
       {
+  //  WHAM based on R = A*S/(1+B*S)
         alpha = mfexp(SR_parm_work(3));
         beta = mfexp(SR_parm_work(4));
-        NewRecruits =  (alpha * SSB_curr_adj) / (beta + SSB_curr_adj);
+        NewRecruits =  (alpha * SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
         break;
       }
   }
@@ -315,8 +316,6 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
   //  WHAM based on R = A*S/(1+B*S)
   //  log_SR_a = log(4 * SR_h/(exp(log_SPR0)*(1 - SR_h)));
   //  log_SR_b = log((5*SR_h - 1)/((1-SR_h)*SR_R0*exp(log_SPR0)));
-  //  SR_h = 0.2 * exp(0.8*log(exp(log_SR_a) * exp(log_SPR0)));
-  //  SR_R0 = log(exp(log_SR_a + log_SPR0))/(exp(log_SR_b + log_SPR0));
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index fcd322ed..22e1df1b 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1739,17 +1739,15 @@ FUNCTION void write_bigoutput()
     SS2out << " SPR_virgin "<<SPR_virgin<<endl;
     if (SR_fxn == 10)
     {
-  //  SR_h = 0.2 * exp(0.8*log(exp(log_SR_a) * exp(log_SPR0)));
-  //  SR_R0 = log(exp(log_SR_a + log_SPR0))/(exp(log_SR_b + log_SPR0));
-      SS2out << " derived_steepness "<< 0.2 * mfexp( 0.8 * log( alpha ) * SPR_virgin)<<" using_virgin_SPR; will be time-varying if biology is time-varying"<<endl;
-      SS2out << "derived_R0 "<<  log( alpha * SPR_virgin ) / ( beta * SPR_virgin)<endl;
+      SS2out << " Ln_alpha_parameter: " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
+      SS2out << " Ln_beta_parameter: " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
     }
     else if (SR_fxn == 3)
     {
       alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
-      SS2out << " derived_alpha " << alpha << " using_virgin_SPR" << endl;
-      SS2out << "derived_beta " <<  beta <<endl;
+      SS2out << " Ln_alpha_derived: " << log(alpha) << " alpha " << alpha << endl;
+      SS2out << " Ln_beta_derived: " << log(beta) << " beta " << beta;
     }
     else if (SR_fxn == 8)
     {

From 449e87b1f63a29e52091e7c97544cdc0f5b1be2e Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Fri, 19 May 2023 17:06:15 -0700
Subject: [PATCH 05/29] adding reporting for timevary growth

---
 SS_benchfore.tpl              |  8 ++++++++
 SS_popdyn.tpl                 |  8 ++++++++
 SS_write_report.tpl           | 14 ++++++++------
 StockSynthesis.code-workspace |  3 ++-
 4 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 9c5c5e37..42b0b332 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -3646,6 +3646,14 @@ FUNCTION void Get_Forecast()
 
         Smry_Table(y, 11) = SSB_equil;
         Smry_Table(y, 13) = GenTime;
+        if( SR_fxn == 10 )
+        {
+          temp = SSB_equil / equ_Recr;  //  current year's SPB/R with current biology at age
+          alpha = mfexp(SR_parm_work(3));
+          beta = mfexp(SR_parm_work(4));
+          SR_parm_byyr(y, 2) =  alpha * temp / (4. + alpha * temp);  //  implied steepness
+          SR_parm_byyr(y, 1) = log( 1. / beta * (alpha - (1. / temp)));  //  implied ln_R0
+        }
         Fishon = 1;
         Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
         if (STD_Yr_Reverse_Ofish(y) > 0)
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index 27f41507..b2dd8299 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -1782,6 +1782,14 @@ FUNCTION void get_time_series()
       Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation with current year's biology
       Smry_Table(y, 11) = SSB_equil;
       Smry_Table(y, 13) = GenTime;
+      if( SR_fxn == 10 )
+      {
+        temp = SSB_equil / Recr_virgin;  //  current year's SPB/R with current biology at age
+        alpha = mfexp(SR_parm_work(3));
+        beta = mfexp(SR_parm_work(4));
+        SR_parm_byyr(y, 2) =  alpha * temp / (4. + alpha * temp);  //  implied steepness
+        SR_parm_byyr(y, 1) = log( 1. / beta * (alpha - (1. / temp)));  //  implied ln_R0
+      }
       Fishon = 1;
       Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation with current year's biology and F
       if (STD_Yr_Reverse_Ofish(y) > 0)
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index 22e1df1b..bda7f9ac 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1740,7 +1740,7 @@ FUNCTION void write_bigoutput()
     if (SR_fxn == 10)
     {
       SS2out << " Ln_alpha_parameter: " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
-      SS2out << " Ln_beta_parameter: " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
+      SS2out << " Ln_beta_parameter: " << SR_parm(4) << " beta " << mfexp(SR_parm(4));
     }
     else if (SR_fxn == 3)
     {
@@ -1764,9 +1764,7 @@ FUNCTION void write_bigoutput()
     {
       SS2out << " Ricker_Power: " << SR_parm(3);
     }
-
-    SS2out << endl;
-    SS2out << sigmaR << " sigmaR" << endl;
+    SS2out << endl << sigmaR << " sigmaR" << endl;
     SS2out << init_equ_steepness << "  # 0/1 to use steepness in initial equ recruitment calculation" << endl;
 
     SS2out << SR_parm(N_SRparm2 - 1) << " init_eq:  see below" << endl
@@ -1799,7 +1797,7 @@ FUNCTION void write_bigoutput()
     }
     SS2out << endl;
 
-    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev" << endl;
+    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SPR0 h R0" << endl;
     SS2out << "S/Rcurve " << SSB_virgin << " " << Recr_virgin << endl;
     y = styr - 2;
     SS2out << "Virg " << SSB_yr(y) << " " << exp_rec(y) << " - " << 0.0 << " Virg " << SSB_B_yr(y) << " " << SSB_N_yr(y) << " 0.0 " << endl;
@@ -1850,7 +1848,11 @@ FUNCTION void write_bigoutput()
       {
         SS2out << " _ _ Fixed";
       }
-      SS2out << endl;
+      temp = Smry_Table(y,11) / Recr_virgin;
+      alpha = mfexp(SR_parm_byyr(y,3));
+      beta = mfexp(SR_parm_byyr(y,4));
+      SS2out << " " << temp << " " << alpha * temp / (4. + alpha * temp) << " " << 1. / beta * (alpha - (1. / temp));
+      SS2out << SR_parm_byyr(y)(1,4) << endl;
     }
 
     // REPORT_KEYWORD SPAWN_RECR_CURVE
diff --git a/StockSynthesis.code-workspace b/StockSynthesis.code-workspace
index cdd30489..14159ac5 100644
--- a/StockSynthesis.code-workspace
+++ b/StockSynthesis.code-workspace
@@ -11,7 +11,8 @@
 			"*.htp": "c",
 			"ostream": "c",
 			"xlocale": "c",
-			"iosfwd": "c"
+			"iosfwd": "c",
+			"cmath": "c"
 		},
 		"explorer.excludeGitIgnore": true
 	}

From 43afa5139b7ca3279d5a7193da4c08d3a74547cc Mon Sep 17 00:00:00 2001
From: RickMethot <richard.methot@noaa.gov>
Date: Wed, 31 May 2023 09:40:07 -0700
Subject: [PATCH 06/29] WIP

---
 SS_benchfore.tpl | 19 ++++++++++++-------
 SS_recruit.tpl   |  5 ++++-
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 42b0b332..40f9bb89 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -748,18 +748,22 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   Recr_unf = mfexp(SR_parm_work(1));
   Do_Equil_Calc(Recr_unf);
   SSB_unf = SSB_equil;
-  report5<<" calc SSBunf "<<SSB_unf<<" recr "<<Recr_unf<<" work "<<SR_parm_work<<" parm "<<SR_parm<<endl;
-  SR_parm_work(N_SRparm2 + 1) = SSB_unf;
+  SPR_unfished = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
   if (show_MSY == 1)
+  {
     report5 << "SR_parm for benchmark: " << SR_parm_work << endl
-            << "for years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << "  SSB_virgin was: " << SSB_virgin << endl;
-  if (show_MSY == 1)
-    report5 << "Repro_output_by_age_for_morph_1: " << fec(1) << endl;
+            << "mean from years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << endl;
+    SPR_virgin = SSB_virgin / Recr_virgin;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Virgin SPR0, SSB, R: " << SPR_virgin << " " << Equ_SpawnRecr_Result << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Benchmark SPR0, SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << endl;
+  }
+  SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   Mgmt_quant(1) = SSB_unf;
   Mgmt_quant(2) = totbio;
   Mgmt_quant(3) = smrybio;
   Mgmt_quant(4) = Recr_unf;
-
   // find Fspr             SS_Label_710
   {
     if (show_MSY == 1)
@@ -905,6 +909,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     //  SPAWN-RECR:   calc equil spawn-recr in YPR; need to make this area-specific
     SPR_temp = SSB_equil;  //  based on most recent call to Do_Equil_Calc
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+         report5<<SPR_temp<<" " << Equ_SpawnRecr_Result<<endl;
 
     Bspr = Equ_SpawnRecr_Result(1);
     Bspr_rec = Equ_SpawnRecr_Result(2);
@@ -1113,8 +1118,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
         SPR_Btgt = SSB_equil / SPR_unfished;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
-    
         Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+         report5<<SPR_temp<<" " << Equ_SpawnRecr_Result<<endl;
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
 
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 86604f67..c24509c0 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -319,12 +319,15 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
+      SPR_virgin = SSB_virgin / Recr_virgin;
       alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
+      report5<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_virgin<<" SPR "<<SPR_virgin<<" steep "<<steepness<<endl;
       B_equil = (alpha * SPR_temp - 1.0) / beta;
+//      report5<<" spr "<<SPR_temp<<"  Beq "<<B_equil<<endl;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5<<" WHAM Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
+//      report5<<"  Beq "<<B_equil<<" Req "<<R_equil<<endl;
 //      R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil); //Beverton-Holt
 //      report5<<" SS3 Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
       break;

From d6316c4b583678afb9be3c0fc521e89eb50611b3 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Wed, 22 May 2024 16:11:03 -0700
Subject: [PATCH 07/29] working version with a,b

---
 SS_recruit.tpl      | 41 +++++++++++++++++++----------------------
 SS_write_report.tpl |  8 ++++----
 2 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index c24509c0..5553dd26 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -49,15 +49,19 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 3: // Beverton-Holt
     {
       steepness = SR_parm_work(2);
-//      dvariable SPR = SSB_virgin_adj / Recr_virgin;
-//      dvariable alpha = (4.0 * steepness) / ( SPR * (1. - steepness)) ;
-//      dvariable beta = (5.0 * steepness - 1.0 )/((1.0 - steepness ) * Recr_virgin * SPR );
-//      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
       NewRecruits = (4. * steepness * Recr_virgin_adj * SSB_curr_adj) /
           (SSB_virgin_adj * (1. - steepness) + (5. * steepness - 1.) * SSB_curr_adj);
       break;
     }
 
+      case 10: // Beverton-Holt with alpha beta  per WHAM:  R = A*S/(1+B*S)
+      {
+        alpha = mfexp(SR_parm_work(3));
+        beta = mfexp(SR_parm_work(4));
+        NewRecruits =  (alpha * SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
+        break;
+      }
+
     //  SS_Label_43.3.4  constant expected recruitment
     case 4: // none
     {
@@ -159,14 +163,6 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
       break;
     }
 
-      case 10: // Beverton-Holt with alpha beta
-      {
-  //  WHAM based on R = A*S/(1+B*S)
-        alpha = mfexp(SR_parm_work(3));
-        beta = mfexp(SR_parm_work(4));
-        NewRecruits =  (alpha * SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
-        break;
-      }
   }
   RETURN_ARRAYS_DECREMENT();
   return NewRecruits;
@@ -322,18 +318,19 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
       SPR_virgin = SSB_virgin / Recr_virgin;
       alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
-      report5<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_virgin<<" SPR "<<SPR_virgin<<" steep "<<steepness<<endl;
+
+//      report5 <<" SSB_unf "<<SSB_virgin<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin << endl;
+//      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
+//      report5 << " deriv_h: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SPR_virgin))<<endl;
       B_equil = (alpha * SPR_temp - 1.0) / beta;
-//      report5<<" spr "<<SPR_temp<<"  Beq "<<B_equil<<endl;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5<<"  Beq "<<B_equil<<" Req "<<R_equil<<endl;
-//      R_equil = (4. * steepness * Recr_virgin * B_equil) / (SSB_virgin * (1. - steepness) + (5. * steepness - 1.) * B_equil); //Beverton-Holt
-//      report5<<" SS3 Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
+//      report5 << "SPR_input: " << SPR_temp << " B_equil: " << B_equil << " R_equil: "<<R_equil << endl<<endl;
+
       break;
     }
 
-    case 10: // Beverton-Holt with alpha and beta parameterization using  R = A*S/(B+S) approach
+    case 10: // Beverton-Holt with alpha and beta parameterization using  R = A*S/(1+B*S) approach; same as WHAM
     {
       alpha = mfexp(SRparm(3));
       beta = mfexp(SRparm(4));
@@ -354,11 +351,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     //  SS_Label_44.1.5  Hockey Stick
     case 5: // hockey stick
     {
-      alpha = SRparm(3) * Recr_virgin; // min recruitment level
+      dvariable hockey_min = SRparm(3) * Recr_virgin; // min recruitment level
       //        temp=SSB_virgin/R0*steepness;  // spawners per recruit at inflection
-      beta = (Recr_virgin - alpha) / (steepness * SSB_virgin); //  slope of recruitment on spawners below the inflection
-      B_equil = Join_Fxn(0.0 * SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin * steepness, SPR_temp, alpha / ((1. / SPR_temp) - beta), SPR_temp * Recr_virgin);
-      R_equil = Join_Fxn(0.0 * SSB_virgin, SSB_virgin, SSB_virgin * steepness, B_equil, alpha + beta * B_equil, Recr_virgin);
+      dvariable hockey_slope = (Recr_virgin - hockey_min) / (steepness * SSB_virgin); //  slope of recruitment on spawners below the inflection
+      B_equil = Join_Fxn(0.0 * SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin * steepness, SPR_temp, hockey_min / ((1. / SPR_temp) - hockey_slope), SPR_temp * Recr_virgin);
+      R_equil = Join_Fxn(0.0 * SSB_virgin, SSB_virgin, SSB_virgin * steepness, B_equil, hockey_min + hockey_slope * B_equil, Recr_virgin);
       break;
     }
     //  SS_Label_44.1.7  3 parameter survival based
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index bda7f9ac..f1b33812 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1745,7 +1745,7 @@ FUNCTION void write_bigoutput()
     else if (SR_fxn == 3)
     {
       alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
-      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
+      beta = (5.0 * steepness - 1.0) / ((1. - steepness) * SSB_virgin);
       SS2out << " Ln_alpha_derived: " << log(alpha) << " alpha " << alpha << endl;
       SS2out << " Ln_beta_derived: " << log(beta) << " beta " << beta;
     }
@@ -1797,7 +1797,7 @@ FUNCTION void write_bigoutput()
     }
     SS2out << endl;
 
-    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SPR0 h R0" << endl;
+    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SSBe/R0 h R0" << endl;
     SS2out << "S/Rcurve " << SSB_virgin << " " << Recr_virgin << endl;
     y = styr - 2;
     SS2out << "Virg " << SSB_yr(y) << " " << exp_rec(y) << " - " << 0.0 << " Virg " << SSB_B_yr(y) << " " << SSB_N_yr(y) << " 0.0 " << endl;
@@ -1848,10 +1848,10 @@ FUNCTION void write_bigoutput()
       {
         SS2out << " _ _ Fixed";
       }
-      temp = Smry_Table(y,11) / Recr_virgin;
+      dvariable SPR = Smry_Table(y, 11) / Recr_virgin;
       alpha = mfexp(SR_parm_byyr(y,3));
       beta = mfexp(SR_parm_byyr(y,4));
-      SS2out << " " << temp << " " << alpha * temp / (4. + alpha * temp) << " " << 1. / beta * (alpha - (1. / temp));
+      SS2out << " " << SPR << " " << alpha * SPR / (4. + alpha * SPR) << " " << 1. / beta * (alpha - (1. / SPR));
       SS2out << SR_parm_byyr(y)(1,4) << endl;
     }
 

From 8558f5e207d35d1dc7c535ae404cc4cb3b981181 Mon Sep 17 00:00:00 2001
From: "Richard.Methot" <1365818351113302@mil>
Date: Tue, 28 May 2024 14:39:34 -0700
Subject: [PATCH 08/29] Update .gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index a8becca9..fac35ef1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@
 Compile/ss.tpl
 Compile/ss_opt.tpl
 Compile/ss_trans.tpl
+Compile/ss3.tpl
+Compile/Make_SS_warn.bat
 ~$*.*
 Compile/ss.log
 Compile/ss3.log

From 9886eb6edaaef28b47f0f66f3bf352cdfc2e3213 Mon Sep 17 00:00:00 2001
From: Rick-Methot-NOAA <richard.methot@noaa.gov>
Date: Wed, 12 Jun 2024 14:50:29 -0700
Subject: [PATCH 09/29] augment spawn_recr report and use to test time-vary
 SR_parm approach

---
 SS_benchfore.tpl       |  12 ++--
 SS_popdyn.tpl          |  18 ++++--
 SS_readcontrol_330.tpl |   9 +++
 SS_recruit.tpl         |  13 ++--
 SS_write_report.tpl    | 139 ++++++++++++++++++++++++++++++++++-------
 5 files changed, 156 insertions(+), 35 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 40f9bb89..c76438e0 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -753,7 +753,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   {
     report5 << "SR_parm for benchmark: " << SR_parm_work << endl
             << "mean from years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << endl;
-    SPR_virgin = SSB_virgin / Recr_virgin;
+    //  SPR_virgin = SSB_virgin / Recr_virgin;  // already defined
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     report5 << " Virgin SPR0, SSB, R: " << SPR_virgin << " " << Equ_SpawnRecr_Result << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
@@ -1906,15 +1906,15 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   }
   else if (show_MSY == 2) //  do brief output
   {
-    SS2out << SPR_actual / 100. << " " << SPR_Fmult << " " << Mgmt_quant(10) << " " << YPR_spr_dead / Vbio1_spr << " " << Bspr_rec << " "
+    report5 << SPR_actual / 100. << " " << SPR_Fmult << " " << Mgmt_quant(10) << " " << YPR_spr_dead / Vbio1_spr << " " << Bspr_rec << " "
            << Bspr << " " << YPR_spr_dead * Bspr_rec << " " << YPR_spr_ret * Bspr_rec
            << " " << Vbio1_spr * Bspr_rec << " # ";
 
-    SS2out << SPR_Btgt << " " << Btgt / SSB_unf << " " << Btgt_Fmult << " " << Mgmt_quant(7) << " " << YPR_Btgt_dead / Vbio1_Btgt << " " << Btgt_Rec << " "
+    report5 << SPR_Btgt << " " << Btgt / SSB_unf << " " << Btgt_Fmult << " " << Mgmt_quant(7) << " " << YPR_Btgt_dead / Vbio1_Btgt << " " << Btgt_Rec << " "
            << Btgt << " " << YPR_Btgt_dead * Btgt_Rec << " " << YPR_Btgt_ret * Btgt_Rec
            << " " << Vbio1_Btgt * Btgt_Rec << " # ";
 
-    SS2out << MSY_SPR << " " << Bmsy / SSB_unf << " " << MSY_Fmult << " " << Mgmt_quant(14) << " " << MSY / (Vbio1_MSY * Recr_msy) << " " << Recr_msy << " "
+    report5 << MSY_SPR << " " << Bmsy / SSB_unf << " " << MSY_Fmult << " " << Mgmt_quant(14) << " " << MSY / (Vbio1_MSY * Recr_msy) << " " << Recr_msy << " "
            << Bmsy << " " << MSY << " " << YPR_msy_dead * Recr_msy << " " << YPR_msy_ret * Recr_msy
            << " " << Vbio1_MSY * Recr_msy << " # " << endl;
   }
@@ -2576,6 +2576,7 @@ FUNCTION void Get_Forecast()
               }
             }
             //  SPAWN-RECR:   get recruitment in forecast;  needs to be area-specific
+            // SR_fxn
             if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
@@ -3212,7 +3213,8 @@ FUNCTION void Get_Forecast()
               }
             }
             //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass
-            //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specififc
+            //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
+            // SR_fxn
             if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index b2dd8299..3891000a 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -357,6 +357,7 @@ FUNCTION void get_initial_conditions()
       beta = mfexp(SR_parm(4));
       steepness = alpha * SPR_virgin / (4. + alpha * SPR_virgin);
       Recr_virgin = 1. / beta * (alpha - (1. / SPR_virgin));
+//      warning << " before AB_calcs " << "parm " << SR_parm(1) << " calc " << log(Recr_virgin) << endl;
       SR_parm(1) = log(Recr_virgin);
       SR_parm(2) = steepness;
     }
@@ -370,6 +371,8 @@ FUNCTION void get_initial_conditions()
     SR_parm_virg(i) = SR_parm(i);
     SR_parm_work(i) = SR_parm(i);
   }
+//  if (SR_fxn == 3) warning << "tester_A: " << SR_parm_work(1) << " base: " << SR_parm(1) << endl;
+//  if (SR_fxn == 10) warning << "tester_A: " << SR_parm_work(4) << " base: " << SR_parm(4) << endl;
     equ_Recr = Recr_virgin;
     exp_rec(eq_yr, 1) = Recr_virgin; //  expected Recr from s-r parms
     exp_rec(eq_yr, 2) = Recr_virgin;
@@ -476,6 +479,9 @@ FUNCTION void get_initial_conditions()
     else
     {
       SR_parm_work(f) = parm_timevary(SR_parm_timevary(f), eq_yr);
+//      warning << "tester_B: " << SR_parm_work(f) << " timevary " << " base " << SR_parm(f) <<endl;
+//      warning << parm_timevary(2) << endl;
+
     }
     SR_parm_byyr(eq_yr, f) = SR_parm_work(f);
   }
@@ -529,7 +535,7 @@ FUNCTION void get_initial_conditions()
     CrashPen += Equ_penalty;
     SPR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
     //  get equilibrium SSB and recruitment from SPR_temp, Recr_virgin and virgin steepness
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     R1_exp = Equ_SpawnRecr_Result(2); //  set the expected recruitment equal to this equilibrium
     exp_rec(eq_yr, 1) = R1_exp;
 
@@ -725,6 +731,7 @@ FUNCTION void get_time_series()
       else
       {
         SR_parm_work(f) = parm_timevary(SR_parm_timevary(f), y);
+//        warning << "tester_C: " << SR_parm_work(f) << " timevary_year " << endl;
       }
       SR_parm_byyr(y, f) = SR_parm_work(f);
     }
@@ -1017,6 +1024,7 @@ FUNCTION void get_time_series()
 
         //  SS_Label_Info_24.2.3 #Get the total recruitment produced by this spawning biomass
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
+        //  SR_Fxn  relevant keyword
         if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
         {
           R0_use = Recr_virgin;
@@ -1025,6 +1033,7 @@ FUNCTION void get_time_series()
         else
         {
           R0_use = mfexp(SR_parm_work(1));
+          warning << y << " set R0use to SRparm_work " << R0_use << " vir: " << Recr_virgin << endl;
           equ_Recr = R0_use;
           Fishon = 0;
           eq_yr = y;
@@ -1475,14 +1484,15 @@ FUNCTION void get_time_series()
         }
         //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
-        if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
+        //  SR_fxn
+        if (SR_update_SPR0 == 0) //  SR parms are not time-varying
         {
           R0_use = Recr_virgin;
           SSB_use = SSB_virgin;
         }
-        else
+        else  //  update SSB_use and R0_use where will update SPR0 inside the Spawn_recr fxn
         {
-          R0_use = mfexp(SR_parm_work(1));
+          R0_use = mfexp(SR_parm_work(1));  //  check to be sure this works when R0 is derived from B-H with alpha, beta parameters
           equ_Recr = R0_use;
           Fishon = 0;
           eq_yr = y;
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index b88046a0..edd7a3a7 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1656,6 +1656,7 @@
 
 !!//  SS_Label_Info_4.5.4 #Set up time-varying parameters for MG parms
   int timevary_used;
+  int timevary_MG_firstyr;
   int timevary_parm_cnt_MG;
   int timevary_parm_start_MG;
 
@@ -1704,6 +1705,7 @@
   timevary_parm_start_MG = 0;
   timevary_parm_cnt_MG = 0;
   timevary_used = 0;
+  timevary_MG_firstyr = YrMax;
   MGparm_timevary.initialize();
   ivector block_design_null(1, 1);
   block_design_null.initialize();
@@ -1804,6 +1806,7 @@
       {
         MG_active(f) = 1;
         timevary_MG(y, 0) = 1; // tracks active status for all MG types
+        if(timevary_MG_firstyr == YrMax) timevary_MG_firstyr = y;  // save for reporting in MSY and spawn_recruit output
       }
     }
     //  timevary growth or maturity and Maunder M refers to that maturity
@@ -1961,6 +1964,7 @@
   int timevary_parm_cnt_SR;
   ivector timevary_SRparm(styr-3,YrMax+1);
   ivector SR_parm_timevary(1,N_SRparm2);
+  int SR_update_SPR0  // 0/1 flag to control updating of SPR0 for timevary biology 
 
  LOCAL_CALCS
   // clang-format on
@@ -1972,6 +1976,8 @@
   SR_parm_timevary.initialize();
   SR_env_link = 0;
   SR_env_target = 0;
+  SR_update_SPR0 = 0;
+
   //#_SR_function: 1=null; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=Survival_3Parm; 10=B-H with a,b "<<endl;
   ParmLabel += "SR_LN(R0)";
   switch (SR_fxn)
@@ -2118,6 +2124,9 @@
         for (y = styr - 3; y <= YrMax + 1; y++) {
           timevary_SRparm(y) = timevary_pass(y);
         } // year vector for this category og MGparm
+        // special consideration for impact on spawner-recruitment SPR0 calculations
+        if (SR_fxn == 10 && (SR_parm_timevary(3) > 0 || SR_parm_timevary(4) > 0) )  {SR_update_SPR0 = 1;}  //  alpha or beta is time-varying
+        else if ((SR_parm_timevary(1) > 0 || SR_parm_timevary(2) > 0) )  {SR_update_SPR0 = 1;}  //  R0 or steepness is time-varying
       }
     }
   N_SRparm3 = N_SRparm2;
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 5553dd26..2065b277 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -22,6 +22,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
   dvariable SRZ_0;
   dvariable srz_min;
   dvariable SRZ_surv;
+//  warning << y << "  Tester_R0 " <<  Recr_virgin_adj << " SSB0 " << SSB_virgin_adj << " SSB_curr: " << SSB_current << endl;
 
   //  SS_Label_43.1  add 0.1 to input spawning biomass value to make calculation more rebust
   SSB_curr_adj = SSB_current + 0.100; // robust
@@ -56,8 +57,8 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
 
       case 10: // Beverton-Holt with alpha beta  per WHAM:  R = A*S/(1+B*S)
       {
-        alpha = mfexp(SR_parm_work(3));
-        beta = mfexp(SR_parm_work(4));
+        dvariable alpha = mfexp(SR_parm_work(3));
+        dvariable beta = mfexp(SR_parm_work(4));
         NewRecruits =  (alpha * SSB_curr_adj) / (1.0 + beta * SSB_curr_adj);
         break;
       }
@@ -315,10 +316,12 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
-      SPR_virgin = SSB_virgin / Recr_virgin;
+  //    SPR_virgin = SSB_virgin / Recr_virgin;  //  this is already defined
       alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
 
+      // " h " << steepness << " derive "  << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << endl;
+      // " R0 " << Recr_virgin << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
 //      report5 <<" SSB_unf "<<SSB_virgin<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin << endl;
 //      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
 //      report5 << " deriv_h: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SPR_virgin))<<endl;
@@ -332,8 +335,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
     case 10: // Beverton-Holt with alpha and beta parameterization using  R = A*S/(1+B*S) approach; same as WHAM
     {
-      alpha = mfexp(SRparm(3));
-      beta = mfexp(SRparm(4));
+      dvariable alpha = mfexp(SRparm(3));
+      dvariable beta = mfexp(SRparm(4));
       B_equil = (alpha * SPR_temp - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index f1b33812..c5b13169 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1730,26 +1730,14 @@ FUNCTION void write_bigoutput()
     var /= (n_rmse(1) + 1.0e-09);
 
     dvariable steepness = SR_parm(2);
+
     SS2out << endl
            << pick_report_name(19);
     SS2out << "  Function: " << SR_fxn << "  RecDev_method: " << do_recdev << "   sum_recdev: " << sum_recdev << endl
            << SR_parm(1) << " Ln(R0) " << mfexp(SR_parm(1)) << endl
-           << steepness << " steepness " << endl
+           << steepness << " steepness" << endl
            << Bmsy / SSB_virgin << " Bmsy/Bzero ";
-    SS2out << " SPR_virgin "<<SPR_virgin<<endl;
-    if (SR_fxn == 10)
-    {
-      SS2out << " Ln_alpha_parameter: " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
-      SS2out << " Ln_beta_parameter: " << SR_parm(4) << " beta " << mfexp(SR_parm(4));
-    }
-    else if (SR_fxn == 3)
-    {
-      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
-      beta = (5.0 * steepness - 1.0) / ((1. - steepness) * SSB_virgin);
-      SS2out << " Ln_alpha_derived: " << log(alpha) << " alpha " << alpha << endl;
-      SS2out << " Ln_beta_derived: " << log(beta) << " beta " << beta;
-    }
-    else if (SR_fxn == 8)
+    if (SR_fxn == 8)
     {
       dvariable Shepherd_c;
       dvariable Shepherd_c2;
@@ -1764,7 +1752,9 @@ FUNCTION void write_bigoutput()
     {
       SS2out << " Ricker_Power: " << SR_parm(3);
     }
-    SS2out << endl << sigmaR << " sigmaR" << endl;
+
+    SS2out << endl;
+    SS2out << sigmaR << " sigmaR" << endl;
     SS2out << init_equ_steepness << "  # 0/1 to use steepness in initial equ recruitment calculation" << endl;
 
     SS2out << SR_parm(N_SRparm2 - 1) << " init_eq:  see below" << endl
@@ -1797,7 +1787,114 @@ FUNCTION void write_bigoutput()
     }
     SS2out << endl;
 
-    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SSBe/R0 h R0" << endl;
+    SS2out << endl << "#New_Expanded_Spawn_Recr_report" << endl << pick_report_name(19) << endl;
+    SS2out << "SR_Function: " << SR_fxn << endl;
+    SS2out << "#" << endl << "parm  parm_label value phase" << endl;
+    for (int j = 1; j <=N_SRparm2; j++)
+    {
+      SS2out << j << " " << ParmLabel(firstSRparm + j) << " " << SR_parm(j) << " " << SR_parm_PH(j);
+      if (SR_parm_timevary(j) > 0 && j <= 4 ) //  timevary SRparm exists
+      {SS2out << " #_is_time_vary,_so_SRR_updates_base_SPR_annually";} 
+  if (j == (N_SRparm2 - 1) && SR_parm_timevary(j) > 0) //  timevary regime exists
+    {SS2out << " #_Persistent_deviations_from_SRR_(e.g.regimes)_exist";}
+      SS2out << endl;
+    }
+
+    SS2out << "# " <<endl;
+    SS2out << "sigmaR: "<< sigmaR  << endl;
+    SS2out << "SPR_virgin: " << SPR_virgin << " #_uses_biology_from_start_year: " << styr <<endl;
+
+    switch (SR_fxn)
+    {
+      case 3: // Beverton-Holt with steepness
+    {
+      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+      beta = (5.0 * steepness - 1.0) / ((1. - steepness) * SSB_virgin);
+      SS2out << "Ln(R0): " << SR_parm(1) << endl << "R0: " << mfexp(SR_parm(1)) << endl;
+      SS2out << "steepness: " << steepness << endl;
+      SS2out << "Ln(alpha)_derived: " << log(alpha) << " alpha " << alpha << endl;
+      SS2out << "Ln(beta)_derived: " << log(beta) << " beta " << beta;
+      break;
+    }
+      case 10: // Beverton-Holt with alpha, beta
+    {
+      SS2out << "Ln(alpha): " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
+      SS2out << "Ln(beta): " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
+      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << SR_parm(3) << endl;  // steepness virgin
+      SS2out << "R0_derived: " << 1. / beta * (alpha - (1. / SPR_virgin)) << " " << SR_parm(1) << endl;  //  virgin R0
+      break;
+    }
+    case 8:
+    {
+      dvariable Shepherd_c;
+      dvariable Shepherd_c2;
+      dvariable Hupper;
+      Shepherd_c = SR_parm(3);
+      Shepherd_c2 = pow(0.2, Shepherd_c);
+      Hupper = 1.0 / (5.0 * Shepherd_c2);
+      temp = 0.2 + (SR_parm(2) - 0.2) / (0.8) * (Hupper - 0.2);
+      SS2out << " Shepherd_c: " << Shepherd_c << " steepness_limit: " << Hupper << " Adjusted_steepness: " << temp << endl;
+      break;
+    }
+    case 9:
+    {
+      SS2out << " Ricker_Parm1: " << SR_parm(1) << endl;
+      SS2out << " Ricker_Parm2: " << SR_parm(2) << endl;
+      SS2out << " Ricker_Power: " << SR_parm(3) << endl;
+      break;
+    }
+    default:
+    {
+      SS2out << "default output needed " << endl;
+      break;
+    }
+    }
+
+    SS2out << endl << "#" << endl << "Quantities for MSY and other benchmark calculations " << endl << "Benchmark_years: 1_beg_bio 2_end_bio 3_beg_selex 4_end_selex 5_beg_relF 6_end_relF 7_beg_recr_dist 8_end_recr_dist 9_beg_SRparm 10_end_SRparm" << endl;
+    SS2out << "Benchmark_years: " << Bmark_Yr << endl;
+    if( timevary_MG_firstyr == YrMax)
+    { SS2out << "No_timevary_biology " << endl; }
+    else
+    { SS2out << "First_year_with_timevary_MG: " << timevary_MG_firstyr << endl; }
+    for ( int k = 1; k <=9; k+=2) 
+    { if (Bmark_Yr(k+1) > Bmark_Yr(k))
+      {SS2out << "#_range_of_years_is_averaged,_so_reduces_standard_error_of_result;_do_this_only_when_timevarying_makes_necessary:  " << k << " "<< k+1 << endl;}
+    }
+    SS2out << "SPR_unfished_benchmark: " << Mgmt_quant(1) / Mgmt_quant(4) << "  #_based_on_averaging_biology_over_benchmark_year_range " << endl;
+    SS2out << "Bmsy/Bzero: "<< Bmsy / SSB_virgin  << " # using styr bio for Bzero" << endl;
+    SS2out << "Bmsy/Bunf: "<< Bmsy / Mgmt_quant(1)  << " # using MSY's averaged bio for Bunf" << endl;
+
+    SS2out << "#" << endl << "RecDev_method: " << do_recdev << endl << "sum_recdev: " << sum_recdev << endl << "recr_logL: " << recr_like << endl;
+    SS2out << recdev_start << " " << recdev_end << " main_recdev:start_end" << endl
+           << recdev_adj(1) << " " << recdev_adj(2, 5) << " breakpoints_for_bias_adjustment_ramp " << endl;
+
+    temp = sigmaR * sigmaR; //  sigmaR^2
+    SS2out << "ERA    N    RMSE  RMSE^2/sigmaR^2  mean_BiasAdj est_rho Durbin-Watson" << endl;
+    SS2out << "main  " << n_rmse(1) << " " << rmse(1) << " " << square(rmse(1)) / temp << " " << rmse(2) << " " << cross / var << " " << Durbin;
+    if (wrote_bigreport == 0) //  first time writing bigreport
+    {
+      if (rmse(1) < 0.5 * sigmaR && rmse(2) > (0.01 + 2.0 * square(rmse(1)) / temp))
+      {
+        warnstream << "Main recdev biasadj is >2 times ratio of rmse to sigmaR";
+        SS2out << " # " << warnstream.str() ;
+        write_message (WARN, 0);
+      }
+    }
+    SS2out << endl;
+
+    SS2out << "early " << n_rmse(3) << " " << rmse(3) << " " << square(rmse(3)) / temp << " " << rmse(4);
+    if (wrote_bigreport == 0) //  first time writing bigreport
+    {
+      if (rmse(3) < 0.5 * sigmaR && rmse(4) > (0.01 + 2.0 * square(rmse(3)) / temp))
+      {
+        warnstream << "Early recdev biasadj is >2 times ratio of rmse to sigmaR";
+        SS2out << " # " << warnstream.str();
+        write_message (WARN, 0);
+      }
+    }
+    SS2out << endl  << "#" << endl << "Initial_equilibrium: " << init_equ_steepness << "  # 0/1_to_use_spawner-recruitment_in_initial_equ_recruitment_calculation" << endl << "#" << endl;
+
+    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SPR0_curr h_curr R0_curr P1 P2 P3 P4" << endl;
     SS2out << "S/Rcurve " << SSB_virgin << " " << Recr_virgin << endl;
     y = styr - 2;
     SS2out << "Virg " << SSB_yr(y) << " " << exp_rec(y) << " - " << 0.0 << " Virg " << SSB_B_yr(y) << " " << SSB_N_yr(y) << " 0.0 " << endl;
@@ -1848,10 +1945,10 @@ FUNCTION void write_bigoutput()
       {
         SS2out << " _ _ Fixed";
       }
-      dvariable SPR = Smry_Table(y, 11) / Recr_virgin;
-      alpha = mfexp(SR_parm_byyr(y,3));
-      beta = mfexp(SR_parm_byyr(y,4));
-      SS2out << " " << SPR << " " << alpha * SPR / (4. + alpha * SPR) << " " << 1. / beta * (alpha - (1. / SPR));
+      dvariable SPR_curr = Smry_Table(y, 11) / Recr_virgin;
+      SS2out << " " << SPR_curr << " ";
+      SS2out << alpha * SPR_curr / (4. + alpha * SPR_curr) << " ";  // steepness with current SPR
+      SS2out << 1. / beta * (alpha - (1. / SPR_curr)) << " ";  //  R0 with current SPR
       SS2out << SR_parm_byyr(y)(1,4) << endl;
     }
 

From a9b353d42a74af9011c1b4011a9ae9f0b646a96d Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 08:46:20 -0400
Subject: [PATCH 10/29] try downgrading qemu

---
 .github/workflows/build-ss3.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index 108c745e..1d944ce7 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -217,6 +217,8 @@ jobs:
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
+          curl -OSL https://raw.githubusercontent.com/Homebrew/homebrew-core/dc0669eca9479e9eeb495397ba3a7480aaa45c2e/Formula/qemu.rb
+          brew install ./qemu.rb
           brew install docker
           colima start
           docker pull johnoel/admb-13.2:linux

From d3d0fb9f26245a5001cfbd079bc1429e97af2307 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:01:54 -0400
Subject: [PATCH 11/29] try previous version of colima

---
 .github/workflows/build-ss3.yml | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index 1d944ce7..83cf7228 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -217,8 +217,9 @@ jobs:
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
-          curl -OSL https://raw.githubusercontent.com/Homebrew/homebrew-core/dc0669eca9479e9eeb495397ba3a7480aaa45c2e/Formula/qemu.rb
-          brew install ./qemu.rb
+          brew uninstall colima
+          sudo mkdir -p /usr/local/bin
+          sudo curl -L -o /usr/local/bin/colima https://github.com/abiosoft/colima/releases/download/v0.6.8/colima-Darwin-x86_64 && sudo chmod +x /usr/local/bin/colima
           brew install docker
           colima start
           docker pull johnoel/admb-13.2:linux

From 123f5aa2d4e36ce104e1f0273f1219e37dbaaf25 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:09:43 -0400
Subject: [PATCH 12/29] where colima

---
 .github/workflows/build-ss3.yml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index 83cf7228..8bb5448b 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -217,9 +217,8 @@ jobs:
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
-          brew uninstall colima
-          sudo mkdir -p /usr/local/bin
-          sudo curl -L -o /usr/local/bin/colima https://github.com/abiosoft/colima/releases/download/v0.6.8/colima-Darwin-x86_64 && sudo chmod +x /usr/local/bin/colima
+          brew update
+          brew where colima
           brew install docker
           colima start
           docker pull johnoel/admb-13.2:linux

From 9d23824fe05321e58c362ea3926457bf2016e047 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:12:38 -0400
Subject: [PATCH 13/29] fix where

---
 .github/workflows/build-ss3.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index 8bb5448b..f8d3cebc 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -218,7 +218,7 @@ jobs:
         if: matrix.config.os == 'macos-12'
         run: |
           brew update
-          brew where colima
+          where colima
           brew install docker
           colima start
           docker pull johnoel/admb-13.2:linux

From 8deb43345de04efe6a8c73c15c67991c7d5d4932 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:22:32 -0400
Subject: [PATCH 14/29] try brew upgrade and --cpu-type max

---
 .github/workflows/build-ss3.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index f8d3cebc..da6b93e8 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -218,9 +218,9 @@ jobs:
         if: matrix.config.os == 'macos-12'
         run: |
           brew update
-          where colima
+          brew upgrade
           brew install docker
-          colima start
+          colima start --arch x86_64 --cpu-type max
           docker pull johnoel/admb-13.2:linux
 
           rm -rf SS330

From f74c36f1f976757bee9857095000f05e1932ff61 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:33:33 -0400
Subject: [PATCH 15/29] remove brew upgrade

---
 .github/workflows/build-ss3.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index da6b93e8..e3d4a1f3 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -217,8 +217,6 @@ jobs:
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
-          brew update
-          brew upgrade
           brew install docker
           colima start --arch x86_64 --cpu-type max
           docker pull johnoel/admb-13.2:linux

From 0468430ef93245adc3c39558e3a6954c8f76884a Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 09:42:25 -0400
Subject: [PATCH 16/29] try colima delete and reinstall

---
 .github/workflows/build-ss3.yml | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index e3d4a1f3..8784588d 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -217,8 +217,11 @@ jobs:
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
+          brew update
+          colima delete
+          brew reinstall colima
           brew install docker
-          colima start --arch x86_64 --cpu-type max
+          colima start --arch x86_64
           docker pull johnoel/admb-13.2:linux
 
           rm -rf SS330

From f422412af05216471de3751067b5f2150cd9b4e3 Mon Sep 17 00:00:00 2001
From: e-perl-NOAA <elizabeth.gugliotti@noaa.gov>
Date: Thu, 13 Jun 2024 10:49:52 -0400
Subject: [PATCH 17/29] update comments

---
 .github/workflows/build-ss3.yml | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/build-ss3.yml b/.github/workflows/build-ss3.yml
index 8784588d..0c1108c4 100644
--- a/.github/workflows/build-ss3.yml
+++ b/.github/workflows/build-ss3.yml
@@ -213,7 +213,6 @@ jobs:
           mv SS330/ss3.exe SS330/ss3_win.exe
           mv SS330/ss3_opt.exe SS330/ss3_opt_win.exe
 
-
       - name: Build stock synthesis for mac with admb docker image
         if: matrix.config.os == 'macos-12'
         run: |
@@ -233,8 +232,12 @@ jobs:
 
           colima stop
 
+        # brew update and colima uninstall and re-install needed to get colima 
+        # to work with macOS-12 runner updates
+
         # Once macos-12 no longer is kept up by GitHub actions, we will have to 
-        # build from source the macos-13 and the macos-14 x86_64 images to make versions
+        # build from source the macos-13 (or figure out how to get docker image
+        # to work with macos-13 and the macos-14 x86_64 images to make versions
         # compatible with x86_64 machines
 
       - name: Build stock synthesis for mac m2 with admb docker image

From 24c1260450370c9fe264645d6f4919e110769fb9 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Wed, 26 Jun 2024 15:05:50 -0700
Subject: [PATCH 18/29] adding benchmark change

---
 SS_benchfore.tpl    | 4 ++--
 SS_write_report.tpl | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index c76438e0..13db227f 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -1340,7 +1340,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       MSY_SPR = SSB_equil / SPR_unfished;
       SPR_temp = SSB_equil;
       Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-      Bmsy = Equ_SpawnRecr_Result(1);
+      Bmsy = Equ_SpawnRecr_Result(1);  //  with MSY set to SPR, not directly estimated
       Recr_msy = Equ_SpawnRecr_Result(2);
       yld1(1) = YPR_opt * Recr_msy;
       YPR_msy_enc = YPR_enc;
@@ -1433,7 +1433,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           MSY_SPR = SSB_equil / SPR_unfished;
           SPR_temp = SSB_equil;
           Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-          Bmsy = Equ_SpawnRecr_Result(1);
+          Bmsy = Equ_SpawnRecr_Result(1);  //  MSY is directly estimated
           Recr_msy = Equ_SpawnRecr_Result(2);
           Profit = (PricePerF * YPR_val_vec) * Recr_msy - Cost;
           if (Do_MSY == 2) //  dead catch without excluded bycatch fleets
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index c5b13169..66963485 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1802,7 +1802,7 @@ FUNCTION void write_bigoutput()
 
     SS2out << "# " <<endl;
     SS2out << "sigmaR: "<< sigmaR  << endl;
-    SS2out << "SPR_virgin: " << SPR_virgin << " #_uses_biology_from_start_year: " << styr <<endl;
+    SS2out << "SPR0_(virgin): " << SPR_virgin << " #_uses_biology_from_start_year: " << styr <<endl;
 
     switch (SR_fxn)
     {
@@ -1820,8 +1820,8 @@ FUNCTION void write_bigoutput()
     {
       SS2out << "Ln(alpha): " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
       SS2out << "Ln(beta): " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
-      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << SR_parm(3) << endl;  // steepness virgin
-      SS2out << "R0_derived: " << 1. / beta * (alpha - (1. / SPR_virgin)) << " " << SR_parm(1) << endl;  //  virgin R0
+      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << endl;  // steepness virgin
+      SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SPR_virgin))) << endl;  //  virgin R0
       break;
     }
     case 8:

From 37a4ac97f69ebae928dba76ee2cfff600bfcf943 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Wed, 3 Jul 2024 15:30:57 -0700
Subject: [PATCH 19/29] format changes for spawn_recr report

---
 SS_readcontrol_330.tpl |  6 +++++-
 SS_write_report.tpl    | 40 ++++++++++++++++++++++++----------------
 2 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index edd7a3a7..fbf18704 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1979,7 +1979,11 @@
   SR_update_SPR0 = 0;
 
   //#_SR_function: 1=null; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=Survival_3Parm; 10=B-H with a,b "<<endl;
-  ParmLabel += "SR_LN(R0)";
+  if (SR_fxn == 10)
+  {ParmLabel += "SR_LN(R0)_derived";}
+  else
+  {ParmLabel += "SR_LN(R0)";}
+  
   switch (SR_fxn)
   {
     case 1: // previous placement for B-H constrained
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index 66963485..aec89f6d 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1789,6 +1789,7 @@ FUNCTION void write_bigoutput()
 
     SS2out << endl << "#New_Expanded_Spawn_Recr_report" << endl << pick_report_name(19) << endl;
     SS2out << "SR_Function: " << SR_fxn << endl;
+    SS2out << "N_SRparms: " << N_SRparm2 << endl;
     SS2out << "#" << endl << "parm  parm_label value phase" << endl;
     for (int j = 1; j <=N_SRparm2; j++)
     {
@@ -1796,7 +1797,7 @@ FUNCTION void write_bigoutput()
       if (SR_parm_timevary(j) > 0 && j <= 4 ) //  timevary SRparm exists
       {SS2out << " #_is_time_vary,_so_SRR_updates_base_SPR_annually";} 
   if (j == (N_SRparm2 - 1) && SR_parm_timevary(j) > 0) //  timevary regime exists
-    {SS2out << " #_Persistent_deviations_from_SRR_(e.g.regimes)_exist";}
+    {SS2out << " #_Regime_parameter_used_to_offset_from_SRR";}
       SS2out << endl;
     }
 
@@ -1820,8 +1821,8 @@ FUNCTION void write_bigoutput()
     {
       SS2out << "Ln(alpha): " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
       SS2out << "Ln(beta): " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
-      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << endl;  // steepness virgin
       SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SPR_virgin))) << endl;  //  virgin R0
+      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << endl;  // steepness virgin
       break;
     }
     case 8:
@@ -1833,19 +1834,12 @@ FUNCTION void write_bigoutput()
       Shepherd_c2 = pow(0.2, Shepherd_c);
       Hupper = 1.0 / (5.0 * Shepherd_c2);
       temp = 0.2 + (SR_parm(2) - 0.2) / (0.8) * (Hupper - 0.2);
-      SS2out << " Shepherd_c: " << Shepherd_c << " steepness_limit: " << Hupper << " Adjusted_steepness: " << temp << endl;
-      break;
-    }
-    case 9:
-    {
-      SS2out << " Ricker_Parm1: " << SR_parm(1) << endl;
-      SS2out << " Ricker_Parm2: " << SR_parm(2) << endl;
-      SS2out << " Ricker_Power: " << SR_parm(3) << endl;
+      SS2out << "Shepherd_c: " << Shepherd_c << endl << "Shepard_steepness_limit: " << Hupper << endl << "Shepard_adjusted_steepness: " << temp << endl;
       break;
     }
     default:
     {
-      SS2out << "default output needed " << endl;
+      SS2out << "other_SRR " << endl;
       break;
     }
     }
@@ -1865,8 +1859,8 @@ FUNCTION void write_bigoutput()
     SS2out << "Bmsy/Bunf: "<< Bmsy / Mgmt_quant(1)  << " # using MSY's averaged bio for Bunf" << endl;
 
     SS2out << "#" << endl << "RecDev_method: " << do_recdev << endl << "sum_recdev: " << sum_recdev << endl << "recr_logL: " << recr_like << endl;
-    SS2out << recdev_start << " " << recdev_end << " main_recdev:start_end" << endl
-           << recdev_adj(1) << " " << recdev_adj(2, 5) << " breakpoints_for_bias_adjustment_ramp " << endl;
+    SS2out << "main_recdev:start_end: " << recdev_start << " " << recdev_end << endl
+           << "breakpoints_for_bias_adjustment_ramp: " <<recdev_adj(1,4) << endl << "max_bias_adj: " << recdev_adj(5) <<  endl;
 
     temp = sigmaR * sigmaR; //  sigmaR^2
     SS2out << "ERA    N    RMSE  RMSE^2/sigmaR^2  mean_BiasAdj est_rho Durbin-Watson" << endl;
@@ -1893,8 +1887,17 @@ FUNCTION void write_bigoutput()
       }
     }
     SS2out << endl  << "#" << endl << "Initial_equilibrium: " << init_equ_steepness << "  # 0/1_to_use_spawner-recruitment_in_initial_equ_recruitment_calculation" << endl << "#" << endl;
-
-    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SPR0_curr h_curr R0_curr P1 P2 P3 P4" << endl;
+    if (SR_fxn == 10) SS2out << "#_Note:_h_curr_and_R0_curr_are_for_info_only;_calculated_from_alpha_beta_and_current_SPR0" << endl;
+    SS2out << "#_columns_with_P_will_show_time_vary_SR_parameters" << endl << "#" << endl;
+    SS2out << "Yr SpawnBio exp_recr with_regime bias_adjusted pred_recr dev biasadjuster era mature_bio mature_num raw_dev SPR0_curr ";
+    if(SR_fxn == 10)
+    {SS2out << "h_curr R0_curr ";}
+    else
+    {SS2out << "NA1 NA2 ";}
+;
+    for (j = 1; j <= N_SRparm2; j++) 
+    {SS2out << "P" << j << " ";}
+    SS2out << endl;
     SS2out << "S/Rcurve " << SSB_virgin << " " << Recr_virgin << endl;
     y = styr - 2;
     SS2out << "Virg " << SSB_yr(y) << " " << exp_rec(y) << " - " << 0.0 << " Virg " << SSB_B_yr(y) << " " << SSB_N_yr(y) << " 0.0 " << endl;
@@ -1947,9 +1950,14 @@ FUNCTION void write_bigoutput()
       }
       dvariable SPR_curr = Smry_Table(y, 11) / Recr_virgin;
       SS2out << " " << SPR_curr << " ";
+      if (SR_fxn == 10)
+      {
       SS2out << alpha * SPR_curr / (4. + alpha * SPR_curr) << " ";  // steepness with current SPR
       SS2out << 1. / beta * (alpha - (1. / SPR_curr)) << " ";  //  R0 with current SPR
-      SS2out << SR_parm_byyr(y)(1,4) << endl;
+      }
+      else
+      {SS2out << " - - ";}
+      SS2out << SR_parm_byyr(y)(1,N_SRparm2) << endl;
     }
 
     // REPORT_KEYWORD SPAWN_RECR_CURVE

From b67a60e8950f5a55355952d38fea664c314ec800 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Tue, 9 Jul 2024 15:13:53 -0700
Subject: [PATCH 20/29] fixes to ss_warn

---
 Compile/Make_SS_warn.bat | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Compile/Make_SS_warn.bat b/Compile/Make_SS_warn.bat
index 3fdb0d20..af9b1430 100644
--- a/Compile/Make_SS_warn.bat
+++ b/Compile/Make_SS_warn.bat
@@ -19,15 +19,15 @@ cd Compile
 
 if exist ss3.exe (
   if exist ss3_old.exe (
-    del ss3old.exe
+    del ss3_old.exe
   )
   ren ss3.exe ss3_old.exe
 )
 
 tpl2cpp ss3
 
-g++ -c -std=c++14 -O2 -D_FILE_OFFSET_BITS=64  -DUSE_ADMB_CONTRIBS -D_USE_MATH_DEFINES -I. -I"C:\ADMB-13.1\include" -I"C:\ADMB-13.1\include\contrib" -Wall -Wextra -o ss3.obj ss3.cpp
+g++ -c -std=c++17 -O2 -D_FILE_OFFSET_BITS=64  -DUSE_ADMB_CONTRIBS -D_USE_MATH_DEFINES -I. -I"C:\ADMB-13.2\include" -I"C:\ADMB-13.2\include\contrib" -Wall -Wextra -o ss3.obj ss3.cpp
 
-g++ -static -o ss3.exe ss3.obj "C:\ADMB-13.1\lib\libadmb-contrib-mingw64-g++8.a"
+g++ -static -o ss3.exe ss3.obj "C:\ADMB-13.2\lib\libadmb-contrib-mingw64-g++13.a"
 
 dir *.exe

From 0666d6fa5a6386a3b761a55e7aaf9c8842a4b8d2 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Tue, 13 Aug 2024 20:06:06 -0700
Subject: [PATCH 21/29] WIP-more work needed on benchmark calcs

---
 SS_benchfore.tpl    | 30 ++++++++++++++++++++------
 SS_param.tpl        |  1 +
 SS_popdyn.tpl       | 21 +++++++++---------
 SS_recruit.tpl      | 52 ++++++++++++++++++++++-----------------------
 SS_write_report.tpl |  6 +++---
 5 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 13db227f..8bb12412 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -744,6 +744,18 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       SR_parm_work(j) = temp / (Bmark_Yr(10) - Bmark_Yr(9) + 1.);
     }
   }
+
+  if(SR_fxn == 10)  //  B-H with alpha, beta
+  {
+      alpha = mfexp(SR_parm_work(3));
+      beta = mfexp(SR_parm_work(4));
+      Fishon = 0;
+      Recr_unf = 1.0;
+      Do_Equil_Calc(Recr_unf);
+      SPR_virgin_adj = SSB_equil / 1.0;
+      SR_parm_work(2) = alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj);  // steepness
+      SR_parm_work(1) = log(1. / beta * (alpha - (1. / SPR_virgin_adj)));  // ln(R0)
+  }
   Fishon = 0;
   Recr_unf = mfexp(SR_parm_work(1));
   Do_Equil_Calc(Recr_unf);
@@ -751,13 +763,17 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   SPR_unfished = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
   if (show_MSY == 1)
   {
-    report5 << "SR_parm for benchmark: " << SR_parm_work << endl
+    report5 << "SR_parms for benchmark: " << SR_parm_work << endl
             << "mean from years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << endl;
     //  SPR_virgin = SSB_virgin / Recr_virgin;  // already defined
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Virgin SPR0, SSB, R: " << SPR_virgin << " " << Equ_SpawnRecr_Result << endl;
+    report5 << " Virgin SSB, R0: " << SSB_virgin << " " << Recr_virgin << " "  << SPR_virgin_adj << endl;
+    report5 << " unfished SSB, R0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unfished << " with current biology " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_virgin_adj); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Virgin SPR0, result_SSB, R: " << SPR_virgin_adj << " " << Equ_SpawnRecr_Result << endl << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SPR0, SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << endl;
+    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << endl << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << " with virgin spawn-recr " << endl;
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   Mgmt_quant(1) = SSB_unf;
@@ -1930,7 +1946,7 @@ FUNCTION void Get_Forecast()
   dvariable OFL_catch;
   dvariable Fcast_Crash;
   dvariable totcatch;
-  dvariable R0_use;
+  dvariable R0_use;  // annually updated variable if SR_update_SPR0 == 1
   dvariable SSB_use;
   dvar_matrix catage_w(1, gmorph, 0, nages);
   dvar_vector tempcatch(1, Nfleet);
@@ -2577,7 +2593,7 @@ FUNCTION void Get_Forecast()
             }
             //  SPAWN-RECR:   get recruitment in forecast;  needs to be area-specific
             // SR_fxn
-            if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
+            if (SR_update_SPR0 == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
               SSB_use = SSB_virgin;
@@ -3215,7 +3231,7 @@ FUNCTION void Get_Forecast()
             //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass
             //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
             // SR_fxn
-            if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
+            if (SR_update_SPR0 == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
               SSB_use = SSB_virgin;
diff --git a/SS_param.tpl b/SS_param.tpl
index bd21a12b..3d000222 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -166,6 +166,7 @@ PARAMETER_SECTION
   number half_sigmaRsq;
   number sigmaR;
   number SPR_virgin;
+  number SPR_virgin_adj;
   number regime_change;
   number rho;
   number dirichlet_Parm;
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index 3891000a..2f0213c5 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -344,7 +344,7 @@ FUNCTION void get_initial_conditions()
     equ_Recr = 1.0;
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation.  Returns SPR because R = 1.0
     SPR_virgin = SSB_equil; //  spawners per recruit.  Needed for Sr_fxn = 10
-
+    SPR_virgin_adj = SSB_equil;
     if(SR_fxn == 10)  // B-H with a,b
     {
   //  WHAM based on R = A*S/(1+B*S)
@@ -355,8 +355,8 @@ FUNCTION void get_initial_conditions()
 
       alpha = mfexp(SR_parm(3));
       beta = mfexp(SR_parm(4));
-      steepness = alpha * SPR_virgin / (4. + alpha * SPR_virgin);
-      Recr_virgin = 1. / beta * (alpha - (1. / SPR_virgin));
+      steepness = alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj);
+      Recr_virgin = 1. / beta * (alpha - (1. / SPR_virgin_adj));
 //      warning << " before AB_calcs " << "parm " << SR_parm(1) << " calc " << log(Recr_virgin) << endl;
       SR_parm(1) = log(Recr_virgin);
       SR_parm(2) = steepness;
@@ -380,7 +380,7 @@ FUNCTION void get_initial_conditions()
     exp_rec(eq_yr, 4) = Recr_virgin;
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
     SSB_virgin = SSB_equil;
-    SPR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit
+//    SPR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit already calculated
     if(Do_Benchmark==0)
     {
       Mgmt_quant(1)=SSB_virgin;
@@ -696,7 +696,7 @@ FUNCTION void get_time_series()
   dvariable crashtemp1;
   dvariable interim_tot_catch;
   dvariable Z_adjuster;
-  dvariable R0_use;
+  dvariable R0_use;  // annually updated variable if SR_update_SPR0 == 1; gets passed to Spawn_Recr() function
   dvariable SSB_use;
 
   if (Do_Morphcomp > 0)
@@ -1022,10 +1022,10 @@ FUNCTION void get_time_series()
           }
         }
 
-        //  SS_Label_Info_24.2.3 #Get the total recruitment produced by this spawning biomass
+        //  SS_Label_Info_24.2.3 #Get the total recruitment produced by this spawning biomass at the beginning of the season
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
         //  SR_Fxn  relevant keyword
-        if (SR_parm_timevary(1) == 0) //  R0 is not time-varying
+        if (SR_update_SPR0 == 0) //  SRparm are not time-varying
         {
           R0_use = Recr_virgin;
           SSB_use = SSB_virgin;
@@ -1033,12 +1033,12 @@ FUNCTION void get_time_series()
         else
         {
           R0_use = mfexp(SR_parm_work(1));
-          warning << y << " set R0use to SRparm_work " << R0_use << " vir: " << Recr_virgin << endl;
           equ_Recr = R0_use;
           Fishon = 0;
           eq_yr = y;
           bio_yr = y;
           Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation
+          SSB_use = SSB_equil;
           if (fishery_on_off == 1)
           {
             Fishon = 1;
@@ -1047,7 +1047,6 @@ FUNCTION void get_time_series()
           {
             Fishon = 0;
           }
-          SSB_use = SSB_equil;
         }
         Recruits = Spawn_Recr(SSB_use, R0_use, SSB_current); // calls to function Spawn_Recr
         if (SR_fxn != 7) apply_recdev(Recruits, R0_use); //  apply recruitment deviation
@@ -1482,7 +1481,7 @@ FUNCTION void get_time_series()
             SSB_yr(y) = SSB_current;
           }
         }
-        //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass
+        //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass at some time during the season
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
         //  SR_fxn
         if (SR_update_SPR0 == 0) //  SR parms are not time-varying
@@ -1498,6 +1497,7 @@ FUNCTION void get_time_series()
           eq_yr = y;
           bio_yr = y;
           Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation
+          SSB_use = SSB_equil;
           if (fishery_on_off == 1)
           {
             Fishon = 1;
@@ -1506,7 +1506,6 @@ FUNCTION void get_time_series()
           {
             Fishon = 0;
           }
-          SSB_use = SSB_equil;
         }
 
         Recruits = Spawn_Recr(SSB_use, R0_use, SSB_current); // calls to function Spawn_Recr
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 2065b277..179ecd6e 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -268,7 +268,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
  /*  SS_Label_FUNCTION 44 Equil_Spawn_Recr_Fxn */
 //  SPAWN-RECR:   function  Equil_Spawn_Recr_Fxn
 FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
-    const prevariable& SSB_virgin, const prevariable& Recr_virgin, const prevariable& SPR_temp)
+    const prevariable& SSB_temp, const prevariable& RECR_temp, const prevariable& SPR_temp)
   {
   RETURN_ARRAYS_INCREMENT();
   dvar_vector Equil_Spawn_Recr_Calc(1, 2); // values to return 1 is B_equil, 2 is R_equil
@@ -297,8 +297,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     //  SS_Label_44.1.2  Ricker
     case 2: // Ricker
     {
-      B_equil = SSB_virgin * (1. + (log(Recr_virgin / SSB_virgin) + log(SPR_temp)) / steepness);
-      R_equil = Recr_virgin * B_equil / SSB_virgin * mfexp(steepness * (1. - B_equil / SSB_virgin));
+      B_equil = SSB_temp * (1. + (log(RECR_temp / SSB_temp) + log(SPR_temp)) / steepness);
+      R_equil = RECR_temp * B_equil / SSB_temp * mfexp(steepness * (1. - B_equil / SSB_temp));
 
       break;
     }
@@ -316,14 +316,14 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
-  //    SPR_virgin = SSB_virgin / Recr_virgin;  //  this is already defined
-      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+  //    SPR_virgin = SSB_temp / RECR_temp;  //  this is already defined
+      alpha = 4.0 * steepness / (SPR_virgin_adj * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
 
       // " h " << steepness << " derive "  << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << endl;
-      // " R0 " << Recr_virgin << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
-//      report5 <<" SSB_unf "<<SSB_virgin<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin << endl;
-//      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
+      // " R0 " << RECR_temp << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
+//      report5 <<" SSB_unf "<<SSB_temp<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<RECR_temp << endl;
+      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
 //      report5 << " deriv_h: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SPR_virgin))<<endl;
       B_equil = (alpha * SPR_temp - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
@@ -347,27 +347,27 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     //  SS_Label_44.1.4  constant recruitment
     case 4: // constant; no bias correction
     {
-      B_equil = SPR_temp * Recr_virgin;
-      R_equil = Recr_virgin;
+      B_equil = SPR_temp * RECR_temp;
+      R_equil = RECR_temp;
       break;
     }
     //  SS_Label_44.1.5  Hockey Stick
     case 5: // hockey stick
     {
-      dvariable hockey_min = SRparm(3) * Recr_virgin; // min recruitment level
-      //        temp=SSB_virgin/R0*steepness;  // spawners per recruit at inflection
-      dvariable hockey_slope = (Recr_virgin - hockey_min) / (steepness * SSB_virgin); //  slope of recruitment on spawners below the inflection
-      B_equil = Join_Fxn(0.0 * SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin, SSB_virgin / Recr_virgin * steepness, SPR_temp, hockey_min / ((1. / SPR_temp) - hockey_slope), SPR_temp * Recr_virgin);
-      R_equil = Join_Fxn(0.0 * SSB_virgin, SSB_virgin, SSB_virgin * steepness, B_equil, hockey_min + hockey_slope * B_equil, Recr_virgin);
+      dvariable hockey_min = SRparm(3) * RECR_temp; // min recruitment level
+      //        temp=SSB_temp/R0*steepness;  // spawners per recruit at inflection
+      dvariable hockey_slope = (RECR_temp - hockey_min) / (steepness * SSB_temp); //  slope of recruitment on spawners below the inflection
+      B_equil = Join_Fxn(0.0 * SSB_temp / RECR_temp, SSB_temp / RECR_temp, SSB_temp / RECR_temp * steepness, SPR_temp, hockey_min / ((1. / SPR_temp) - hockey_slope), SPR_temp * RECR_temp);
+      R_equil = Join_Fxn(0.0 * SSB_temp, SSB_temp, SSB_temp * steepness, B_equil, hockey_min + hockey_slope * B_equil, RECR_temp);
       break;
     }
     //  SS_Label_44.1.7  3 parameter survival based
     case 7: // survival
     {
-      SRZ_0 = log(1.0 / (SSB_virgin / Recr_virgin));
+      SRZ_0 = log(1.0 / (SSB_temp / RECR_temp));
       srz_min = SRZ_0 * (1.0 - steepness);
-      B_equil = SSB_virgin * (1. - (log(1. / SPR_temp) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3))));
-      SRZ_surv = mfexp((1. - pow((B_equil / SSB_virgin), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
+      B_equil = SSB_temp * (1. - (log(1. / SPR_temp) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3))));
+      SRZ_surv = mfexp((1. - pow((B_equil / SSB_temp), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
       R_equil = B_equil * SRZ_surv;
       break;
     }
@@ -389,10 +389,10 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
       Shepherd_c2 = pow(0.2, SRparm(3));
       Hupper = 1.0 / (5.0 * Shepherd_c2);
       steepness = 0.2 + (SRparm(2) - 0.2) / (0.8) * (Hupper - 0.2);
-      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_temp * Recr_virgin) / SSB_virgin - (1.0 - 5.0 * steepness * Shepherd_c2);
+      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_temp * RECR_temp) / SSB_temp - (1.0 - 5.0 * steepness * Shepherd_c2);
       Shep_bot = 5.0 * steepness - 1.0;
       Shep_top2 = posfun(Shep_top, 0.001, temp);
-      R_equil = (SSB_virgin / SPR_temp) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
+      R_equil = (SSB_temp / SPR_temp) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
       B_equil = R_equil * SPR_temp;
       break;
     }
@@ -402,10 +402,10 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       steepness = SRparm(2);
       dvariable RkrPower = SRparm(3);
-      temp = SSB_virgin / (SPR_temp * Recr_virgin);
+      temp = SSB_temp / (SPR_temp * RECR_temp);
       dvariable RkrTop = pow(0.8, RkrPower) * log(temp) / log(5.0 * steepness);
       RkrTop = posfun(RkrTop, 0.000001, CrashPen);
-      R_equil = temp * Recr_virgin * (1.0 - pow(RkrTop, 1.0 / RkrPower));
+      R_equil = temp * RECR_temp * (1.0 - pow(RkrTop, 1.0 / RkrPower));
       B_equil = R_equil * SPR_temp;
       break;
     }
@@ -428,10 +428,10 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
         Hupper=1.0/(5.0*Shepherd_c2);
         steepness=0.20001+((0.8)/(1.0+exp(-SRparm2))-0.2)/(0.8)*(Hupper-0.2);
 //        steep2=0.20001+(steepness-0.2)/(0.8)*(Hupper-0.2);
-        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SPR_temp*Recr_virgin)/SSB_virgin-(1.0-5.0*steepness*Shepherd_c2);
+        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SPR_temp*RECR_temp)/SSB_temp-(1.0-5.0*steepness*Shepherd_c2);
         Shep_bot=5.0*steepness-1.0;
         Shep_top2=posfun(Shep_top,0.001,temp);
-        R_equil=(SSB_virgin/SPR_temp) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
+        R_equil=(SSB_temp/SPR_temp) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
         B_equil=R_equil*SPR_temp;
         break;
       }
@@ -448,10 +448,10 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 //   if (Recs < 0) Rec2 = 0; else Rec2 = Recs;
         steepness = 0.2 + (10.0 - 0.2)/(1+exp(-SR_parm_work(2)));
         dvariable RkrPower=exp(SR_parm_work(3));
-        temp=SSB_virgin/(SPR_temp*Recr_virgin);
+        temp=SSB_virgin/(SPR_temp*RECR_temp);
         dvariable RkrTop =  pow(0.8,RkrPower)*log(temp)/log(5.0*steepness);
         RkrTop = posfun(RkrTop,0.000001,CrashPen);
-        R_equil = temp *Recr_virgin * (1.0 - pow(RkrTop,1.0/RkrPower));
+        R_equil = temp *RECR_temp * (1.0 - pow(RkrTop,1.0/RkrPower));
         B_equil=R_equil*SPR_temp;
         break;
       }
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index aec89f6d..25e2f936 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1809,7 +1809,7 @@ FUNCTION void write_bigoutput()
     {
       case 3: // Beverton-Holt with steepness
     {
-      alpha = 4.0 * steepness / (SPR_virgin * (1. - steepness));
+      alpha = 4.0 * steepness / (SPR_virgin_adj * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1. - steepness) * SSB_virgin);
       SS2out << "Ln(R0): " << SR_parm(1) << endl << "R0: " << mfexp(SR_parm(1)) << endl;
       SS2out << "steepness: " << steepness << endl;
@@ -1821,8 +1821,8 @@ FUNCTION void write_bigoutput()
     {
       SS2out << "Ln(alpha): " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
       SS2out << "Ln(beta): " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
-      SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SPR_virgin))) << endl;  //  virgin R0
-      SS2out << "steepness_derived: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << endl;  // steepness virgin
+      SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SPR_virgin_adj))) << endl;  //  virgin R0
+      SS2out << "steepness_derived: " << alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj) << endl;  // steepness virgin
       break;
     }
     case 8:

From f2df4f49c177e718ad4ac8aa13aabe4adb26102a Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Thu, 15 Aug 2024 17:02:43 -0700
Subject: [PATCH 22/29] WIP2-need-to-fix-SPR-passing_to_benchmark

---
 SS_benchfore.tpl | 36 ++++++++++++++++++------------------
 SS_popdyn.tpl    | 17 ++++++++---------
 2 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 8bb12412..4bf41b98 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -536,7 +536,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   dvariable last_F1;
   dvariable Closer;
   dvariable Vbio1_unfished;
-  dvariable SPR_unfished;
+  dvariable SPR_unf;
   dvariable Vbio_MSY;
   dvariable Vbio1_MSY;
   dvariable junk;
@@ -751,7 +751,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       beta = mfexp(SR_parm_work(4));
       Fishon = 0;
       Recr_unf = 1.0;
-      Do_Equil_Calc(Recr_unf);
+      Do_Equil_Calc(Recr_unf);  // 
       SPR_virgin_adj = SSB_equil / 1.0;
       SR_parm_work(2) = alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj);  // steepness
       SR_parm_work(1) = log(1. / beta * (alpha - (1. / SPR_virgin_adj)));  // ln(R0)
@@ -759,21 +759,21 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   Fishon = 0;
   Recr_unf = mfexp(SR_parm_work(1));
   Do_Equil_Calc(Recr_unf);
-  SSB_unf = SSB_equil;
-  SPR_unfished = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
+  SSB_unf = SSB_equil;  // equilibrium unfished SSB using the benchmark averaged Recr_unf and benchmark averaged biology
+  SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
   if (show_MSY == 1)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
             << "mean from years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << endl;
     //  SPR_virgin = SSB_virgin / Recr_virgin;  // already defined
     report5 << " Virgin SSB, R0: " << SSB_virgin << " " << Recr_virgin << " "  << SPR_virgin_adj << endl;
-    report5 << " unfished SSB, R0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unfished << " with current biology " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
+    report5 << " unfished SSB, R0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unf << " with current biology " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_virgin_adj); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     report5 << " Virgin SPR0, result_SSB, R: " << SPR_virgin_adj << " " << Equ_SpawnRecr_Result << endl << endl;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << endl << endl;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_unfished); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unfished << " " << Equ_SpawnRecr_Result << " with virgin spawn-recr " << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unf << " " << Equ_SpawnRecr_Result << endl << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unf << " " << Equ_SpawnRecr_Result << " with virgin spawn-recr " << endl;
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   Mgmt_quant(1) = SSB_unf;
@@ -808,7 +808,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     SPR_target100 = SPR_target * 100.;
 
     Do_Equil_Calc(equ_Recr);
-    SPR_unfished = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
+    SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
     Vbio1_unfished = smrybio; // gets value from equil_calc
     if (show_MSY == 1)
     {
@@ -854,7 +854,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
 
         Fishon = 1;
         Do_Equil_Calc(equ_Recr);
-        yld1(ii) = 100. * SSB_equil / SPR_unfished; //  spawning potential ratio
+        yld1(ii) = 100. * SSB_equil / SPR_unf; //  spawning potential ratio
       }
       SPR_actual = yld1(1); //  spawning potential ratio
 
@@ -1008,7 +1008,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       last_F1 = F1(1);
       if (show_MSY == 1)
       {
-        report5 << j << " " << F1(1) << " " << equ_F_std << " " << SSB_equil / SPR_unfished << " " << YPR_opt << " " << F01_actual << " " << F01_second << " last F1 " << last_F1 << " Closer " << Closer << " delta " << (F01_origin * 0.1 - F01_actual) / (F01_second) << endl;
+        report5 << j << " " << F1(1) << " " << equ_F_std << " " << SSB_equil / SPR_unf << " " << YPR_opt << " " << F01_actual << " " << F01_second << " last F1 " << last_F1 << " Closer " << Closer << " delta " << (F01_origin * 0.1 - F01_actual) / (F01_second) << endl;
       }
       F1(1) += (F01_origin * 0.1 - F01_actual) / (F01_second);
       F1(1) = (1. - Closer) * F1(1) + Closer * last_F1;
@@ -1051,7 +1051,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     YPR_Btgt_revenue = (PricePerF * YPR_val_vec) * Btgt_Rec; //  vector*vector*scalar
     //    YPR_Btgt_revenue = Price*YPR_ret*Btgt_Rec;
     YPR_Btgt_profit = YPR_Btgt_revenue - Cost;
-    SPR_Btgt = SSB_equil / SPR_unfished;
+    SPR_Btgt = SSB_equil / SPR_unf;
     Vbio_Btgt = totbio;
     Vbio1_Btgt = smrybio;
     Mgmt_quant(7) = equ_F_std;
@@ -1131,7 +1131,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           //  else  Hrate for bycatch fleets already set
         }
         Do_Equil_Calc(equ_Recr); //  where equ_Recr=1.0, so returned SSB_equil is a SSB/R,
-        SPR_Btgt = SSB_equil / SPR_unfished;
+        SPR_Btgt = SSB_equil / SPR_unf;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
         Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
@@ -1353,7 +1353,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
 
       Do_Equil_Calc(equ_Recr);
       //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
-      MSY_SPR = SSB_equil / SPR_unfished;
+      MSY_SPR = SSB_equil / SPR_unf;
       SPR_temp = SSB_equil;
       Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
       Bmsy = Equ_SpawnRecr_Result(1);  //  with MSY set to SPR, not directly estimated
@@ -1446,7 +1446,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           }
           Do_Equil_Calc(equ_Recr);
           //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
-          MSY_SPR = SSB_equil / SPR_unfished;
+          MSY_SPR = SSB_equil / SPR_unf;
           SPR_temp = SSB_equil;
           Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
           Bmsy = Equ_SpawnRecr_Result(1);  //  MSY is directly estimated
@@ -1739,7 +1739,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           //  else  Hrate for bycatch fleets already set
         }
         Do_Equil_Calc(equ_Recr);
-        SPR_Btgt2 = SSB_equil / SPR_unfished;
+        SPR_Btgt2 = SSB_equil / SPR_unf;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
         SPR_temp = SSB_equil;
         Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
@@ -1947,7 +1947,7 @@ FUNCTION void Get_Forecast()
   dvariable Fcast_Crash;
   dvariable totcatch;
   dvariable R0_use;  // annually updated variable if SR_update_SPR0 == 1
-  dvariable SSB_use;
+  dvariable SSB_use;  // selected version of SSB that gets passes to Spawn_Recr
   dvar_matrix catage_w(1, gmorph, 0, nages);
   dvar_vector tempcatch(1, Nfleet);
   imatrix Do_F_tune(t_base, TimeMax_Fcast_std, 1, Nfleet); //  flag for doing F from catch
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index 2f0213c5..f509cf93 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -344,7 +344,7 @@ FUNCTION void get_initial_conditions()
     equ_Recr = 1.0;
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation.  Returns SPR because R = 1.0
     SPR_virgin = SSB_equil; //  spawners per recruit.  Needed for Sr_fxn = 10
-    SPR_virgin_adj = SSB_equil;
+    SPR_virgin_adj = SSB_equil;  //  also needed for Sr_fxn 10.  Will get revised in benchmark to use averaged biology if requested.
     if(SR_fxn == 10)  // B-H with a,b
     {
   //  WHAM based on R = A*S/(1+B*S)
@@ -381,14 +381,14 @@ FUNCTION void get_initial_conditions()
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
     SSB_virgin = SSB_equil;
 //    SPR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit already calculated
-    if(Do_Benchmark==0)
+    if(Do_Benchmark==0)  // assign values that would be created in benchmark section
     {
-      Mgmt_quant(1)=SSB_virgin;
-      SSB_unf=SSB_virgin;
-      Recr_unf=Recr_virgin;
-      Mgmt_quant(2)=totbio;  //  from equil calcs
-      Mgmt_quant(3)=smrybio;  //  from equil calcs
-      Mgmt_quant(4)=Recr_virgin;
+      Mgmt_quant(1) = SSB_virgin;
+      SSB_unf = SSB_virgin;
+      Recr_unf = Recr_virgin;
+      Mgmt_quant(2) = totbio;  //  from equil calcs
+      Mgmt_quant(3) = smrybio;  //  from equil calcs
+      Mgmt_quant(4) = Recr_virgin;
     }
     Smry_Table(styr - 2, 1) = totbio; //  from equil calcs
     Smry_Table(styr - 2, 2) = smrybio; //  from equil calcs
@@ -1492,7 +1492,6 @@ FUNCTION void get_time_series()
         else  //  update SSB_use and R0_use where will update SPR0 inside the Spawn_recr fxn
         {
           R0_use = mfexp(SR_parm_work(1));  //  check to be sure this works when R0 is derived from B-H with alpha, beta parameters
-          equ_Recr = R0_use;
           Fishon = 0;
           eq_yr = y;
           bio_yr = y;

From a9dacb03d6b28badda5ba3b23dd0b27e89e2fda1 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Fri, 13 Sep 2024 16:27:52 -0700
Subject: [PATCH 23/29] WIP: add switch in benchmark to use correct SPR0

---
 SS_benchfore.tpl       |  42 +++++++--------
 SS_popdyn.tpl          |   5 +-
 SS_readcontrol_330.tpl |   2 +-
 SS_recruit.tpl         | 116 ++++++++++++++++++++---------------------
 4 files changed, 80 insertions(+), 85 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 4bf41b98..25038380 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -745,35 +745,30 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     }
   }
 
-  if(SR_fxn == 10)  //  B-H with alpha, beta
+  if (SR_update_SPR0 == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations
   {
-      alpha = mfexp(SR_parm_work(3));
-      beta = mfexp(SR_parm_work(4));
-      Fishon = 0;
-      Recr_unf = 1.0;
-      Do_Equil_Calc(Recr_unf);  // 
-      SPR_virgin_adj = SSB_equil / 1.0;
-      SR_parm_work(2) = alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj);  // steepness
-      SR_parm_work(1) = log(1. / beta * (alpha - (1. / SPR_virgin_adj)));  // ln(R0)
+     Recr_unf = Recr_virgin;
+     SSB_unf = SSB_virgin;
+     SPR_unf = SSB_unf / Recr_unf;
+  }
+  else  // use benchmark biology in the spawner-recruitment R0,h calculations
+  {
+    Fishon = 0;
+    Recr_unf = mfexp(SR_parm_work(1));
+    Do_Equil_Calc(Recr_unf);
+    SSB_unf = SSB_equil;  // equilibrium unfished SSB using the benchmark averaged Recr_unf and benchmark averaged biology
+    SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
   }
-  Fishon = 0;
-  Recr_unf = mfexp(SR_parm_work(1));
-  Do_Equil_Calc(Recr_unf);
-  SSB_unf = SSB_equil;  // equilibrium unfished SSB using the benchmark averaged Recr_unf and benchmark averaged biology
-  SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
   if (show_MSY == 1)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
-            << "mean from years: " << Bmark_Yr(9) << " " << Bmark_Yr(10) << endl;
-    //  SPR_virgin = SSB_virgin / Recr_virgin;  // already defined
-    report5 << " Virgin SSB, R0: " << SSB_virgin << " " << Recr_virgin << " "  << SPR_virgin_adj << endl;
-    report5 << " unfished SSB, R0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unf << " with current biology " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_virgin_adj); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Virgin SPR0, result_SSB, R: " << SPR_virgin_adj << " " << Equ_SpawnRecr_Result << endl << endl;
+            << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
+    if ( SR_update_SPR0 == 1) report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SPR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
+
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unf << " " << Equ_SpawnRecr_Result << endl << endl;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SPR0, result_SSB, R: " << SPR_unf << " " << Equ_SpawnRecr_Result << " with virgin spawn-recr " << endl;
+    report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   Mgmt_quant(1) = SSB_unf;
@@ -925,7 +920,6 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     //  SPAWN-RECR:   calc equil spawn-recr in YPR; need to make this area-specific
     SPR_temp = SSB_equil;  //  based on most recent call to Do_Equil_Calc
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-         report5<<SPR_temp<<" " << Equ_SpawnRecr_Result<<endl;
 
     Bspr = Equ_SpawnRecr_Result(1);
     Bspr_rec = Equ_SpawnRecr_Result(2);
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index f509cf93..a0297e3c 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -535,6 +535,7 @@ FUNCTION void get_initial_conditions()
     CrashPen += Equ_penalty;
     SPR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
     //  get equilibrium SSB and recruitment from SPR_temp, Recr_virgin and virgin steepness
+    //  this is the initial year, so no time-vary effects available, so uses _virgin quantities for spawner-recruitment
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     R1_exp = Equ_SpawnRecr_Result(2); //  set the expected recruitment equal to this equilibrium
     exp_rec(eq_yr, 1) = R1_exp;
@@ -1037,7 +1038,7 @@ FUNCTION void get_time_series()
           Fishon = 0;
           eq_yr = y;
           bio_yr = y;
-          Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation
+          Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation with current year's biology and adjusted R0
           SSB_use = SSB_equil;
           if (fishery_on_off == 1)
           {
@@ -1048,7 +1049,7 @@ FUNCTION void get_time_series()
             Fishon = 0;
           }
         }
-        Recruits = Spawn_Recr(SSB_use, R0_use, SSB_current); // calls to function Spawn_Recr
+        Recruits = Spawn_Recr(SSB_use, R0_use, SSB_current); // calls to function Spawn_Recr using either virgin or adjusted R0 and SSB0
         if (SR_fxn != 7) apply_recdev(Recruits, R0_use); //  apply recruitment deviation
         // distribute Recruitment of age 0 fish among the current and future settlements; and among areas and morphs
         //  use t offset for each birth event:  Settlement_offset(settle)
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index fbf18704..905f9a81 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -6453,7 +6453,7 @@
       active_parm(CoVar_Count) = j;
       if (y == styr - 2)
       {
-        ParmLabel += "Recr_Virgin";
+        ParmLabel += "Recr_virgin";
       }
       else if (y == styr - 1)
       {
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 179ecd6e..5766efce 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -6,7 +6,7 @@
 //********************************************************************
  /*  SS_Label_FUNCTION 43 Spawner-recruitment function */
 //  SPAWN-RECR:   function: to calc R from S
-FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariable& Recr_virgin_adj, const prevariable& SSB_current)
+FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_use, const prevariable& Recr_virgin_use, const prevariable& SSB_current)
   {
   RETURN_ARRAYS_INCREMENT();
   dvariable NewRecruits;
@@ -22,7 +22,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
   dvariable SRZ_0;
   dvariable srz_min;
   dvariable SRZ_surv;
-//  warning << y << "  Tester_R0 " <<  Recr_virgin_adj << " SSB0 " << SSB_virgin_adj << " SSB_curr: " << SSB_current << endl;
+//  warning << y << "  Tester_R0 " <<  Recr_virgin_use << " SSB0 " << SSB_virgin_use << " SSB_curr: " << SSB_current << endl;
 
   //  SS_Label_43.1  add 0.1 to input spawning biomass value to make calculation more rebust
   SSB_curr_adj = SSB_current + 0.100; // robust
@@ -30,7 +30,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
   regime_change = SR_parm_work(N_SRparm2 - 1); //  this is a persistent deviation off the S/R curve
 
   //  SS_Label_43.3  calculate expected recruitment from the input spawning biomass and the SR curve
-  // functions below use Recr_virgin_adj,SSB_virgin_adj which could have been adjusted adjusted above from R0,SSB_virgin
+  // functions below use Recr_virgin_use,SSB_virgin_use which could have been adjusted adjusted above from R0,SSB_virgin
   switch (SR_fxn)
   {
     case 1: // previous placement for B-H constrained
@@ -43,15 +43,15 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 2: // ricker
     {
       steepness = SR_parm_work(2);
-      NewRecruits = Recr_virgin_adj * SSB_curr_adj / SSB_virgin_adj * mfexp(steepness * (1. - SSB_curr_adj / SSB_virgin_adj));
+      NewRecruits = Recr_virgin_use * SSB_curr_adj / SSB_virgin_use * mfexp(steepness * (1. - SSB_curr_adj / SSB_virgin_use));
       break;
     }
     //  SS_Label_43.3.3  Beverton-Holt
     case 3: // Beverton-Holt
     {
       steepness = SR_parm_work(2);
-      NewRecruits = (4. * steepness * Recr_virgin_adj * SSB_curr_adj) /
-          (SSB_virgin_adj * (1. - steepness) + (5. * steepness - 1.) * SSB_curr_adj);
+      NewRecruits = (4. * steepness * Recr_virgin_use * SSB_curr_adj) /
+          (SSB_virgin_use * (1. - steepness) + (5. * steepness - 1.) * SSB_curr_adj);
       break;
     }
 
@@ -66,7 +66,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     //  SS_Label_43.3.4  constant expected recruitment
     case 4: // none
     {
-      NewRecruits = Recr_virgin_adj;
+      NewRecruits = Recr_virgin_use;
       break;
     }
     //  SS_Label_43.3.5  Hockey stick
@@ -74,8 +74,8 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
       //  the 3rd parameter allows for a minimum recruitment level
       {
         steepness = SR_parm_work(2);
-        temp = SR_parm_work(3) * Recr_virgin_adj + SSB_curr_adj / (steepness * SSB_virgin_adj) * (Recr_virgin_adj - SR_parm_work(3) * Recr_virgin_adj); //  linear decrease below steepness*SSB_virgin_adj
-        NewRecruits = Join_Fxn(0.0 * SSB_virgin_adj, SSB_virgin_adj, steepness * SSB_virgin_adj, SSB_curr_adj, temp, Recr_virgin_adj);
+        temp = SR_parm_work(3) * Recr_virgin_use + SSB_curr_adj / (steepness * SSB_virgin_use) * (Recr_virgin_use - SR_parm_work(3) * Recr_virgin_use); //  linear decrease below steepness*SSB_virgin_use
+        NewRecruits = Join_Fxn(0.0 * SSB_virgin_use, SSB_virgin_use, steepness * SSB_virgin_use, SSB_curr_adj, temp, Recr_virgin_use);
         break;
       }
 
@@ -83,32 +83,32 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     case 6: //Beverton-Holt constrained
     {
       steepness = SR_parm_work(2);
-//      dvariable SPR = SSB_virgin_adj / Recr_virgin;
+//      dvariable SPR = SSB_virgin_use / Recr_virgin;
 //      alpha = ((4.0 * steepness) / (1. - steepness)) / SPR ;
 //      beta = (1.0 / Recr_virgin) * (alpha - (1.0 / SPR));
-      if (SSB_curr_adj > SSB_virgin_adj)
+      if (SSB_curr_adj > SSB_virgin_use)
       {
-        SSB_BH1 = SSB_virgin_adj;
+        SSB_BH1 = SSB_virgin_use;
       }
       else
       {
         SSB_BH1 = SSB_curr_adj;
       }
-      NewRecruits = (4. * steepness * Recr_virgin_adj * SSB_BH1) / (SSB_virgin_adj * (1. - steepness) + (5. * steepness - 1.) * SSB_BH1);
+      NewRecruits = (4. * steepness * Recr_virgin_use * SSB_BH1) / (SSB_virgin_use * (1. - steepness) + (5. * steepness - 1.) * SSB_BH1);
       break;
     }
 
     //  SS_Label_43.3.7  survival based
     case 7: // survival based, so constrained such that recruits cannot exceed fecundity
     {
-      // PPR_0=SSB_virgin_adj/Recr_virgin_adj;  //  pups per recruit at virgin
+      // PPR_0=SSB_virgin_use/Recr_virgin_use;  //  pups per recruit at virgin
       // Surv_0=1./PPR_0;   //  recruits per pup at virgin
-      // Pups_0=SSB_virgin_adj;  //  total population fecundity is the number of pups produced
+      // Pups_0=SSB_virgin_use;  //  total population fecundity is the number of pups produced
       // Sfrac=SR_parm(2);
-      SRZ_0 = log(1.0 / (SSB_virgin_adj / Recr_virgin_adj));
+      SRZ_0 = log(1.0 / (SSB_virgin_use / Recr_virgin_use));
       steepness = SR_parm_work(2);
       srz_min = SRZ_0 * (1.0 - steepness);
-      SRZ_surv = mfexp((1. - pow((SSB_curr_adj / SSB_virgin_adj), SR_parm_work(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
+      SRZ_surv = mfexp((1. - pow((SSB_curr_adj / SSB_virgin_use), SR_parm_work(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
       NewRecruits = SSB_curr_adj * SRZ_surv;
       exp_rec(y, 1) = NewRecruits; // expected arithmetic mean recruitment
       //  SS_Label_43.3.7.1  Do variation in recruitment by adjusting survival
@@ -145,8 +145,8 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
       Shepherd_c2 = pow(0.2, SR_parm_work(3));
       Hupper = 1.0 / (5.0 * Shepherd_c2);
       steepness = 0.2 + (SR_parm_work(2) - 0.2) / (0.8) * (Hupper - 0.2);
-      temp = (SSB_curr_adj) / (SSB_virgin_adj);
-      NewRecruits = (5. * steepness * Recr_virgin_adj * (1. - Shepherd_c2) * temp) /
+      temp = (SSB_curr_adj) / (SSB_virgin_use);
+      NewRecruits = (5. * steepness * Recr_virgin_use * (1. - Shepherd_c2) * temp) /
           (1.0 - 5.0 * steepness * Shepherd_c2 + (5. * steepness - 1.) * pow(temp, Shepherd_c));
       break;
     }
@@ -156,11 +156,11 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
     {
       steepness = SR_parm_work(2);
       dvariable RkrPower = SR_parm_work(3);
-      temp = SSB_curr_adj / SSB_virgin_adj;
+      temp = SSB_curr_adj / SSB_virgin_use;
       temp2 = posfun(1.0 - temp, 0.0000001, temp3);
       temp = 1.0 - temp2; //  Rick's new line to stabilize recruitment at R0 if B>B0
       dvariable RkrTop = log(5.0 * steepness) * pow(temp2, RkrPower) / pow(0.8, RkrPower);
-      NewRecruits = Recr_virgin_adj * temp * mfexp(RkrTop);
+      NewRecruits = Recr_virgin_use * temp * mfexp(RkrTop);
       break;
     }
 
@@ -169,7 +169,7 @@ FUNCTION dvariable Spawn_Recr(const prevariable& SSB_virgin_adj, const prevariab
   return NewRecruits;
   } //  end spawner_recruitment
 
-FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_virgin_adj)
+FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_virgin_use)
   {
   RETURN_ARRAYS_INCREMENT();
   //  SS_Label_43.4  For non-survival based SRR, get recruitment deviations by adjusting recruitment itself
@@ -196,7 +196,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
     {
       if (do_recdev >= 3)
       {
-        NewRecruits = Recr_virgin_adj * mfexp(recdev(y)); //  recruitment deviation
+        NewRecruits = Recr_virgin_use * mfexp(recdev(y)); //  recruitment deviation
       }
       else if (SR_fxn != 7)
       {
@@ -228,7 +228,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
       }
       case 2: //  use multiplier of R0
       {
-        exp_rec(y, 2) = Recr_virgin_adj * Fcast_Loop_Control(4); //  apply fcast multiplier to the virgin recruitment
+        exp_rec(y, 2) = Recr_virgin_use * Fcast_Loop_Control(4); //  apply fcast multiplier to the virgin recruitment
         NewRecruits = exp_rec(y, 2);
         if (SR_fxn != 4)
           NewRecruits *= mfexp(-biasadj(y) * half_sigmaRsq); // bias adjustment
@@ -268,7 +268,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
  /*  SS_Label_FUNCTION 44 Equil_Spawn_Recr_Fxn */
 //  SPAWN-RECR:   function  Equil_Spawn_Recr_Fxn
 FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
-    const prevariable& SSB_temp, const prevariable& RECR_temp, const prevariable& SPR_temp)
+    const prevariable& SSB_virgin_use, const prevariable& Recr_virgin_use, const prevariable& SPR_current)
   {
   RETURN_ARRAYS_INCREMENT();
   dvar_vector Equil_Spawn_Recr_Calc(1, 2); // values to return 1 is B_equil, 2 is R_equil
@@ -284,7 +284,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
   dvariable SRZ_surv;
 
   steepness = SRparm(2); //  common usage but some different
-  //  SS_Label_44.1  calc equilibrium SpawnBio and Recruitment from input SPR_temp, which is spawning biomass per recruit at some given F level
+  //  SS_Label_44.1  calc equilibrium SpawnBio and Recruitment from input SPR_current, which is spawning biomass per recruit at some given F level
   switch (SR_fxn)
   {
     case 1: // previous placement for B-H constrained
@@ -297,8 +297,8 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     //  SS_Label_44.1.2  Ricker
     case 2: // Ricker
     {
-      B_equil = SSB_temp * (1. + (log(RECR_temp / SSB_temp) + log(SPR_temp)) / steepness);
-      R_equil = RECR_temp * B_equil / SSB_temp * mfexp(steepness * (1. - B_equil / SSB_temp));
+      B_equil = SSB_virgin_use * (1. + (log(Recr_virgin_use / SSB_virgin_use) + log(SPR_current)) / steepness);
+      R_equil = Recr_virgin_use * B_equil / SSB_virgin_use * mfexp(steepness * (1. - B_equil / SSB_virgin_use));
 
       break;
     }
@@ -316,19 +316,19 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
-  //    SPR_virgin = SSB_temp / RECR_temp;  //  this is already defined
+  //    SPR_virgin = SSB_virgin_use / Recr_virgin_use;  //  this is already defined
       alpha = 4.0 * steepness / (SPR_virgin_adj * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
 
       // " h " << steepness << " derive "  << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << endl;
-      // " R0 " << RECR_temp << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
-//      report5 <<" SSB_unf "<<SSB_temp<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<RECR_temp << endl;
-      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
+      // " R0 " << Recr_virgin_use << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
+//      report5 <<" SSB_unf "<<SSB_virgin_use<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin_use << endl;
+//      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
 //      report5 << " deriv_h: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SPR_virgin))<<endl;
-      B_equil = (alpha * SPR_temp - 1.0) / beta;
+      B_equil = (alpha * SPR_current - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5 << "SPR_input: " << SPR_temp << " B_equil: " << B_equil << " R_equil: "<<R_equil << endl<<endl;
+//      report5 << "SPR_input: " << SPR_current << " B_equil: " << B_equil << " R_equil: "<<R_equil << endl<<endl;
 
       break;
     }
@@ -337,37 +337,37 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       dvariable alpha = mfexp(SRparm(3));
       dvariable beta = mfexp(SRparm(4));
-      B_equil = (alpha * SPR_temp - 1.0) / beta;
+      B_equil = (alpha * SPR_current - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5<<SPR_temp<<" Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
+//      report5<<SPR_current<<" Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
       break;
     }
 
     //  SS_Label_44.1.4  constant recruitment
     case 4: // constant; no bias correction
     {
-      B_equil = SPR_temp * RECR_temp;
-      R_equil = RECR_temp;
+      B_equil = SPR_current * Recr_virgin_use;
+      R_equil = Recr_virgin_use;
       break;
     }
     //  SS_Label_44.1.5  Hockey Stick
     case 5: // hockey stick
     {
-      dvariable hockey_min = SRparm(3) * RECR_temp; // min recruitment level
-      //        temp=SSB_temp/R0*steepness;  // spawners per recruit at inflection
-      dvariable hockey_slope = (RECR_temp - hockey_min) / (steepness * SSB_temp); //  slope of recruitment on spawners below the inflection
-      B_equil = Join_Fxn(0.0 * SSB_temp / RECR_temp, SSB_temp / RECR_temp, SSB_temp / RECR_temp * steepness, SPR_temp, hockey_min / ((1. / SPR_temp) - hockey_slope), SPR_temp * RECR_temp);
-      R_equil = Join_Fxn(0.0 * SSB_temp, SSB_temp, SSB_temp * steepness, B_equil, hockey_min + hockey_slope * B_equil, RECR_temp);
+      dvariable hockey_min = SRparm(3) * Recr_virgin_use; // min recruitment level
+      //        temp=SSB_virgin_use/R0*steepness;  // spawners per recruit at inflection
+      dvariable hockey_slope = (Recr_virgin_use - hockey_min) / (steepness * SSB_virgin_use); //  slope of recruitment on spawners below the inflection
+      B_equil = Join_Fxn(0.0 * SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use * steepness, SPR_current, hockey_min / ((1. / SPR_current) - hockey_slope), SPR_current * Recr_virgin_use);
+      R_equil = Join_Fxn(0.0 * SSB_virgin_use, SSB_virgin_use, SSB_virgin_use * steepness, B_equil, hockey_min + hockey_slope * B_equil, Recr_virgin_use);
       break;
     }
     //  SS_Label_44.1.7  3 parameter survival based
     case 7: // survival
     {
-      SRZ_0 = log(1.0 / (SSB_temp / RECR_temp));
+      SRZ_0 = log(1.0 / (SSB_virgin_use / Recr_virgin_use));
       srz_min = SRZ_0 * (1.0 - steepness);
-      B_equil = SSB_temp * (1. - (log(1. / SPR_temp) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3))));
-      SRZ_surv = mfexp((1. - pow((B_equil / SSB_temp), SRparm(3))) * (srz_min - SRZ_0) + SRZ_0); //  survival
+      B_equil = SSB_virgin_use * (1. - (log(1. / SPR_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;
       break;
     }
@@ -389,11 +389,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
       Shepherd_c2 = pow(0.2, SRparm(3));
       Hupper = 1.0 / (5.0 * Shepherd_c2);
       steepness = 0.2 + (SRparm(2) - 0.2) / (0.8) * (Hupper - 0.2);
-      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_temp * RECR_temp) / SSB_temp - (1.0 - 5.0 * steepness * Shepherd_c2);
+      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_current * Recr_virgin_use) / SSB_virgin_use - (1.0 - 5.0 * steepness * Shepherd_c2);
       Shep_bot = 5.0 * steepness - 1.0;
       Shep_top2 = posfun(Shep_top, 0.001, temp);
-      R_equil = (SSB_temp / SPR_temp) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
-      B_equil = R_equil * SPR_temp;
+      R_equil = (SSB_virgin_use / SPR_current) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
+      B_equil = R_equil * SPR_current;
       break;
     }
 
@@ -402,11 +402,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       steepness = SRparm(2);
       dvariable RkrPower = SRparm(3);
-      temp = SSB_temp / (SPR_temp * RECR_temp);
+      temp = SSB_virgin_use / (SPR_current * Recr_virgin_use);
       dvariable RkrTop = pow(0.8, RkrPower) * log(temp) / log(5.0 * steepness);
       RkrTop = posfun(RkrTop, 0.000001, CrashPen);
-      R_equil = temp * RECR_temp * (1.0 - pow(RkrTop, 1.0 / RkrPower));
-      B_equil = R_equil * SPR_temp;
+      R_equil = temp * Recr_virgin_use * (1.0 - pow(RkrTop, 1.0 / RkrPower));
+      B_equil = R_equil * SPR_current;
       break;
     }
 
@@ -428,11 +428,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
         Hupper=1.0/(5.0*Shepherd_c2);
         steepness=0.20001+((0.8)/(1.0+exp(-SRparm2))-0.2)/(0.8)*(Hupper-0.2);
 //        steep2=0.20001+(steepness-0.2)/(0.8)*(Hupper-0.2);
-        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SPR_temp*RECR_temp)/SSB_temp-(1.0-5.0*steepness*Shepherd_c2);
+        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SPR_current*Recr_virgin_use)/SSB_virgin_use-(1.0-5.0*steepness*Shepherd_c2);
         Shep_bot=5.0*steepness-1.0;
         Shep_top2=posfun(Shep_top,0.001,temp);
-        R_equil=(SSB_temp/SPR_temp) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
-        B_equil=R_equil*SPR_temp;
+        R_equil=(SSB_virgin_use/SPR_current) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
+        B_equil=R_equil*SPR_current;
         break;
       }
 
@@ -448,11 +448,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 //   if (Recs < 0) Rec2 = 0; else Rec2 = Recs;
         steepness = 0.2 + (10.0 - 0.2)/(1+exp(-SR_parm_work(2)));
         dvariable RkrPower=exp(SR_parm_work(3));
-        temp=SSB_virgin/(SPR_temp*RECR_temp);
+        temp=SSB_virgin/(SPR_current*Recr_virgin_use);
         dvariable RkrTop =  pow(0.8,RkrPower)*log(temp)/log(5.0*steepness);
         RkrTop = posfun(RkrTop,0.000001,CrashPen);
-        R_equil = temp *RECR_temp * (1.0 - pow(RkrTop,1.0/RkrPower));
-        B_equil=R_equil*SPR_temp;
+        R_equil = temp *Recr_virgin_use * (1.0 - pow(RkrTop,1.0/RkrPower));
+        B_equil=R_equil*SPR_current;
         break;
       }
    */

From d351e200f3961584eef2946b0b1792e1245d1f0c Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Mon, 16 Sep 2024 18:22:06 -0700
Subject: [PATCH 24/29] refactor SPR to SSBpR; clean-up reference to timevary
 biology

---
 SS_benchfore.tpl    | 73 ++++++++++++++++++++++++---------------------
 SS_param.tpl        |  6 ++--
 SS_popdyn.tpl       | 18 ++++++-----
 SS_recruit.tpl      | 54 ++++++++++++++++-----------------
 SS_write_report.tpl | 14 ++++-----
 5 files changed, 85 insertions(+), 80 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 25038380..79a792fa 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -536,7 +536,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   dvariable last_F1;
   dvariable Closer;
   dvariable Vbio1_unfished;
-  dvariable SPR_unf;
+  dvariable SSBpR_unf;
   dvariable Vbio_MSY;
   dvariable Vbio1_MSY;
   dvariable junk;
@@ -749,7 +749,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   {
      Recr_unf = Recr_virgin;
      SSB_unf = SSB_virgin;
-     SPR_unf = SSB_unf / Recr_unf;
+     SSBpR_unf = SSB_unf / Recr_unf;
   }
   else  // use benchmark biology in the spawner-recruitment R0,h calculations
   {
@@ -757,18 +757,21 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     Recr_unf = mfexp(SR_parm_work(1));
     Do_Equil_Calc(Recr_unf);
     SSB_unf = SSB_equil;  // equilibrium unfished SSB using the benchmark averaged Recr_unf and benchmark averaged biology
-    SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
+    SSBpR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
+    SSBpR_virgin_adj = SSB_unf / Recr_unf;  //  update 
   }
   if (show_MSY == 1)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
             << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
     if ( SR_update_SPR0 == 1) report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SPR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SSBpR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SSBpR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
+
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SSBpR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
+    report5 << "Repro_output_by_age_for_morph_1: " << fec(1) << endl;
 
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SPR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
   Mgmt_quant(1) = SSB_unf;
@@ -803,7 +806,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     SPR_target100 = SPR_target * 100.;
 
     Do_Equil_Calc(equ_Recr);
-    SPR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
+    SSBpR_unf = SSB_unf / Recr_unf; //  this corresponds to the biology for benchmark average years, not the virgin SSB_virgin
     Vbio1_unfished = smrybio; // gets value from equil_calc
     if (show_MSY == 1)
     {
@@ -849,7 +852,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
 
         Fishon = 1;
         Do_Equil_Calc(equ_Recr);
-        yld1(ii) = 100. * SSB_equil / SPR_unf; //  spawning potential ratio
+        yld1(ii) = 100. * SSB_equil / SSBpR_unf; //  spawning potential ratio
       }
       SPR_actual = yld1(1); //  spawning potential ratio
 
@@ -918,8 +921,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     }
 
     //  SPAWN-RECR:   calc equil spawn-recr in YPR; need to make this area-specific
-    SPR_temp = SSB_equil;  //  based on most recent call to Do_Equil_Calc
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    SSBpR_temp = SSB_equil;  //  based on most recent call to Do_Equil_Calc
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
 
     Bspr = Equ_SpawnRecr_Result(1);
     Bspr_rec = Equ_SpawnRecr_Result(2);
@@ -1002,7 +1005,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       last_F1 = F1(1);
       if (show_MSY == 1)
       {
-        report5 << j << " " << F1(1) << " " << equ_F_std << " " << SSB_equil / SPR_unf << " " << YPR_opt << " " << F01_actual << " " << F01_second << " last F1 " << last_F1 << " Closer " << Closer << " delta " << (F01_origin * 0.1 - F01_actual) / (F01_second) << endl;
+        report5 << j << " " << F1(1) << " " << equ_F_std << " " << SSB_equil / SSBpR_unf << " " << YPR_opt << " " << F01_actual << " " << F01_second << " last F1 " << last_F1 << " Closer " << Closer << " delta " << (F01_origin * 0.1 - F01_actual) / (F01_second) << endl;
       }
       F1(1) += (F01_origin * 0.1 - F01_actual) / (F01_second);
       F1(1) = (1. - Closer) * F1(1) + Closer * last_F1;
@@ -1033,8 +1036,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     Btgt_Fmult = F1(1);
     if (rundetail > 0 && mceval_counter == 0 && show_MSY == 1)
       echoinput << "Calculated F0.1: " << Btgt_Fmult << endl;
-    SPR_temp = SSB_equil;
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    SSBpR_temp = SSB_equil;
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     Btgt = Equ_SpawnRecr_Result(1);
     Btgt_Rec = Equ_SpawnRecr_Result(2);
     YPR_Btgt_enc = YPR_enc; //  total encountered yield per recruit
@@ -1045,7 +1048,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     YPR_Btgt_revenue = (PricePerF * YPR_val_vec) * Btgt_Rec; //  vector*vector*scalar
     //    YPR_Btgt_revenue = Price*YPR_ret*Btgt_Rec;
     YPR_Btgt_profit = YPR_Btgt_revenue - Cost;
-    SPR_Btgt = SSB_equil / SPR_unf;
+    SPR_Btgt = SSB_equil / SSBpR_unf;
     Vbio_Btgt = totbio;
     Vbio1_Btgt = smrybio;
     Mgmt_quant(7) = equ_F_std;
@@ -1060,9 +1063,12 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     // ******************************************************
     if (show_MSY == 1)
     {
-      report5 << "#" << endl
-              << "Find_target_SSB/Bzero; where Bzero is for Bmark years, not Virgin" << endl
-              << "Iter Fmult ann_F SPR Catch SSB Recruits SSB/Bzero Tot_catch";
+      report5 << "#" << endl;
+  if (SR_update_SPR0 == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations
+    {report5 << "Find_target_SSB/Bzero; where Bzero is Virgin SSB:" << SSB_unf << " where SSBpR_unf = " << SSBpR_unf << endl;}
+  else
+    {report5 << "Find_target_SSB/Bzero; where Bzero is for Bmark biology and updated SPR0: " << SSB_unf << " where SSBpR_unf = " << SSBpR_unf << endl;}
+  report5  << "Iter Fmult ann_F SPR Catch SSB Recruits SSB/Bzero Tot_catch";
       for (p = 1; p <= pop; p++)
         for (gp = 1; gp <= N_GP; gp++)
         {
@@ -1088,8 +1094,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       Nloops = 28;
     }
 
-    //    Btgttgt=BTGT_target*SSB_virgin;   //  this is relative to virgin, not to the average biology from benchmark years
-    Btgttgt = BTGT_target * SSB_unf; //  now relative to Bmark
+    Btgttgt = BTGT_target * SSB_unf;
 
     for (j = 0; j <= Nloops; j++) // loop find Btarget
     {
@@ -1124,12 +1129,11 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           }
           //  else  Hrate for bycatch fleets already set
         }
-        Do_Equil_Calc(equ_Recr); //  where equ_Recr=1.0, so returned SSB_equil is a SSB/R,
-        SPR_Btgt = SSB_equil / SPR_unf;
+        Do_Equil_Calc(equ_Recr); //  where equ_Recr=1.0, so returned SSB_equil is in units of SSB/R,
+        SSBpR_temp = SSB_equil;
+        SPR_Btgt = SSBpR_temp / SSBpR_unf;  //  where SSBpR_unf = SSB_unf / Recr_unf so units of SSB/R; so result is SPR_Btgt = (fished SSB/R) / (unfished SSB/R)
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
-        SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-         report5<<SPR_temp<<" " << Equ_SpawnRecr_Result<<endl;
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
 
@@ -1169,6 +1173,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
             report5 << " " << SSB_equil_pop_gp(p, gp) * Equ_SpawnRecr_Result(2);
           }
         report5 << endl;
+//        " SSB_unf " << SSB_unf << " recr " <<Recr_unf<< " SSB_equil " << SSB_equil << " ssbpr_virginadj: " << SSBpR_virgin_adj << " Btgt " << Btgt << endl;
       }
     } // end search loop
 
@@ -1347,9 +1352,9 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
 
       Do_Equil_Calc(equ_Recr);
       //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
-      MSY_SPR = SSB_equil / SPR_unf;
-      SPR_temp = SSB_equil;
-      Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+      MSY_SPR = SSB_equil / SSBpR_unf;
+      SSBpR_temp = SSB_equil;
+      Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
       Bmsy = Equ_SpawnRecr_Result(1);  //  with MSY set to SPR, not directly estimated
       Recr_msy = Equ_SpawnRecr_Result(2);
       yld1(1) = YPR_opt * Recr_msy;
@@ -1440,9 +1445,9 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           }
           Do_Equil_Calc(equ_Recr);
           //  SPAWN-RECR:   calc spawn-recr for MSY calcs;  need to make area-specific
-          MSY_SPR = SSB_equil / SPR_unf;
-          SPR_temp = SSB_equil;
-          Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+          MSY_SPR = SSB_equil / SSBpR_unf;
+          SSBpR_temp = SSB_equil;
+          Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
           Bmsy = Equ_SpawnRecr_Result(1);  //  MSY is directly estimated
           Recr_msy = Equ_SpawnRecr_Result(2);
           Profit = (PricePerF * YPR_val_vec) * Recr_msy - Cost;
@@ -1733,10 +1738,10 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
           //  else  Hrate for bycatch fleets already set
         }
         Do_Equil_Calc(equ_Recr);
-        SPR_Btgt2 = SSB_equil / SPR_unf;
+        SPR_Btgt2 = SSB_equil / SSBpR_unf;
         //  SPAWN-RECR:   calc equil spawn-recr for Btarget calcs;  need to make area-specific
-        SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+        SSBpR_temp = SSB_equil;
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         yld1(ii) = Equ_SpawnRecr_Result(1);
       }
 
diff --git a/SS_param.tpl b/SS_param.tpl
index 3d000222..6a454579 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -165,8 +165,8 @@ PARAMETER_SECTION
   number two_sigmaRsq;
   number half_sigmaRsq;
   number sigmaR;
-  number SPR_virgin;
-  number SPR_virgin_adj;
+  number SSBpR_virgin;
+  number SSBpR_virgin_adj;
   number regime_change;
   number rho;
   number dirichlet_Parm;
@@ -249,7 +249,7 @@ PARAMETER_SECTION
 
   number SPR_trial
   number SPR_actual;
-  number SPR_temp;  //  used to pass quantity into Equil_SpawnRecr
+  number SSBpR_temp;  //  SSB per Recruit; used to pass quantity into Equil_SpawnRecr
   number Recruits;                            // Age0 Recruits
   number equ_mat_bio
   number equ_mat_num
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index a0297e3c..d475456a 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -343,8 +343,8 @@ FUNCTION void get_initial_conditions()
   {
     equ_Recr = 1.0;
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation.  Returns SPR because R = 1.0
-    SPR_virgin = SSB_equil; //  spawners per recruit.  Needed for Sr_fxn = 10
-    SPR_virgin_adj = SSB_equil;  //  also needed for Sr_fxn 10.  Will get revised in benchmark to use averaged biology if requested.
+    SSBpR_virgin = SSB_equil; //  spawners per recruit.  Needed for Sr_fxn = 10
+    SSBpR_virgin_adj = SSB_equil;  //  also needed for Sr_fxn 10.  Will get revised in benchmark to use averaged biology if requested.
     if(SR_fxn == 10)  // B-H with a,b
     {
   //  WHAM based on R = A*S/(1+B*S)
@@ -355,8 +355,8 @@ FUNCTION void get_initial_conditions()
 
       alpha = mfexp(SR_parm(3));
       beta = mfexp(SR_parm(4));
-      steepness = alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj);
-      Recr_virgin = 1. / beta * (alpha - (1. / SPR_virgin_adj));
+      steepness = alpha * SSBpR_virgin_adj / (4. + alpha * SSBpR_virgin_adj);
+      Recr_virgin = 1. / beta * (alpha - (1. / SSBpR_virgin_adj));
 //      warning << " before AB_calcs " << "parm " << SR_parm(1) << " calc " << log(Recr_virgin) << endl;
       SR_parm(1) = log(Recr_virgin);
       SR_parm(2) = steepness;
@@ -380,7 +380,7 @@ FUNCTION void get_initial_conditions()
     exp_rec(eq_yr, 4) = Recr_virgin;
     Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
     SSB_virgin = SSB_equil;
-//    SPR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit already calculated
+//    SSBpR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit already calculated
     if(Do_Benchmark==0)  // assign values that would be created in benchmark section
     {
       Mgmt_quant(1) = SSB_virgin;
@@ -533,10 +533,10 @@ FUNCTION void get_initial_conditions()
 
     Do_Equil_Calc(equ_Recr);
     CrashPen += Equ_penalty;
-    SPR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
-    //  get equilibrium SSB and recruitment from SPR_temp, Recr_virgin and virgin steepness
+    SSBpR_temp = SSB_equil / equ_Recr; //  spawners per recruit at initial F
+    //  get equilibrium SSB and recruitment from SSBpR_temp, Recr_virgin and virgin steepness
     //  this is the initial year, so no time-vary effects available, so uses _virgin quantities for spawner-recruitment
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     R1_exp = Equ_SpawnRecr_Result(2); //  set the expected recruitment equal to this equilibrium
     exp_rec(eq_yr, 1) = R1_exp;
 
@@ -1040,6 +1040,7 @@ FUNCTION void get_time_series()
           bio_yr = y;
           Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation with current year's biology and adjusted R0
           SSB_use = SSB_equil;
+          SSBpR_virgin_adj = SSB_use / R0_use;  //  update 
           if (fishery_on_off == 1)
           {
             Fishon = 1;
@@ -1498,6 +1499,7 @@ FUNCTION void get_time_series()
           bio_yr = y;
           Do_Equil_Calc(R0_use); //  call function to do equilibrium calculation
           SSB_use = SSB_equil;
+          SSBpR_virgin_adj = SSB_use / R0_use;  //  update 
           if (fishery_on_off == 1)
           {
             Fishon = 1;
diff --git a/SS_recruit.tpl b/SS_recruit.tpl
index 5766efce..645dbcf3 100644
--- a/SS_recruit.tpl
+++ b/SS_recruit.tpl
@@ -268,7 +268,7 @@ FUNCTION void apply_recdev(prevariable& NewRecruits, const prevariable& Recr_vir
  /*  SS_Label_FUNCTION 44 Equil_Spawn_Recr_Fxn */
 //  SPAWN-RECR:   function  Equil_Spawn_Recr_Fxn
 FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
-    const prevariable& SSB_virgin_use, const prevariable& Recr_virgin_use, const prevariable& SPR_current)
+    const prevariable& SSB_virgin_use, const prevariable& Recr_virgin_use, const prevariable& SSBpR_current)
   {
   RETURN_ARRAYS_INCREMENT();
   dvar_vector Equil_Spawn_Recr_Calc(1, 2); // values to return 1 is B_equil, 2 is R_equil
@@ -284,7 +284,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
   dvariable SRZ_surv;
 
   steepness = SRparm(2); //  common usage but some different
-  //  SS_Label_44.1  calc equilibrium SpawnBio and Recruitment from input SPR_current, which is spawning biomass per recruit at some given F level
+  //  SS_Label_44.1  calc equilibrium SpawnBio and Recruitment from input SSBpR_current, which is spawning biomass per recruit at some given F level
   switch (SR_fxn)
   {
     case 1: // previous placement for B-H constrained
@@ -297,7 +297,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     //  SS_Label_44.1.2  Ricker
     case 2: // Ricker
     {
-      B_equil = SSB_virgin_use * (1. + (log(Recr_virgin_use / SSB_virgin_use) + log(SPR_current)) / steepness);
+      B_equil = SSB_virgin_use * (1. + (log(Recr_virgin_use / SSB_virgin_use) + log(SSBpR_current)) / steepness);
       R_equil = Recr_virgin_use * B_equil / SSB_virgin_use * mfexp(steepness * (1. - B_equil / SSB_virgin_use));
 
       break;
@@ -316,19 +316,17 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 
   //  SS3 previously used alternative formulation: R = A*S/(B+S)
   //  converting SS3 to align with WHAM
-  //    SPR_virgin = SSB_virgin_use / Recr_virgin_use;  //  this is already defined
-      alpha = 4.0 * steepness / (SPR_virgin_adj * (1. - steepness));
-      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin);
-
-      // " h " << steepness << " derive "  << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " " << endl;
-      // " R0 " << Recr_virgin_use << " derive "  << 1. / beta * (alpha - 1./SPR_virgin) << endl;
-//      report5 <<" SSB_unf "<<SSB_virgin_use<<" SPR_unf "<<SPR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin_use << endl;
+      alpha = 4.0 * steepness / (SSBpR_virgin_adj * (1. - steepness));
+      beta = (5.0 * steepness - 1.0) / ((1 - steepness) * SSB_virgin_use);
+      // " h " << steepness << " derive "  << alpha * SSBpR_virgin / (4. + alpha * SSBpR_virgin) << " " << endl;
+      // " R0 " << Recr_virgin_use << " derive "  << 1. / beta * (alpha - 1./SSBpR_virgin) << endl;
+//      report5 <<" SSB_unf "<<SSB_virgin_use<<" SSBpR_unf "<<SSBpR_virgin<<" steep: "<<steepness<<" R0: "<<Recr_virgin_use << endl;
 //      report5 <<" derive_alpha "<<alpha<<" derive_beta "<<beta << endl;
-//      report5 << " deriv_h: " << alpha * SPR_virgin / (4. + alpha * SPR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SPR_virgin))<<endl;
-      B_equil = (alpha * SPR_current - 1.0) / beta;
+//      report5 << " deriv_h: " << alpha * SSBpR_virgin / (4. + alpha * SSBpR_virgin) << " derive_R0: " << 1. / beta * (alpha - (1. / SSBpR_virgin))<<endl;
+      B_equil = (alpha * SSBpR_current - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5 << "SPR_input: " << SPR_current << " B_equil: " << B_equil << " R_equil: "<<R_equil << endl<<endl;
+//      report5 << "SPR_input: " << SSBpR_current << " B_equil: " << B_equil << " R_equil: "<<R_equil << endl<<endl;
 
       break;
     }
@@ -337,17 +335,17 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       dvariable alpha = mfexp(SRparm(3));
       dvariable beta = mfexp(SRparm(4));
-      B_equil = (alpha * SPR_current - 1.0) / beta;
+      B_equil = (alpha * SSBpR_current - 1.0) / beta;
       B_equil = posfun(B_equil, 0.0001, temp);
       R_equil = alpha * B_equil / (1.0 + beta * B_equil);
-//      report5<<SPR_current<<" Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
+//      report5<<SSBpR_current<<" Beq "<<B_equil<<" Req "<<R_equil<<" alpha "<<alpha<<" beta "<<beta<<" SSB_unf "<<SSB_unf<<endl;
       break;
     }
 
     //  SS_Label_44.1.4  constant recruitment
     case 4: // constant; no bias correction
     {
-      B_equil = SPR_current * Recr_virgin_use;
+      B_equil = SSBpR_current * Recr_virgin_use;
       R_equil = Recr_virgin_use;
       break;
     }
@@ -357,7 +355,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
       dvariable hockey_min = SRparm(3) * Recr_virgin_use; // min recruitment level
       //        temp=SSB_virgin_use/R0*steepness;  // spawners per recruit at inflection
       dvariable hockey_slope = (Recr_virgin_use - hockey_min) / (steepness * SSB_virgin_use); //  slope of recruitment on spawners below the inflection
-      B_equil = Join_Fxn(0.0 * SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use * steepness, SPR_current, hockey_min / ((1. / SPR_current) - hockey_slope), SPR_current * Recr_virgin_use);
+      B_equil = Join_Fxn(0.0 * SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use, SSB_virgin_use / Recr_virgin_use * steepness, SSBpR_current, hockey_min / ((1. / SSBpR_current) - hockey_slope), SSBpR_current * Recr_virgin_use);
       R_equil = Join_Fxn(0.0 * SSB_virgin_use, SSB_virgin_use, SSB_virgin_use * steepness, B_equil, hockey_min + hockey_slope * B_equil, Recr_virgin_use);
       break;
     }
@@ -366,7 +364,7 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       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. / SPR_current) - SRZ_0) / pow((srz_min - SRZ_0), (1. / SRparm(3))));
+      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;
       break;
@@ -389,11 +387,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
       Shepherd_c2 = pow(0.2, SRparm(3));
       Hupper = 1.0 / (5.0 * Shepherd_c2);
       steepness = 0.2 + (SRparm(2) - 0.2) / (0.8) * (Hupper - 0.2);
-      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SPR_current * Recr_virgin_use) / SSB_virgin_use - (1.0 - 5.0 * steepness * Shepherd_c2);
+      Shep_top = 5.0 * steepness * (1.0 - Shepherd_c2) * (SSBpR_current * Recr_virgin_use) / SSB_virgin_use - (1.0 - 5.0 * steepness * Shepherd_c2);
       Shep_bot = 5.0 * steepness - 1.0;
       Shep_top2 = posfun(Shep_top, 0.001, temp);
-      R_equil = (SSB_virgin_use / SPR_current) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
-      B_equil = R_equil * SPR_current;
+      R_equil = (SSB_virgin_use / SSBpR_current) * pow((Shep_top2 / Shep_bot), (1.0 / SRparm(3)));
+      B_equil = R_equil * SSBpR_current;
       break;
     }
 
@@ -402,11 +400,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
     {
       steepness = SRparm(2);
       dvariable RkrPower = SRparm(3);
-      temp = SSB_virgin_use / (SPR_current * Recr_virgin_use);
+      temp = SSB_virgin_use / (SSBpR_current * Recr_virgin_use);
       dvariable RkrTop = pow(0.8, RkrPower) * log(temp) / log(5.0 * steepness);
       RkrTop = posfun(RkrTop, 0.000001, CrashPen);
       R_equil = temp * Recr_virgin_use * (1.0 - pow(RkrTop, 1.0 / RkrPower));
-      B_equil = R_equil * SPR_current;
+      B_equil = R_equil * SSBpR_current;
       break;
     }
 
@@ -428,11 +426,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
         Hupper=1.0/(5.0*Shepherd_c2);
         steepness=0.20001+((0.8)/(1.0+exp(-SRparm2))-0.2)/(0.8)*(Hupper-0.2);
 //        steep2=0.20001+(steepness-0.2)/(0.8)*(Hupper-0.2);
-        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SPR_current*Recr_virgin_use)/SSB_virgin_use-(1.0-5.0*steepness*Shepherd_c2);
+        Shep_top=5.0*steepness*(1.0-Shepherd_c2)*(SSBpR_current*Recr_virgin_use)/SSB_virgin_use-(1.0-5.0*steepness*Shepherd_c2);
         Shep_bot=5.0*steepness-1.0;
         Shep_top2=posfun(Shep_top,0.001,temp);
-        R_equil=(SSB_virgin_use/SPR_current) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
-        B_equil=R_equil*SPR_current;
+        R_equil=(SSB_virgin_use/SSBpR_current) * pow((Shep_top2/Shep_bot),(1.0/Shepherd_c));
+        B_equil=R_equil*SSBpR_current;
         break;
       }
 
@@ -448,11 +446,11 @@ FUNCTION dvar_vector Equil_Spawn_Recr_Fxn(const dvar_vector& SRparm,
 //   if (Recs < 0) Rec2 = 0; else Rec2 = Recs;
         steepness = 0.2 + (10.0 - 0.2)/(1+exp(-SR_parm_work(2)));
         dvariable RkrPower=exp(SR_parm_work(3));
-        temp=SSB_virgin/(SPR_current*Recr_virgin_use);
+        temp=SSB_virgin/(SSBpR_current*Recr_virgin_use);
         dvariable RkrTop =  pow(0.8,RkrPower)*log(temp)/log(5.0*steepness);
         RkrTop = posfun(RkrTop,0.000001,CrashPen);
         R_equil = temp *Recr_virgin_use * (1.0 - pow(RkrTop,1.0/RkrPower));
-        B_equil=R_equil*SPR_current;
+        B_equil=R_equil*SSBpR_current;
         break;
       }
    */
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index 25e2f936..4a48fa0f 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1803,13 +1803,13 @@ FUNCTION void write_bigoutput()
 
     SS2out << "# " <<endl;
     SS2out << "sigmaR: "<< sigmaR  << endl;
-    SS2out << "SPR0_(virgin): " << SPR_virgin << " #_uses_biology_from_start_year: " << styr <<endl;
+    SS2out << "SPR0_(virgin): " << SSBpR_virgin << " #_uses_biology_from_start_year: " << styr <<endl;
 
     switch (SR_fxn)
     {
       case 3: // Beverton-Holt with steepness
     {
-      alpha = 4.0 * steepness / (SPR_virgin_adj * (1. - steepness));
+      alpha = 4.0 * steepness / (SSBpR_virgin_adj * (1. - steepness));
       beta = (5.0 * steepness - 1.0) / ((1. - steepness) * SSB_virgin);
       SS2out << "Ln(R0): " << SR_parm(1) << endl << "R0: " << mfexp(SR_parm(1)) << endl;
       SS2out << "steepness: " << steepness << endl;
@@ -1821,8 +1821,8 @@ FUNCTION void write_bigoutput()
     {
       SS2out << "Ln(alpha): " << SR_parm(3) << " alpha " << mfexp(SR_parm(3)) << endl;
       SS2out << "Ln(beta): " << SR_parm(4) << " beta " << mfexp(SR_parm(4)) << endl;
-      SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SPR_virgin_adj))) << endl;  //  virgin R0
-      SS2out << "steepness_derived: " << alpha * SPR_virgin_adj / (4. + alpha * SPR_virgin_adj) << endl;  // steepness virgin
+      SS2out << "ln(R0)_derived: " << log( 1. / beta * (alpha - (1. / SSBpR_virgin_adj))) << endl;  //  virgin R0
+      SS2out << "steepness_derived: " << alpha * SSBpR_virgin_adj / (4. + alpha * SSBpR_virgin_adj) << endl;  // steepness virgin
       break;
     }
     case 8:
@@ -1854,7 +1854,7 @@ FUNCTION void write_bigoutput()
     { if (Bmark_Yr(k+1) > Bmark_Yr(k))
       {SS2out << "#_range_of_years_is_averaged,_so_reduces_standard_error_of_result;_do_this_only_when_timevarying_makes_necessary:  " << k << " "<< k+1 << endl;}
     }
-    SS2out << "SPR_unfished_benchmark: " << Mgmt_quant(1) / Mgmt_quant(4) << "  #_based_on_averaging_biology_over_benchmark_year_range " << endl;
+    SS2out << "SSBpR_unfished_benchmark: " << Mgmt_quant(1) / Mgmt_quant(4) << "  #_based_on_averaging_biology_over_benchmark_year_range " << endl;
     SS2out << "Bmsy/Bzero: "<< Bmsy / SSB_virgin  << " # using styr bio for Bzero" << endl;
     SS2out << "Bmsy/Bunf: "<< Bmsy / Mgmt_quant(1)  << " # using MSY's averaged bio for Bunf" << endl;
 
@@ -4862,8 +4862,8 @@ FUNCTION void SPR_profile()
 
         Do_Equil_Calc(equ_Recr);
         //  SPAWN-RECR:   calc equil spawn-recr in the SPR loop
-        SPR_temp = SSB_equil;
-        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SPR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+        SSBpR_temp = SSB_equil;
+        Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_temp); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
         Btgt_prof = Equ_SpawnRecr_Result(1);
         Btgt_prof_rec = Equ_SpawnRecr_Result(2);
         if (Btgt_prof < 0.001 || Btgt_prof_rec < 0.001)

From 7a7ebf7a2a60cbfd90ddeb5f155fa27bb68eaf42 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Fri, 20 Sep 2024 09:58:02 -0700
Subject: [PATCH 25/29] create new switch to control updating of SSBpR0

---
 SS_benchfore.tpl       | 12 +++++-----
 SS_popdyn.tpl          |  8 +++----
 SS_readcontrol_330.tpl | 53 +++++++++++++++++++++++++++++++++++++-----
 SS_write_ssnew.tpl     |  6 ++++-
 4 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 79a792fa..d2cee309 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -745,7 +745,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     }
   }
 
-  if (SR_update_SPR0 == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations
+  if (SR_update_SSBpR0_bmark == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations in bmark
   {
      Recr_unf = Recr_virgin;
      SSB_unf = SSB_virgin;
@@ -764,7 +764,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
             << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
-    if ( SR_update_SPR0 == 1) report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
+    if ( SR_update_SSBpR0_bmark == 1) report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SSBpR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SSBpR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
 
@@ -1064,7 +1064,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     if (show_MSY == 1)
     {
       report5 << "#" << endl;
-  if (SR_update_SPR0 == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations
+  if (SR_update_SSBpR0_bmark == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations
     {report5 << "Find_target_SSB/Bzero; where Bzero is Virgin SSB:" << SSB_unf << " where SSBpR_unf = " << SSBpR_unf << endl;}
   else
     {report5 << "Find_target_SSB/Bzero; where Bzero is for Bmark biology and updated SPR0: " << SSB_unf << " where SSBpR_unf = " << SSBpR_unf << endl;}
@@ -1945,7 +1945,7 @@ FUNCTION void Get_Forecast()
   dvariable OFL_catch;
   dvariable Fcast_Crash;
   dvariable totcatch;
-  dvariable R0_use;  // annually updated variable if SR_update_SPR0 == 1
+  dvariable R0_use;  // annually updated value if SR_update_SSBpR0_timeseries == 1
   dvariable SSB_use;  // selected version of SSB that gets passes to Spawn_Recr
   dvar_matrix catage_w(1, gmorph, 0, nages);
   dvar_vector tempcatch(1, Nfleet);
@@ -2592,7 +2592,7 @@ FUNCTION void Get_Forecast()
             }
             //  SPAWN-RECR:   get recruitment in forecast;  needs to be area-specific
             // SR_fxn
-            if (SR_update_SPR0 == 0) //  R0 is not time-varying
+            if (SR_update_SSBpR0_timeseries == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
               SSB_use = SSB_virgin;
@@ -3230,7 +3230,7 @@ FUNCTION void Get_Forecast()
             //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass
             //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
             // SR_fxn
-            if (SR_update_SPR0 == 0) //  R0 is not time-varying
+            if (SR_update_SSBpR0_timeseries == 0) //  R0 is not time-varying
             {
               R0_use = Recr_virgin;
               SSB_use = SSB_virgin;
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index d475456a..e5fda47c 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -697,7 +697,7 @@ FUNCTION void get_time_series()
   dvariable crashtemp1;
   dvariable interim_tot_catch;
   dvariable Z_adjuster;
-  dvariable R0_use;  // annually updated variable if SR_update_SPR0 == 1; gets passed to Spawn_Recr() function
+  dvariable R0_use;  // annually updated variable if SR_update_SSBpR0_timeseries == 1; gets passed to Spawn_Recr() function
   dvariable SSB_use;
 
   if (Do_Morphcomp > 0)
@@ -1026,7 +1026,7 @@ FUNCTION void get_time_series()
         //  SS_Label_Info_24.2.3 #Get the total recruitment produced by this spawning biomass at the beginning of the season
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
         //  SR_Fxn  relevant keyword
-        if (SR_update_SPR0 == 0) //  SRparm are not time-varying
+        if (SR_update_SSBpR0_timeseries == 0) //  SRparm are not time-varying
         {
           R0_use = Recr_virgin;
           SSB_use = SSB_virgin;
@@ -1486,12 +1486,12 @@ FUNCTION void get_time_series()
         //  SS_Label_Info_24.3.4.1 #Get recruitment from this spawning biomass at some time during the season
         //  SPAWN-RECR:   calc recruitment in time series; need to make this area-specific
         //  SR_fxn
-        if (SR_update_SPR0 == 0) //  SR parms are not time-varying
+        if (SR_update_SSBpR0_timeseries == 0) //  SR parms are not time-varying
         {
           R0_use = Recr_virgin;
           SSB_use = SSB_virgin;
         }
-        else  //  update SSB_use and R0_use where will update SPR0 inside the Spawn_recr fxn
+        else  //  update SSB_use and R0_use where will update SSBpR0 inside the Spawn_recr fxn
         {
           R0_use = mfexp(SR_parm_work(1));  //  check to be sure this works when R0 is derived from B-H with alpha, beta parameters
           Fishon = 0;
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index 905f9a81..83f2632c 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1943,8 +1943,21 @@
 !!echoinput<<SR_fxn<<" #_SR_function: 1=NA; 2=Ricker(2 parms); 3=BevHolt(2); 4=SCAA(2); 5=Hockey(3); 6=B-H_flattop(2); 7=Survival(3); 8=Shepherd(3); 9=Ricker_Power(3); 10=B-H_a,b(4)"<<endl;
   init_int init_equ_steepness;
 !!echoinput<<init_equ_steepness<<"  # 0/1 to use steepness in initial equ recruitment calculation"<<endl;
-  init_int sigmaR_dendep;
-!! echoinput<<sigmaR_dendep<<"  #  future feature:  0/1 to make realized sigmaR a function of SR curvature"<<endl;
+  init_int SR_update_SSBpR0_rd;
+//  SR_update_SSBpR0_rd values
+//  1 best:  update SSBpR0 for benchmark and for time series only if SRparm R0 or h (not regime) is set to have time-varying property
+//  2 incorrect, relic:  always update SSBpR0 for benchmark's use of spawner-recruitment (old, incorrect SS3 approach), but only for the time series if there is a timevary SR parm
+//  3 option:  do not update SSBpR0 (do keep start year SPR0), even if R0 or h is set to have time-varying property
+  int SR_update_SSBpR0_bmark
+  int SR_update_SSBpR0_timeseries
+ LOCAL_CALCS
+  SR_update_SSBpR0_bmark = 0;
+  SR_update_SSBpR0_timeseries = 0;
+  echoinput<<SR_update_SSBpR0_rd<<"  #  controls effect of time-varying biology on spawner-recruitment updating" << endl;
+ END_CALCS
+
+//   echoinput<<sigmaR_dendep<<"  #  future feature:  0/1 to make realized sigmaR a function of SR curvature"<<endl;
+
   ivector N_SRparm(1,10)
 !!N_SRparm.fill("{0,2,2,2,3,2,3,3,3,4}");
   int N_SRparm2
@@ -1964,7 +1977,7 @@
   int timevary_parm_cnt_SR;
   ivector timevary_SRparm(styr-3,YrMax+1);
   ivector SR_parm_timevary(1,N_SRparm2);
-  int SR_update_SPR0  // 0/1 flag to control updating of SPR0 for timevary biology 
+  int SR_update_parm  // 0/1 flag to control updating of SPR0 for timevary biology 
 
  LOCAL_CALCS
   // clang-format on
@@ -1976,7 +1989,7 @@
   SR_parm_timevary.initialize();
   SR_env_link = 0;
   SR_env_target = 0;
-  SR_update_SPR0 = 0;
+  SR_update_parm = 0;
 
   //#_SR_function: 1=null; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=Survival_3Parm; 10=B-H with a,b "<<endl;
   if (SR_fxn == 10)
@@ -2129,8 +2142,8 @@
           timevary_SRparm(y) = timevary_pass(y);
         } // year vector for this category og MGparm
         // special consideration for impact on spawner-recruitment SPR0 calculations
-        if (SR_fxn == 10 && (SR_parm_timevary(3) > 0 || SR_parm_timevary(4) > 0) )  {SR_update_SPR0 = 1;}  //  alpha or beta is time-varying
-        else if ((SR_parm_timevary(1) > 0 || SR_parm_timevary(2) > 0) )  {SR_update_SPR0 = 1;}  //  R0 or steepness is time-varying
+        if (SR_fxn == 10 && (SR_parm_timevary(3) > 0 || SR_parm_timevary(4) > 0) )  {SR_update_parm = 1;}  //  alpha or beta is time-varying
+        else if ((SR_parm_timevary(1) > 0 || SR_parm_timevary(2) > 0) )  {SR_update_parm = 1;}  //  R0 or steepness is time-varying
       }
     }
   N_SRparm3 = N_SRparm2;
@@ -2142,6 +2155,34 @@
     echoinput << " SR timevary_parm_cnt start and end " << timevary_parm_start_SR << " " << timevary_parm_cnt_SR << endl;
     echoinput << "link to timevary parms:  " << SR_parm_timevary << endl;
   }
+
+//  SR_update_SSBpR0_rd values
+//  1 best:  update SSBpR0 for benchmark and for time series only if SRparm R0 or h (not regime) is set to have time-varying property
+//  2 incorrect, relic:  always update SSBpR0 for benchmark's use of spawner-recruitment (old, incorrect SS3 approach), but only for the time series if there is a timevary SR parm
+//  3 option:  do not update SSBpR0 (do keep start year SPR0), even if R0 or h is set to have time-varying property
+
+  switch (SR_update_SSBpR0_rd)
+  {
+  case 0:
+    if(timevary_MG_firstyr < YrMax)  // timevary biology exists and SR_update not set
+    {
+      warnstream << "user must select 1, 2, or 3 for updating SPR0 flag (formerly labelled future feature in SR input) because there is time-varying biology";
+      write_message (FATAL, 0); // EXIT!
+    }
+    break;
+  case 1:
+    SR_update_SSBpR0_bmark = 1 * SR_update_parm;  //  but conditional on SRparm_timevary, so update value there
+    SR_update_SSBpR0_timeseries = 1 * SR_update_parm;
+    break;
+  case 2:
+    SR_update_SSBpR0_bmark = 1;
+    SR_update_SSBpR0_timeseries = 0;
+    break;
+  case 3:
+    SR_update_SSBpR0_bmark = 0;
+    SR_update_SSBpR0_timeseries = 0;
+    break;
+  }
   echoinput << "SR_Npar and N_SRparm2 and N_SRparm3:  " << N_SRparm(SR_fxn) << " " << N_SRparm2 << " " << N_SRparm3 << endl;
   // clang-format off
  END_CALCS
diff --git a/SS_write_ssnew.tpl b/SS_write_ssnew.tpl
index ea8b9375..4f692468 100644
--- a/SS_write_ssnew.tpl
+++ b/SS_write_ssnew.tpl
@@ -2125,7 +2125,11 @@ FUNCTION void write_nucontrol()
   report4 << "#" << endl;
   report4 << SR_fxn << " #_Spawner-Recruitment; Options: 1=NA; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=survival_3Parm; 8=Shepherd_3Parm; 9=RickerPower_3parm" << endl;
   report4 << init_equ_steepness << "  # 0/1 to use steepness in initial equ recruitment calculation" << endl;
-  report4 << sigmaR_dendep << "  #  future feature:  0/1 to make realized sigmaR a function of SR curvature" << endl;
+  report4 << SR_update_SSBpR0_rd <<  "#  SR_update_SSBpR0" << endl <<
+  "#  0 - OK, but only if no timevary biology or SR parm" << endl <<
+  "#  1 - best: update SSBpR0 for benchmark and for time series only if SRparm R0 or h (not regime) is set to have time-varying property" << endl <<
+  "#  2 - incorrect (old, incorrect SS3 approach):  always update SSBpR0 for benchmark's use of spawner-recruitment, but only for the time series if there is a timevary SR parm" << endl <<
+  "#  3 - option:  do not update SSBpR0 (do keep start year SSBpR0), even if R0 or h is set to have time-varying property" << endl << "#" << endl;
   report4 << "#_          LO            HI          INIT         PRIOR         PR_SD       PR_type      PHASE    env-var    use_dev   dev_mnyr   dev_mxyr     dev_PH      Block    Blk_Fxn #  parm_name" << endl;
   report4.unsetf(std::ios_base::fixed);
   report4.unsetf(std::ios_base::floatfield);

From 735fff77e211f11642f9aaf09319543e3c88fb93 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Fri, 4 Oct 2024 14:58:13 -0700
Subject: [PATCH 26/29] too many changes

---
 SS_benchfore.tpl       | 82 +++++++++++++++++++++++-------------------
 SS_global.tpl          |  4 +--
 SS_param.tpl           | 11 +++---
 SS_popdyn.tpl          | 36 +++++++++----------
 SS_proced.tpl          |  6 ++--
 SS_readcontrol_330.tpl | 21 +++++------
 SS_readdata_330.tpl    |  4 +--
 SS_write.tpl           |  2 +-
 SS_write_report.tpl    | 44 +++++++----------------
 SS_write_ssnew.tpl     |  6 ++--
 10 files changed, 104 insertions(+), 112 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index d2cee309..702beb37 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -4,6 +4,15 @@
 // SS_Label_file  # * <u>get_forecast()</u>  //  calculates forecast quantities, includes all popdy characteristics of the time series, writes forecast-report.sso
 // SS_Label_file  #
 
+// Terminology
+// SSB refers to spawning stock biomass, calculated from reproductive output at age (fec()) and numbers-at-age at spawn_month in spawn_seas
+// SSBpR refers to SSB per recruit calculated with equilibrium age composition in equil_calc
+// SPR refers to spawner potential ratio which is the ratio of SSBpR at some level of F to SSBpR with F = 0
+
+// SSBpR_virgin  calculated and reported, but never used
+// SSBpR_virgin_adj  used only in the alpha-beta spawner-recruitment.  _adj means could be updated if SR_update_SSBpR0_timeseries == 1.  Also used to get alpha in equil_spawn_recr B-H
+//  but note that also uses SSB_virgin_use.  So need to align _use with _adj
+
 FUNCTION void setup_Benchmark()  // and forecast
   {
   //  SS_Label_Info_7.5 #Get averages from selected years to use in forecasts
@@ -113,12 +122,7 @@ FUNCTION void setup_Benchmark()  // and forecast
         }
     }
     t = styr + (endyr + 1 - styr) * nseas + spawn_seas - 1;
-    fec = Wt_Age_t(t, -2);
-    //        for (g=1;g<=gmorph;g++)
-    //        if(use_morph(g)>0 && sx(g)==1)
-    //        {
-    //          fec(g)=save_sel_num(t,0,g);
-    //       }
+//    fec = Wt_Age_t(t, -2);  this will always be overwritten, so deleting
 
     if (Fcast_Loop_Control(3) == 3) //  using mean recr_dist from range of years
     {
@@ -569,7 +573,6 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   eq_yr = y;
   t_base = y + (y - styr) * nseas - 1;
   bio_t_base = styr + (bio_yr - styr) * nseas - 1;
-
   //  set the Hrate for bycatch fleets so not scaled with other fleets
   //  bycatch_F(f,s) is created here for use in forecast
   for (f = 1; f <= Nfleet; f++)
@@ -643,6 +646,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       Make_AgeLength_Key(s, subseas);
 
       //  SPAWN-RECR:   call make_fecundity for benchmarks
+      //  this means that any calculation of SSB in benchmark will use the updated fec
+      //  but SSBpR0 will only use that updated fec if SR_update_SSBpR0_bmark == 1
       if (s == spawn_seas)
       {
         {
@@ -744,7 +749,6 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       SR_parm_work(j) = temp / (Bmark_Yr(10) - Bmark_Yr(9) + 1.);
     }
   }
-
   if (SR_update_SSBpR0_bmark == 0)  //  use virgin biology for the spawner-recruitment R0,h calculations in bmark
   {
      Recr_unf = Recr_virgin;
@@ -763,14 +767,17 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   if (show_MSY == 1)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
-            << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl;
-    if ( SR_update_SSBpR0_bmark == 1) report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
+            << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << " flag for updating SSBpR0 = " << SR_update_SSBpR0_bmark << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SSBpR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SSBpR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
-
-    Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
-    report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SSBpR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
-    report5 << "Repro_output_by_age_for_morph_1: " << fec(1) << endl;
+    if ( SR_update_SSBpR0_bmark == 1)
+    {
+      report5 << "SPR0 for equilibrium spawner-recruit based on benchmark biology, not virgin biology" << endl;
+      Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
+      report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SSBpR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
+    }
+    report5 << 0 << " y: " << y << " Repro_output_by_age_for_morph_1 bench " << fec(1) << endl;
+//    report5 << "Repro_output_by_age_for_morph_1: " << fec(1) << endl;
 
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
@@ -1849,7 +1856,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     report5 << "ann_F " << Mgmt_quant(10) << endl;
     report5 << "Exploit(Catch_dead/B_smry) " << YPR_spr_dead / Vbio1_spr << endl;
     report5 << "Recruits " << Bspr_rec << endl;
-    report5 << "SPBio " << Bspr << " " << Bspr / Bspr_rec << endl;
+    report5 << "SSBio " << Bspr << " " << Bspr / Bspr_rec << endl;
     report5 << "Catch_encountered " << YPR_spr_enc * Bspr_rec << " " << YPR_spr_enc << endl;
     report5 << "Catch_dead " << YPR_spr_dead * Bspr_rec << " " << YPR_spr_dead << endl;
     report5 << "Catch_retain " << YPR_spr_ret * Bspr_rec << " " << YPR_spr_ret << endl;
@@ -1869,7 +1876,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       report5 << "ann_F " << Mgmt_quant(7) << endl;
       report5 << "Exploit(Catch_dead/B_smry) " << YPR_Btgt_dead / Vbio1_Btgt << endl;
       report5 << "Recruits@F0.1 " << Btgt_Rec << endl;
-      report5 << "SPBio " << Btgt << " " << Btgt / Btgt_Rec << endl;
+      report5 << "SSBio " << Btgt << " " << Btgt / Btgt_Rec << endl;
       report5 << "Catch_encountered " << YPR_Btgt_enc * Btgt_Rec << " " << YPR_Btgt_enc << endl;
       report5 << "Catch_dead " << YPR_Btgt_dead * Btgt_Rec << " " << YPR_Btgt_dead << endl;
       report5 << "Catch_retain " << YPR_Btgt_ret * Btgt_Rec << " " << YPR_Btgt_ret << endl;
@@ -1889,7 +1896,7 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       report5 << "ann_F " << Mgmt_quant(7) << endl;
       report5 << "Exploit(Catch_dead/B_smry) " << YPR_Btgt_dead / Vbio1_Btgt << endl;
       report5 << "Recruits " << Btgt_Rec << endl;
-      report5 << "SPBio " << Btgt << " " << Btgt / Btgt_Rec << endl;
+      report5 << "SSBio " << Btgt << " " << Btgt / Btgt_Rec << endl;
       report5 << "Catch_encountered " << YPR_Btgt_enc * Btgt_Rec << " " << YPR_Btgt_enc << endl;
       report5 << "Catch_dead " << YPR_Btgt_dead * Btgt_Rec << " " << YPR_Btgt_dead << endl;
       report5 << "Catch_retain " << YPR_Btgt_ret * Btgt_Rec << " " << YPR_Btgt_ret << endl;
@@ -1906,9 +1913,9 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
     report5 << "ann_F " << Mgmt_quant(14) << endl;
     report5 << "Exploit(Catch/Bsmry) " << MSY / (Vbio1_MSY * Recr_msy) << endl;
     report5 << "Recruits@MSY " << Recr_msy << endl;
-    report5 << "SPBmsy " << Bmsy << " " << Bmsy / Recr_msy << endl;
-    report5 << "SPBmsy/SPB_virgin " << Bmsy / SSB_virgin << endl;
-    report5 << "SPBmsy/SPB_unfished " << Bmsy / SSB_unf << endl;
+    report5 << "SSBmsy " << Bmsy << " " << Bmsy / Recr_msy << endl;
+    report5 << "SSBmsy/SSB_virgin " << Bmsy / SSB_virgin << endl;
+    report5 << "SSBmsy/SSB_unfished " << Bmsy / SSB_unf << endl;
     report5 << "MSY_for_optimize " << MSY << " " << MSY / Recr_msy << endl;
     report5 << "MSY_encountered " << YPR_msy_enc * Recr_msy << " " << YPR_msy_enc << endl;
     report5 << "MSY_dead " << YPR_msy_dead * Recr_msy << " " << YPR_msy_dead << endl;
@@ -1934,6 +1941,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
            << " " << Vbio1_MSY * Recr_msy << " # " << endl;
   }
   write_bodywt = write_bodywt_save;
+    report5 << 0 << " y: " << y << " Repro_output_by_age_for_morph_1 end_bench: " << fec(1) << endl;
+//    report5 << "Repro_output_by_age_for_morph_1_after_benchmark: " << fec(1) << endl;
   } //  end benchmarks
 
 FUNCTION void Get_Forecast()
@@ -1945,8 +1954,6 @@ FUNCTION void Get_Forecast()
   dvariable OFL_catch;
   dvariable Fcast_Crash;
   dvariable totcatch;
-  dvariable R0_use;  // annually updated value if SR_update_SSBpR0_timeseries == 1
-  dvariable SSB_use;  // selected version of SSB that gets passes to Spawn_Recr
   dvar_matrix catage_w(1, gmorph, 0, nages);
   dvar_vector tempcatch(1, Nfleet);
   imatrix Do_F_tune(t_base, TimeMax_Fcast_std, 1, Nfleet); //  flag for doing F from catch
@@ -2220,6 +2227,8 @@ FUNCTION void Get_Forecast()
 
   for (int Fcast_Loop1 = 1; Fcast_Loop1 <= jloop; Fcast_Loop1++) //   for different forecast conditions
   {
+    report5 << Fcast_Loop1 << " y: " << 0 << " Repro_output_by_age_for_morph_1 top_forecast: " << fec(1) << endl;
+
     switch (Fcast_Loop1) //  select which ABC_loops to use
     {
       case 1: // do OFL only
@@ -2290,7 +2299,7 @@ FUNCTION void Get_Forecast()
           get_growth3(y, t, s, subseas); //  in case needed for Lorenzen M
           Make_AgeLength_Key(s, subseas); //  which also updates Wt_Age_beg, etc.
         }
-        if (s == spawn_seas)
+//        if (s == spawn_seas)  //  
         {
           if (WTage_rd == 1)
           {
@@ -2301,12 +2310,12 @@ FUNCTION void Get_Forecast()
           }
           else
           {
-            get_mat_fec();
+            get_mat_fec();  // does spawnseas and stores in wt_Age_t(t, -2)
           }
         }
       }
     }
-
+    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 endyr: " << fec(1) << endl;
     for (y = endyr + 1; y <= YrMax; y++)
     {
       t_base = styr + (y - styr) * nseas - 1;
@@ -2496,6 +2505,7 @@ FUNCTION void Get_Forecast()
                   Wt_Age_mid(s, g) = ALK(ALK_idx, g) * wt_len(s, GP(g)); // use for fisheries with no size selectivity
                 }
             }
+    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 annual: " << fec(1) << endl;
             Wt_Age_t(t, 0) = Wt_Age_beg(s);
             for (g = 1; g <= gmorph; g++)
               if (use_morph(g) > 0)
@@ -2575,18 +2585,18 @@ FUNCTION void Get_Forecast()
 
             if (Hermaphro_Option != 0) // get male biomass
             {
-              MaleSPB(y).initialize();
+              MaleSSB(y).initialize();
               for (p = 1; p <= pop; p++)
               {
                 for (g = 1; g <= gmorph; g++)
                   if (sx(g) == 2 && use_morph(g) > 0) //  male; all assumed to be mature
                   {
-                    MaleSPB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * natage(t, p, g); // accumulates SSB by area and by growthpattern
+                    MaleSSB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * natage(t, p, g); // accumulates SSB by area and by growthpattern
                   }
               }
-              if (Hermaphro_maleSPB > 0.0) // add MaleSPB to female SSB
+              if (Hermaphro_maleSSB > 0.0) // add MaleSSB to female SSB
               {
-                SSB_current += Hermaphro_maleSPB * sum(MaleSPB(y));
+                SSB_current += Hermaphro_maleSSB * sum(MaleSSB(y));
                 SSB_yr(y) = SSB_current;
               }
             }
@@ -2615,7 +2625,6 @@ FUNCTION void Get_Forecast()
               }
               SSB_use = SSB_equil;
             }
-
             Recruits = Spawn_Recr(SSB_use, R0_use, SSB_current); // calls to function Spawn_Recr
             if (SR_fxn != 7) apply_recdev(Recruits, R0_use); //  apply recruitment deviation
             if (Fcast_Loop1 < Fcast_Loop_Control(2)) //  use expected recruitment  this should include environ effect - CHECK THIS
@@ -3212,18 +3221,18 @@ FUNCTION void Get_Forecast()
 
             if (Hermaphro_Option != 0) // get male biomass
             {
-              MaleSPB(y).initialize();
+              MaleSSB(y).initialize();
               for (p = 1; p <= pop; p++)
               {
                 for (g = 1; g <= gmorph; g++)
                   if (sx(g) == 2 && use_morph(g) > 0) //  male; all assumed to be mature
                   {
-                    MaleSPB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * elem_prod(natage(t, p, g), mfexp(-Z_rate(t, p, g) * spawn_time_seas)); // accumulates SSB by area and by growthpattern
+                    MaleSSB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * elem_prod(natage(t, p, g), mfexp(-Z_rate(t, p, g) * spawn_time_seas)); // accumulates SSB by area and by growthpattern
                   }
               }
-              if (Hermaphro_maleSPB > 0.0) // add MaleSPB to female SSB
+              if (Hermaphro_maleSSB > 0.0) // add MaleSSB to female SSB
               {
-                SSB_current += Hermaphro_maleSPB * sum(MaleSPB(y));
+                SSB_current += Hermaphro_maleSSB * sum(MaleSSB(y));
                 SSB_yr(y) = SSB_current;
               }
             }
@@ -3662,7 +3671,7 @@ FUNCTION void Get_Forecast()
         Smry_Table(y, 4) = Mgmt_quant(Fcast_catch_start + y - endyr);
         eq_yr = y;
         equ_Recr = Recr_unf;
-        bio_yr = endyr;
+        bio_yr = y;
         Fishon = 0;
         Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
 
@@ -3670,7 +3679,7 @@ FUNCTION void Get_Forecast()
         Smry_Table(y, 13) = GenTime;
         if( SR_fxn == 10 )
         {
-          temp = SSB_equil / equ_Recr;  //  current year's SPB/R with current biology at age
+          temp = SSB_equil / equ_Recr;  //  current year's SSB/R with current biology at age
           alpha = mfexp(SR_parm_work(3));
           beta = mfexp(SR_parm_work(4));
           SR_parm_byyr(y, 2) =  alpha * temp / (4. + alpha * temp);  //  implied steepness
@@ -3678,6 +3687,7 @@ FUNCTION void Get_Forecast()
         }
         Fishon = 1;
         Do_Equil_Calc(equ_Recr); //  call function to do equilibrium calculation
+//             warning <<y<<"  SSB_virgin: " << SSB_virgin<< "SSB_use: "<<SSB_use<<" SSB_unf: "<<SSB_unf<<" fec(15): "<<fec(1,15)<<endl;
         if (STD_Yr_Reverse_Ofish(y) > 0)
           SPR_std(STD_Yr_Reverse_Ofish(y)) = SSB_equil / Smry_Table(y, 11);
         Smry_Table(y, 9) = totbio;
diff --git a/SS_global.tpl b/SS_global.tpl
index f2e976e1..aed4dd12 100644
--- a/SS_global.tpl
+++ b/SS_global.tpl
@@ -1270,10 +1270,10 @@ REPORT_SECTION
     if (Do_TG > 0)
       report << " TG-fleetcomp " << TG_like1 << endl
              << " TG-negbin " << TG_like2 << endl;
-    report << " -log(L): " << obj_fun << "  Spbio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr)) << endl;
+    report << " -log(L): " << obj_fun << "  SSBio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr)) << endl;
 
     report << endl
-           << "Year Spbio Recruitment" << endl;
+           << "Year SSBio Recruitment" << endl;
     report << "Virg " << SSB_yr(styr - 2) << " " << exp_rec(styr - 2, 4) << endl;
     report << "Init " << SSB_yr(styr - 1) << " " << exp_rec(styr - 1, 4) << endl;
     for (y = styr; y <= endyr; y++)
diff --git a/SS_param.tpl b/SS_param.tpl
index 6a454579..df290682 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -159,7 +159,7 @@ PARAMETER_SECTION
   3darray recr_dist_endyr(1,N_GP*gender,1,N_settle_timings,1,pop);
 !!//  SS_Label_Info_5.1.2 #Create SR_parm vector, recruitment vectors
   init_bounded_number_vector SR_parm(1,N_SRparm3,SR_parm_LO,SR_parm_HI,SR_parm_PH)
-  matrix SR_parm_byyr(styr-3,YrMax,1,N_SRparm2+1)  //  R0, steepness, parm3, sigmar, rec_dev_offset, R1, rho, SPB   Time_vary implementation of spawner-recruitment
+  matrix SR_parm_byyr(styr-3,YrMax,1,N_SRparm2+1)  //  R0, steepness, parm3, sigmar, rec_dev_offset, R1, rho, SSB   Time_vary implementation of spawner-recruitment
   vector SR_parm_virg(1,N_SRparm2+1)
   vector SR_parm_work(1,N_SRparm2+1)
   number two_sigmaRsq;
@@ -241,9 +241,12 @@ PARAMETER_SECTION
   number Recr_virgin
   number SSB_vir_LH
 
-  number SSB_unf
+  number SSB_unf //  SSB unfished, based on benchmark biology
   number Recr_unf
+  number SSB_use
+  number R0_use;  // annually updated value if SR_update_SSBpR0_timeseries == 1
 
+  number SSB_deplete //  SSB that will be used as denominator for depletion calculations and as basis for control rule inflection
   number SSB_current;                            // Spawning biomass
   number SSB_equil;
 
@@ -322,7 +325,7 @@ PARAMETER_SECTION
 !!k=0;
 !!if(Hermaphro_Option!=0) k=1;
 
-  3darray MaleSPB(styr-3,YrMax*k,1,pop,1,N_GP)         //Male Spawning biomass
+  3darray MaleSSB(styr-3,YrMax*k,1,pop,1,N_GP)         //Male Spawning biomass
 
   matrix SSB_equil_pop_gp(1,pop,1,N_GP);
   matrix MaleSSB_equil_pop_gp(1,pop,1,N_GP);
@@ -602,7 +605,7 @@ PARAMETER_SECTION
   
 !!//  SS_Label_Info_5.1.8 #Create matrix called smry to store derived quantities of interest
   matrix Smry_Table(styr-3,YrMax,1,20+2*gmorph);
-  // 1=totbio, 2=smrybio, 3=smrynum, 4=enc_catch, 5=dead_catch, 6=ret_catch, 7=spbio, 8=recruit,
+  // 1=totbio, 2=smrybio, 3=smrynum, 4=enc_catch, 5=dead_catch, 6=ret_catch, 7=SSBio, 8=recruit,
   // 9=equ_totbio, 10=equ_smrybio, 11=equ_SSB_virgin, 12=equ_S1, 13=Gentime, 14=YPR, 15=meanage_spawners, 16=meanage_smrynums, 17=meanage_catch
   // 18, 19, 20  not used
   // 21+cumF-bymorph, maxF-by morph
diff --git a/SS_popdyn.tpl b/SS_popdyn.tpl
index e5fda47c..e97b9bd1 100644
--- a/SS_popdyn.tpl
+++ b/SS_popdyn.tpl
@@ -383,7 +383,7 @@ FUNCTION void get_initial_conditions()
 //    SSBpR_virgin = SSB_equil / Recr_virgin; //  spawners per recruit already calculated
     if(Do_Benchmark==0)  // assign values that would be created in benchmark section
     {
-      Mgmt_quant(1) = SSB_virgin;
+      Mgmt_quant(1) = SSB_virgin;  //  can be overwritten in benchmark by updated SSB_unf
       SSB_unf = SSB_virgin;
       Recr_unf = Recr_virgin;
       Mgmt_quant(2) = totbio;  //  from equil calcs
@@ -395,7 +395,7 @@ FUNCTION void get_initial_conditions()
     Smry_Table(styr - 2, 3) = smrynum; //  from equil calcs
     SSB_pop_gp(eq_yr) = SSB_equil_pop_gp; // dimensions of pop x N_GP
     if (Hermaphro_Option != 0)
-      MaleSPB(eq_yr) = MaleSSB_equil_pop_gp;
+      MaleSSB(eq_yr) = MaleSSB_equil_pop_gp;
     SSB_yr(eq_yr) = SSB_equil;
     SR_parm_byyr(eq_yr, N_SRparm2 + 1) = SSB_equil;
     SR_parm_virg(N_SRparm2 + 1) = SSB_equil;
@@ -527,7 +527,7 @@ FUNCTION void get_initial_conditions()
     //  SS_Label_Info_23.5.1.2  #Adjustments  include spawner-recruitment function
     //  do initial equilibrium with R1 based on offset from spawner-recruitment curve, using same approach as the benchmark calculations
     //  first get SPR for this init_F
-    //  SPAWN-RECR:   calc initial equilibrium pop, SPB, Recruitment
+    //  SPAWN-RECR:   calc initial equilibrium pop, SSB, Recruitment
     //    equ_Recr=Recr_virgin;
     equ_Recr = R1_exp * regime_change;
 
@@ -554,7 +554,7 @@ FUNCTION void get_initial_conditions()
 
   SSB_pop_gp(eq_yr) = SSB_equil_pop_gp; // dimensions of pop x N_GP
   if (Hermaphro_Option != 0)
-    MaleSPB(eq_yr) = MaleSSB_equil_pop_gp;
+    MaleSSB(eq_yr) = MaleSSB_equil_pop_gp;
   SSB_yr(eq_yr) = SSB_equil;
   SR_parm_byyr(eq_yr, N_SRparm2 + 1) = SSB_equil;
   SR_parm_work(N_SRparm2 + 1) = SSB_equil;
@@ -697,14 +697,12 @@ FUNCTION void get_time_series()
   dvariable crashtemp1;
   dvariable interim_tot_catch;
   dvariable Z_adjuster;
-  dvariable R0_use;  // annually updated variable if SR_update_SSBpR0_timeseries == 1; gets passed to Spawn_Recr() function
-  dvariable SSB_use;
 
   if (Do_Morphcomp > 0)
     Morphcomp_exp.initialize();
 
   //  SS_Label_Info_24.0 #Retrieve spawning biomass and recruitment from the initial equilibrium
-  //  SPAWN-RECR:   begin of time series, retrieve last spbio and recruitment
+  //  SPAWN-RECR:   begin of time series, retrieve last SSBio and recruitment
   SSB_current = SSB_yr(styr); //  need these initial assignments in case recruitment distribution occurs before spawnbio&recruits
   if (recdev_doit(styr - 1) > 0)
   {
@@ -983,7 +981,7 @@ FUNCTION void get_time_series()
         }
       }
       //  SS_Label_Info_24.2.2 #Compute spawning biomass if this is spawning season so recruits could occur later this season
-      //  SPAWN-RECR:   calc SPB in time series if spawning is at beginning of the season
+      //  SPAWN-RECR:   calc SSB in time series if spawning is at beginning of the season
       if (s == spawn_seas && spawn_time_seas < 0.0001) //  compute spawning biomass if spawning at beginning of season so recruits could occur later this season
       {
         SSB_pop_gp(y).initialize();
@@ -1007,18 +1005,18 @@ FUNCTION void get_time_series()
 
         if (Hermaphro_Option != 0) // get male biomass
         {
-          MaleSPB(y).initialize();
+          MaleSSB(y).initialize();
           for (p = 1; p <= pop; p++)
           {
             for (g = 1; g <= gmorph; g++)
               if (sx(g) == 2 && use_morph(g) > 0) //  male; all assumed to be mature
               {
-                MaleSPB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * natage(t, p, g); // accumulates SSB by area and by growthpattern
+                MaleSSB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * natage(t, p, g); // accumulates SSB by area and by growthpattern
               }
           }
-          if (Hermaphro_maleSPB > 0.0) // add MaleSPB to female SSB
+          if (Hermaphro_maleSSB > 0.0) // add MaleSSB to female SSB
           {
-            SSB_current += Hermaphro_maleSPB * sum(MaleSPB(y));
+            SSB_current += Hermaphro_maleSSB * sum(MaleSSB(y));
             SSB_yr(y) = SSB_current;
           }
         }
@@ -1468,18 +1466,18 @@ FUNCTION void get_time_series()
 
         if (Hermaphro_Option != 0) // get male biomass
         {
-          MaleSPB(y).initialize();
+          MaleSSB(y).initialize();
           for (p = 1; p <= pop; p++)
           {
             for (g = 1; g <= gmorph; g++)
               if (sx(g) == 2 && use_morph(g) > 0) //  male; all assumed to be mature
               {
-                MaleSPB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * elem_prod(natage(t, p, g), mfexp(-Z_rate(t, p, g) * spawn_time_seas)); // accumulates SSB by area and by growthpattern
+                MaleSSB(y, p, GP4(g)) += Wt_Age_t(t, 0, g) * elem_prod(natage(t, p, g), mfexp(-Z_rate(t, p, g) * spawn_time_seas)); // accumulates SSB by area and by growthpattern
               }
           }
-          if (Hermaphro_maleSPB > 0.0) // add MaleSPB to female SSB
+          if (Hermaphro_maleSSB > 0.0) // add MaleSSB to female SSB
           {
-            SSB_current += Hermaphro_maleSPB * sum(MaleSPB(y));
+            SSB_current += Hermaphro_maleSSB * sum(MaleSSB(y));
             SSB_yr(y) = SSB_current;
           }
         }
@@ -1795,7 +1793,7 @@ FUNCTION void get_time_series()
       Smry_Table(y, 13) = GenTime;
       if( SR_fxn == 10 )
       {
-        temp = SSB_equil / Recr_virgin;  //  current year's SPB/R with current biology at age
+        temp = SSB_equil / Recr_virgin;  //  current year's SSB/R with current biology at age
         alpha = mfexp(SR_parm_work(3));
         beta = mfexp(SR_parm_work(4));
         SR_parm_byyr(y, 2) =  alpha * temp / (4. + alpha * temp);  //  implied steepness
@@ -2302,9 +2300,9 @@ FUNCTION void Do_Equil_Calc(const prevariable& equ_Recr)
   GenTime /= SSB_equil;
   smryage /= smrynum;
   cumF /= (r_ages(nages) - r_ages(Smry_Age) + 1.);
-  if (Hermaphro_maleSPB > 0.0) // add MaleSPB to female SSB
+  if (Hermaphro_maleSSB > 0.0) // add MaleSSB to female SSB
   {
-    SSB_equil += Hermaphro_maleSPB * sum(MaleSSB_equil_pop_gp);
+    SSB_equil += Hermaphro_maleSSB * sum(MaleSSB_equil_pop_gp);
   }
   } //  end equil calcs
 
diff --git a/SS_proced.tpl b/SS_proced.tpl
index b5fc8025..831e17ed 100644
--- a/SS_proced.tpl
+++ b/SS_proced.tpl
@@ -205,15 +205,15 @@ PROCEDURE_SECTION
       temp = sqrt((temp + 0.0000001) / (double(recdev_end - recdev_start + 1)));
       if (mcmc_counter == 0 && mceval_counter == 0)
       {
-        cout << current_phase() << " " << niter << " -log(L): " << obj_fun << "  Spbio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
+        cout << current_phase() << " " << niter << " -log(L): " << obj_fun << "  SSBio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
       }
       else if (mcmc_counter > 0)
       {
-        cout << " MCMC: " << mcmc_counter << " -log(L): " << obj_fun << "  Spbio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
+        cout << " MCMC: " << mcmc_counter << " -log(L): " << obj_fun << "  SSBio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
       }
       else if (mceval_counter > 0)
       {
-        cout << " MCeval: " << mceval_counter << " -log(L): " << obj_fun << "  Spbio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
+        cout << " MCeval: " << mceval_counter << " -log(L): " << obj_fun << "  SSBio: " << value(SSB_yr(styr)) << " " << value(SSB_yr(endyr));
       }
       if (F_Method > 1 && sum(catch_like) > 0.01)
       {
diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index 83f2632c..14bcf479 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -1148,11 +1148,11 @@
   int Hermaphro_seas;
   int Hermaphro_firstage;
   number Hermaphro_seas_rd;
-  number Hermaphro_maleSPB;
+  number Hermaphro_maleSSB;
  LOCAL_CALCS
   // clang-format on
   Hermaphro_seas = 0;
-  Hermaphro_maleSPB = 0.0;
+  Hermaphro_maleSSB = 0.0;
   Hermaphro_firstage = 0;
   MGparm_Hermaphro = 0;
   
@@ -1175,8 +1175,8 @@
     //  so  2.3 will do switch in season 2 beginning with age 3.
     echoinput << Hermaphro_seas << "  Hermaphro_season (-1 means all seasons)" << endl;
     echoinput << Hermaphro_firstage << "  Hermaphro_firstage (from decimal part of seas input; note that firstage can only be a single digit, so 9 is max" << endl;
-    *(ad_comm::global_datafile) >> Hermaphro_maleSPB; // read as a fraction (0.0 to 1.0) of the male SSB added into the total SSB
-    echoinput << Hermaphro_maleSPB << "  Hermaphro_maleSPB " << endl;
+    *(ad_comm::global_datafile) >> Hermaphro_maleSSB; // read as a fraction (0.0 to 1.0) of the male SSB added into the total SSB
+    echoinput << Hermaphro_maleSSB << "  Hermaphro_maleSSB " << endl;
   }
   // clang-format off
  END_CALCS
@@ -2183,6 +2183,7 @@
     SR_update_SSBpR0_timeseries = 0;
     break;
   }
+  echoinput << "SRupdate " << SR_update_parm << " use " << SR_update_SSBpR0_bmark << " rd " << SR_update_SSBpR0_rd<< endl;
   echoinput << "SR_Npar and N_SRparm2 and N_SRparm3:  " << N_SRparm(SR_fxn) << " " << N_SRparm2 << " " << N_SRparm3 << endl;
   // clang-format off
  END_CALCS
@@ -5795,7 +5796,7 @@
     Extra_Std_N += YrMax - (styr - 2) + 1;
     if (More_Std_Input(12) == 2) Extra_Std_N += YrMax - (styr - 2) + 1; //  for recruitment
   }
-  // add 3 values for ln(Spbio)
+  // add 3 values for ln(SSBio)
   // (years are automatically generated as startyr, mid-point, and endyr)
   Do_se_LnSSB = Extra_Std_N + 1;
   Extra_Std_N += 3;
@@ -6849,23 +6850,23 @@
     }
   }
   
-  //  output ln(SPB) std for selected years
-  echoinput << " do ln(SPB) std labels for 3 years" << endl;
+  //  output ln(SSB) std for selected years
+  echoinput << " do ln(SSB) std labels for 3 years" << endl;
   CoVar_Count++;
   j++;
   active_parm(CoVar_Count) = j;
   sprintf(onenum, "%d", styr);
-  ParmLabel += "ln(SPB)_" + onenum + CRLF(1);
+  ParmLabel += "ln(SSB)_" + onenum + CRLF(1);
   CoVar_Count++;
   j++;
   active_parm(CoVar_Count) = j;
   sprintf(onenum, "%d", int((endyr + styr) / 2));
-  ParmLabel += "ln(SPB)_" + onenum + CRLF(1);
+  ParmLabel += "ln(SSB)_" + onenum + CRLF(1);
   CoVar_Count++;
   j++;
   active_parm(CoVar_Count) = j;
   sprintf(onenum, "%d", endyr);
-  ParmLabel += "ln(SPB)_" + onenum + CRLF(1);
+  ParmLabel += "ln(SSB)_" + onenum + CRLF(1);
   
   if (Do_se_smrybio > 0)
   {
diff --git a/SS_readdata_330.tpl b/SS_readdata_330.tpl
index f10d7f98..b300f874 100644
--- a/SS_readdata_330.tpl
+++ b/SS_readdata_330.tpl
@@ -5034,10 +5034,10 @@
     if (STD_Yr_Reverse(y) > 0)
     {
       j++;
-      STD_Yr_Reverse(y) = j; // use for SPB and recruitment
+      STD_Yr_Reverse(y) = j; // use for SSB and recruitment
       if (y >= styr)
       {
-        // depletion must start in year AFTER first catch.  It could vary earlier if recdevs happened enough earlier to change spbio, but this is not included
+        // depletion must start in year AFTER first catch.  It could vary earlier if recdevs happened enough earlier to change SSBio, but this is not included
         if ((depletion_basis > 0 && y > first_catch_yr) || y == endyr)
         {
           N_STD_Yr_Dep++;
diff --git a/SS_write.tpl b/SS_write.tpl
index 96d516b3..a3664db4 100644
--- a/SS_write.tpl
+++ b/SS_write.tpl
@@ -1011,7 +1011,7 @@ FUNCTION void write_rebuilder_output()
       rebuild_dat << exp_rec(y, 4) << " ";
     }
     rebuild_dat << " #recruits; first value is R0 (virgin)" << endl;
-    rebuild_dat << SSB_yr(styr - 2) << " " << SSB_yr(styr, k) << " #spbio; first value is SSB_virgin (virgin)" << endl;
+    rebuild_dat << SSB_yr(styr - 2) << " " << SSB_yr(styr, k) << " #SSBio; first value is SSB_virgin (virgin)" << endl;
     rebuild_dat << 1 << " ";
     for (y = styr; y <= k; y++)
       rebuild_dat << 0 << " ";
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index 4a48fa0f..5a11e6bf 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -1483,8 +1483,8 @@ FUNCTION void write_bigoutput()
           if (s == spawn_seas)
           {
             temp = sum(SSB_pop_gp(y, p));
-            if (Hermaphro_maleSPB > 0)
-              temp += Hermaphro_maleSPB * sum(MaleSPB(y, p));
+            if (Hermaphro_maleSSB > 0)
+              temp += Hermaphro_maleSSB * sum(MaleSSB(y, p));
             SS2out << temp;
           }
           else
@@ -1496,7 +1496,7 @@ FUNCTION void write_bigoutput()
           {
             SS2out << SSB_pop_gp(y, p);
             if (Hermaphro_Option != 0)
-              SS2out << MaleSPB(y, p);
+              SS2out << MaleSSB(y, p);
           }
           else
           {
@@ -1661,7 +1661,7 @@ FUNCTION void write_bigoutput()
   if (k < 4)
     k = 4;
   // quantities to store summary statistics
-  dvector rmse(1, k); //  used in the SpBio, Index, Lencomp and Agecomp reports
+  dvector rmse(1, k); //  used in the SSBio, Index, Lencomp and Agecomp reports
   dvector Hrmse(1, k);
   dvector Rrmse(1, k);
   dvector n_rmse(1, k);
@@ -4683,33 +4683,11 @@ FUNCTION void SPR_profile()
   for (s = 1; s <= nseas; s++)
   {
     t = styr - 3 * nseas + s - 1;
-
-    if (MG_active(2) > 0 || MG_active(3) > 0 || save_for_report > 0 || WTage_rd > 0)
-    {
-      subseas = 1;
-      ALK_idx = (s - 1) * N_subseas + subseas; //  for midseason
-      Make_AgeLength_Key(s, subseas); //  for begin season
-      subseas = mid_subseas;
-      ALK_idx = (s - 1) * N_subseas + subseas; //  for midseason
-      Make_AgeLength_Key(s, subseas); //  for midseason
-      if (s == spawn_seas)
-      {
-        subseas = spawn_subseas;
-        if (spawn_subseas != 1 && spawn_subseas != mid_subseas)
-        {
-          //don't call get_growth3(subseas) because using an average ave_size
-          Make_AgeLength_Key(s, subseas); //  spawn subseas
-        }
-        get_mat_fec();
-      }
-    }
-
-    for (g = 1; g <= gmorph; g++)
-      if (use_morph(g) > 0)
-      {
-        ALK_idx = (s - 1) * N_subseas + mid_subseas; //  for midseason
-        Make_FishSelex();
-      }
+    Wt_Age_beg(s) = Wt_Age_t(t, 0); //  used for smrybio
+    Wt_Age_mid(s) = Wt_Age_t(t, -1);
+    if (s == spawn_seas)
+      fec = Wt_Age_t(t, -2);
+    report5 << 0 << " y: " << y << " updated_Repro_output spr/ypr: " << fec(1) << endl;
   }
 
   SS2out << "SPRloop Iter Bycatch Fmult F_report SPR YPR_dead YPR_dead*Recr YPR_ret*Recr Revenue Cost Profit SSB Recruits SSB/Bzero Tot_Catch ";
@@ -4963,7 +4941,7 @@ FUNCTION void Global_MSY()
   //  GLOBAL_MSY with knife-edge age selection, then slot-age selection
   SS2out << endl
          << pick_report_name(55) << endl;
-  y = styr - 3; //  stores the averaged
+  y = styr - 3; //  stores the averaged biology and selectivity, etc. from benchmark
   yz = y;
   bio_yr = y;
   eq_yr = y;
@@ -5042,7 +5020,9 @@ FUNCTION void Global_MSY()
       SS2out << "Actual ";
       show_MSY = 2; //  invokes just brief output in benchmark
       did_MSY = 0;
+    report5 << 0 << " y: " << y << " updated_Repro_output global_1: " << fec(1) << endl;
       Get_Benchmarks(show_MSY);
+    report5 << 0 << " y: " << y << " updated_Repro_output global_2: " << fec(1) << endl;
       did_MSY = 0;
     }
   }
diff --git a/SS_write_ssnew.tpl b/SS_write_ssnew.tpl
index 4f692468..b98fefa7 100644
--- a/SS_write_ssnew.tpl
+++ b/SS_write_ssnew.tpl
@@ -1537,7 +1537,7 @@ FUNCTION void write_nucontrol()
   NuStart << final_conv << " # final convergence criteria (e.g. 1.0e-04) " << endl;
   NuStart << retro_yr - endyr << " # retrospective year relative to end year (e.g. -4)" << endl;
   NuStart << Smry_Age << " # min age for calc of summary biomass" << endl;
-  NuStart << depletion_basis_rd << " # Depletion basis:  denom is: 0=skip; 1=X*SPBvirgin; 2=X*SPBmsy; 3=X*SPB_styr; 4=X*SPB_endyr; 5=X*dyn_Bzero;  values>=11 invoke N multiyr with 10s & 100s digit; append .1 to invoke log(ratio); e.g. 122.1 produces log(12 yr trailing average of B/Bmsy)" << endl;
+  NuStart << depletion_basis_rd << " # Depletion basis:  denom is: 0=skip; 1=X*SSBvirgin; 2=X*SSBmsy; 3=X*SSB_styr; 4=X*SSB_endyr; 5=X*dyn_Bzero;  values>=11 invoke N multiyr with 10s & 100s digit; append .1 to invoke log(ratio); e.g. 122.1 produces log(12 yr trailing average of B/Bmsy)" << endl;
   NuStart << depletion_level << " # Fraction (X) for Depletion denominator (e.g. 0.4)" << endl;
   NuStart << SPR_reporting << " # SPR_report_basis:  0=skip; 1=(1-SPR)/(1-SPR_tgt); 2=(1-SPR)/(1-SPR_MSY); 3=(1-SPR)/(1-SPR_Btarget); 4=rawSPR" << endl;
   NuStart << F_reporting << " # F_std_reporting_units: 0=skip; 1=exploitation(Bio); 2=exploitation(Num); 3=sum(Apical_F's); 4=mean F for range of ages (numbers weighted); 5=unweighted mean F for range of ages" << endl;
@@ -1930,7 +1930,7 @@ FUNCTION void write_nucontrol()
   if (Hermaphro_Option != 0)
   {
     report4 << Hermaphro_seas_rd << " # Hermaphro_season.first_age (seas=-1 means all seasons; first_age must be 0 to 9)" << endl
-            << Hermaphro_maleSPB << " # fraction_of_maleSSB_added_to_total_SSB " << endl;
+            << Hermaphro_maleSSB << " # fraction_of_maleSSB_added_to_total_SSB " << endl;
   }
 
   report4 << MGparm_def << " #_parameter_offset_approach for M, G, CV_G:  1- direct, no offset**; 2- male=fem_parm*exp(male_parm); 3: male=female*exp(parm) then old=young*exp(parm)" << endl;
@@ -2125,7 +2125,7 @@ FUNCTION void write_nucontrol()
   report4 << "#" << endl;
   report4 << SR_fxn << " #_Spawner-Recruitment; Options: 1=NA; 2=Ricker; 3=std_B-H; 4=SCAA; 5=Hockey; 6=B-H_flattop; 7=survival_3Parm; 8=Shepherd_3Parm; 9=RickerPower_3parm" << endl;
   report4 << init_equ_steepness << "  # 0/1 to use steepness in initial equ recruitment calculation" << endl;
-  report4 << SR_update_SSBpR0_rd <<  "#  SR_update_SSBpR0" << endl <<
+  report4 << SR_update_SSBpR0_rd <<  "  #  SR_update_SSBpR0" << endl <<
   "#  0 - OK, but only if no timevary biology or SR parm" << endl <<
   "#  1 - best: update SSBpR0 for benchmark and for time series only if SRparm R0 or h (not regime) is set to have time-varying property" << endl <<
   "#  2 - incorrect (old, incorrect SS3 approach):  always update SSBpR0 for benchmark's use of spawner-recruitment, but only for the time series if there is a timevary SR parm" << endl <<

From e33a3bdae2a8fa5169a088da661793af8edefcec Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Fri, 4 Oct 2024 16:23:39 -0700
Subject: [PATCH 27/29] add HCR_anchor in forecast.ss

---
 SS_benchfore.tpl    | 37 ++++++++++++++++++++-----------------
 SS_param.tpl        |  1 +
 SS_readdata_330.tpl |  4 ++--
 SS_write_report.tpl |  6 +++---
 SS_write_ssnew.tpl  |  3 ++-
 5 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index 702beb37..c2293f20 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -776,8 +776,6 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
       Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_unf, Recr_unf, SSBpR_unf); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
       report5 << " Benchmark SSB, R0, SPR0: " << SSB_unf << " " << Recr_unf << " "  << SSBpR_unf << " equil: " << Equ_SpawnRecr_Result << endl;
     }
-    report5 << 0 << " y: " << y << " Repro_output_by_age_for_morph_1 bench " << fec(1) << endl;
-//    report5 << "Repro_output_by_age_for_morph_1: " << fec(1) << endl;
 
   }
   SR_parm_work(N_SRparm2 + 1) = SSB_unf;
@@ -2211,6 +2209,11 @@ FUNCTION void Get_Forecast()
         break;
       }
     }
+    if (Fcast_Loop_Control(5) <= 1)
+    {HCR_anchor = SSB_unf;}
+    else if (Fcast_Loop_Control(5) ==2)
+    {HCR_anchor = SSB_virgin;}
+    report5 << "Control_rule_anchor_approach: " << Fcast_Loop_Control(5) << " HCR_anchor: " << HCR_anchor << endl;
     report5 << "#" << endl;
   }
 
@@ -2227,7 +2230,7 @@ FUNCTION void Get_Forecast()
 
   for (int Fcast_Loop1 = 1; Fcast_Loop1 <= jloop; Fcast_Loop1++) //   for different forecast conditions
   {
-    report5 << Fcast_Loop1 << " y: " << 0 << " Repro_output_by_age_for_morph_1 top_forecast: " << fec(1) << endl;
+//    report5 << Fcast_Loop1 << " y: " << 0 << " Repro_output_by_age_for_morph_1 top_forecast: " << fec(1) << endl;
 
     switch (Fcast_Loop1) //  select which ABC_loops to use
     {
@@ -2315,7 +2318,7 @@ FUNCTION void Get_Forecast()
         }
       }
     }
-    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 endyr: " << fec(1) << endl;
+//    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 endyr: " << fec(1) << endl;
     for (y = endyr + 1; y <= YrMax; y++)
     {
       t_base = styr + (y - styr) * nseas - 1;
@@ -2505,7 +2508,7 @@ FUNCTION void Get_Forecast()
                   Wt_Age_mid(s, g) = ALK(ALK_idx, g) * wt_len(s, GP(g)); // use for fisheries with no size selectivity
                 }
             }
-    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 annual: " << fec(1) << endl;
+//    report5 << Fcast_Loop1 << " y: " << y << " updated_Repro_output_by_age_for_morph_1 annual: " << fec(1) << endl;
             Wt_Age_t(t, 0) = Wt_Age_beg(s);
             for (g = 1; g <= gmorph; g++)
               if (use_morph(g) > 0)
@@ -2659,9 +2662,9 @@ FUNCTION void Get_Forecast()
           }
           else if (ABC_Loop == 2 && s == 1) // Calc the buffer in season 1, will use last year's spawnbio if multiseas and spawnseas !=1
           {
-            temp = SSB_unf;
-            join1 = 1. / (1. + mfexp(10. * (SSB_current - H4010_bot * temp)));
-            join2 = 1. / (1. + mfexp(10. * (SSB_current - H4010_top * temp)));
+
+            join1 = 1. / (1. + mfexp(10. * (SSB_current - H4010_bot * HCR_anchor)));
+            join2 = 1. / (1. + mfexp(10. * (SSB_current - H4010_top * HCR_anchor)));
 
             switch (HarvestPolicy)
             {
@@ -2674,8 +2677,8 @@ FUNCTION void Get_Forecast()
                 // ramp scales catch as f(B) and buffer (H4010_scale) applied to F
                 {
                   ABC_buffer(y) = H4010_scale_vec(y) *
-                          ((0.0001 * SSB_current / (H4010_bot * temp)) * (join1) // low
-                                      + (0.0001 + (1.0 - 0.0001) * (H4010_top * temp / SSB_current) * (SSB_current - H4010_bot * temp) / (H4010_top * temp - H4010_bot * temp)) * (1.0 - join1) // curve
+                          ((0.0001 * SSB_current / (H4010_bot * HCR_anchor)) * (join1) // low
+                                      + (0.0001 + (1.0 - 0.0001) * (H4010_top * HCR_anchor / SSB_current) * (SSB_current - H4010_bot * HCR_anchor) / (H4010_top * HCR_anchor - H4010_bot * HCR_anchor)) * (1.0 - join1) // curve
                                       ) *
                           (join2) // scale combo
                       +
@@ -2686,8 +2689,8 @@ FUNCTION void Get_Forecast()
                 // ramp scales F as f(B) and buffer (H4010_scale) applied to F
                 {
                   ABC_buffer(y) = H4010_scale_vec(y) *
-                          ((0.0001 * SSB_current / (H4010_bot * temp)) * (join1) // low
-                                      + (0.0001 + (1.0 - 0.0001) * (SSB_current - H4010_bot * temp) / (H4010_top * temp - H4010_bot * temp)) * (1.0 - join1) // curve
+                          ((0.0001 * SSB_current / (H4010_bot * HCR_anchor)) * (join1) // low
+                                      + (0.0001 + (1.0 - 0.0001) * (SSB_current - H4010_bot * HCR_anchor) / (H4010_top * HCR_anchor - H4010_bot * HCR_anchor)) * (1.0 - join1) // curve
                                       ) *
                           (join2) // scale combo
                       +
@@ -2698,8 +2701,8 @@ FUNCTION void Get_Forecast()
                 // ramp scales catch as f(B) and buffer (H4010_scale) applied to catch
                 {
                   ABC_buffer(y) = 1.0 *
-                          ((0.0001 * SSB_current / (H4010_bot * temp)) * (join1) // low
-                                      + (0.0001 + (1.0 - 0.0001) * (H4010_top * temp / SSB_current) * (SSB_current - H4010_bot * temp) / (H4010_top * temp - H4010_bot * temp)) * (1.0 - join1) // curve
+                          ((0.0001 * SSB_current / (H4010_bot * HCR_anchor)) * (join1) // low
+                                      + (0.0001 + (1.0 - 0.0001) * (H4010_top * HCR_anchor / SSB_current) * (SSB_current - H4010_bot * HCR_anchor) / (H4010_top * HCR_anchor - H4010_bot * HCR_anchor)) * (1.0 - join1) // curve
                                       ) *
                           (join2) // scale combo
                       +
@@ -2710,8 +2713,8 @@ FUNCTION void Get_Forecast()
                 // ramp scales F as f(B) and buffer (H4010_scale) applied to catch
                 {
                   ABC_buffer(y) = 1.0 *
-                          ((0.0001 * SSB_current / (H4010_bot * temp)) * (join1) // low
-                                      + (0.0001 + (1.0 - 0.0001) * (SSB_current - H4010_bot * temp) / (H4010_top * temp - H4010_bot * temp)) * (1.0 - join1) // curve
+                          ((0.0001 * SSB_current / (H4010_bot * HCR_anchor)) * (join1) // low
+                                      + (0.0001 + (1.0 - 0.0001) * (SSB_current - H4010_bot * HCR_anchor) / (H4010_top * HCR_anchor - H4010_bot * HCR_anchor)) * (1.0 - join1) // curve
                                       ) *
                           (join2) // scale combo
                       +
@@ -3514,7 +3517,7 @@ FUNCTION void Get_Forecast()
             f = fish_fleet_area(0, ff);
             if (fleet_type(f) == 1)
             {
-              if (ABC_Loop == 2 && HarvestPolicy >= 3)
+              if (ABC_Loop == 2 && HarvestPolicy >= 3)  //  alternative ABC_buffer approach
               {
                 catch_fleet(t, f) *= H4010_scale_vec(y);
               }
diff --git a/SS_param.tpl b/SS_param.tpl
index df290682..3c6147ea 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -235,6 +235,7 @@ PARAMETER_SECTION
   init_bounded_vector Fcast_recruitments(recdev_end+1,s,recdev_LO,recdev_HI,Fcast_recr_PH2)
   init_bounded_vector Fcast_impl_error(endyr+1,j,-1,1,k)
   vector ABC_buffer(endyr+1,YrMax);
+  number HCR_anchor  //  basis (denominator) bor inflection in control rule
 
 //  SPAWN-RECR:   define some spawning biomass and recruitment entities
   number SSB_virgin
diff --git a/SS_readdata_330.tpl b/SS_readdata_330.tpl
index b300f874..4b0a3ea3 100644
--- a/SS_readdata_330.tpl
+++ b/SS_readdata_330.tpl
@@ -4344,8 +4344,8 @@
       "even when the base is set to the mean of earlier recruitments" << endl;
     }
 
-    echoinput << Fcast_Loop_Control(5) << " #echo: loop control 5 not used" << endl;
-
+    echoinput << Fcast_Loop_Control(5) << " #control rule anchor: 1=unfished_benchmark_SSB(old_approach), 2=virgin_SSB " << endl;
+    
     echoinput << "#next enter year in which Fcast loop 3 caps and allocations begin to be applied" << endl;
     *(ad_comm::global_datafile) >> Fcast_Cap_FirstYear;
     echoinput << Fcast_Cap_FirstYear << " # echoed value" << endl;
diff --git a/SS_write_report.tpl b/SS_write_report.tpl
index 5a11e6bf..cf0c4a67 100644
--- a/SS_write_report.tpl
+++ b/SS_write_report.tpl
@@ -4687,7 +4687,7 @@ FUNCTION void SPR_profile()
     Wt_Age_mid(s) = Wt_Age_t(t, -1);
     if (s == spawn_seas)
       fec = Wt_Age_t(t, -2);
-    report5 << 0 << " y: " << y << " updated_Repro_output spr/ypr: " << fec(1) << endl;
+//    report5 << 0 << " y: " << y << " updated_Repro_output spr/ypr: " << fec(1) << endl;
   }
 
   SS2out << "SPRloop Iter Bycatch Fmult F_report SPR YPR_dead YPR_dead*Recr YPR_ret*Recr Revenue Cost Profit SSB Recruits SSB/Bzero Tot_Catch ";
@@ -5020,9 +5020,9 @@ FUNCTION void Global_MSY()
       SS2out << "Actual ";
       show_MSY = 2; //  invokes just brief output in benchmark
       did_MSY = 0;
-    report5 << 0 << " y: " << y << " updated_Repro_output global_1: " << fec(1) << endl;
+//    report5 << 0 << " y: " << y << " updated_Repro_output global_1: " << fec(1) << endl;
       Get_Benchmarks(show_MSY);
-    report5 << 0 << " y: " << y << " updated_Repro_output global_2: " << fec(1) << endl;
+//    report5 << 0 << " y: " << y << " updated_Repro_output global_2: " << fec(1) << endl;
       did_MSY = 0;
     }
   }
diff --git a/SS_write_ssnew.tpl b/SS_write_ssnew.tpl
index b98fefa7..d8a61230 100644
--- a/SS_write_ssnew.tpl
+++ b/SS_write_ssnew.tpl
@@ -1631,6 +1631,7 @@ FUNCTION void write_nucontrol()
   NuFore << HarvestPolicy << " # Control rule method (0: none; 1: ramp does catch=f(SSB), buffer on F; 2: ramp does F=f(SSB), buffer on F; 3: ramp does catch=f(SSB), buffer on catch; 4: ramp does F=f(SSB), buffer on catch) " << endl;
   NuFore << "# values for top, bottom and buffer exist, but not used when Policy=0" << endl;
   NuFore << H4010_top_rd << " # Control rule inflection for constant F (as frac of Bzero, e.g. 0.40); must be > control rule cutoff, or set to -1 to use Bmsy/SSB_unf " << endl;
+  NuFore << "# Also see HCR_anchor below" << endl;
   NuFore << H4010_bot << " # Control rule cutoff for no F (as frac of Bzero, e.g. 0.10) " << endl;
   NuFore << H4010_scale_rd << " # Buffer:  enter Control rule target as fraction of Flimit (e.g. 0.75), negative value invokes list of [year, scalar] with filling from year to YrMax " << endl;
   if (H4010_scale_rd < 0)
@@ -1654,7 +1655,7 @@ FUNCTION void write_nucontrol()
   {
     NuFore << Fcast_Loop_Control(4) << " # multiplier on base recruitment " << endl;
   }
-  NuFore << Fcast_Loop_Control(5) << " # not used" << endl << "#" << endl;
+  NuFore << Fcast_Loop_Control(5) << " # HCR_anchor: 0 or 1 uses unfished benchmark SSB (old hardwired approach), 2 = virgin SSB" << endl << "#" << endl;
 
   NuFore << Fcast_Cap_FirstYear << "  # FirstYear for caps and allocations (should be after years with fixed inputs) " << endl;
 

From 46fc4ee4357ef8a42f92783f5fa11944ce8ef630 Mon Sep 17 00:00:00 2001
From: Richard Methot <richard.methot@noaa.gov>
Date: Thu, 17 Oct 2024 16:07:03 -0700
Subject: [PATCH 28/29] latest update

---
 SS_benchfore.tpl   | 25 +++++++++++++------------
 SS_param.tpl       |  2 +-
 SS_write_ssnew.tpl |  2 +-
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/SS_benchfore.tpl b/SS_benchfore.tpl
index c2293f20..08c9c645 100644
--- a/SS_benchfore.tpl
+++ b/SS_benchfore.tpl
@@ -767,7 +767,8 @@ FUNCTION void Get_Benchmarks(const int show_MSY)
   if (show_MSY == 1)
   {
     report5 << "SR_parms for benchmark: " << SR_parm_work << endl
-            << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << " flag for updating SSBpR0 = " << SR_update_SSBpR0_bmark << endl;
+            << "Benchmark biology averaged over years: " << Bmark_Yr(1) << " " << Bmark_Yr(2) << endl << 
+            "input.SR_update_SSBpR0_rd: " << SR_update_SSBpR0_rd << "flag for updating SSBpR0_Bmark: " << SR_update_SSBpR0_bmark << endl;
     Equ_SpawnRecr_Result = Equil_Spawn_Recr_Fxn(SR_parm_work, SSB_virgin, Recr_virgin, SSBpR_virgin); //  returns 2 element vector containing equilibrium biomass and recruitment at this SPR
     report5 << " Virgin SSB, R0, SPR0: " << SSB_virgin << " " << Recr_virgin << " "  << SSBpR_virgin << " equil: " << Equ_SpawnRecr_Result << endl;
     if ( SR_update_SSBpR0_bmark == 1)
@@ -2176,10 +2177,16 @@ FUNCTION void Get_Forecast()
       {
         H4010_top = H4010_top_rd;
       }
+    if (Fcast_Loop_Control(5) <= 1)
+    {HCR_anchor = SSB_unf;}
+    else if (Fcast_Loop_Control(5) ==2)
+    {HCR_anchor = SSB_virgin;}
     report5 << "#" << endl;
     report5 << "N_forecast_yrs: " << N_Fcast_Yrs << endl;
-    report5 << "OY_Control_Rule "
-            << " Inflection: " << H4010_top << " Intercept: " << H4010_bot << " Scale: " << H4010_scale_vec(endyr + 1) << "; ";
+    report5 << "OY_Control_Rule:  Inflection: " << H4010_top << " Intercept: " << H4010_bot << " Scale: " << H4010_scale_vec(endyr + 1) << endl
+            << "Control_rule_anchor_approach: " << Fcast_Loop_Control(5) << " HCR_anchor: " << HCR_anchor << endl;
+    report5 << "#" << endl;
+
     switch (HarvestPolicy)
     {
       case 0: // none
@@ -2209,13 +2216,7 @@ FUNCTION void Get_Forecast()
         break;
       }
     }
-    if (Fcast_Loop_Control(5) <= 1)
-    {HCR_anchor = SSB_unf;}
-    else if (Fcast_Loop_Control(5) ==2)
-    {HCR_anchor = SSB_virgin;}
-    report5 << "Control_rule_anchor_approach: " << Fcast_Loop_Control(5) << " HCR_anchor: " << HCR_anchor << endl;
-    report5 << "#" << endl;
-  }
+    }
 
   int jloop;
   if (fishery_on_off == 1 || Do_Dyn_Bzero > 0)
@@ -2264,7 +2265,7 @@ FUNCTION void Get_Forecast()
       if (HarvestPolicy == 0)
         report5 << "pop year ABC_Loop season No_buffer bio-all bio-Smry SpawnBio Depletion recruit-0 ";
       if (HarvestPolicy <= 2)
-        report5 << "pop year ABC_Loop season Ramp&Buffer bio-all bio-Smry SpawnBio Depletion recruit-0 ";
+        report5 << "pop year ABC_Loop season Ramp&Buffer Buffer2 bio-all bio-Smry SpawnBio Depletion recruit-0 ";
       if (HarvestPolicy >= 3)
         report5 << "pop year ABC_Loop season Ramp bio-all bio-Smry SpawnBio Depletion recruit-0 ";
       for (int ff = 1; ff <= N_catchfleets(0); ff++)
@@ -3134,7 +3135,7 @@ FUNCTION void Get_Forecast()
             }
             if (show_MSY == 1)
             {
-              report5 << p << " " << y << " " << ABC_Loop << " " << s << " " << ABC_buffer(y) << " " << totbio << " " << smrybio << " ";
+              report5 << p << " " << y << " " << ABC_Loop << " " << s << " " << ABC_buffer(y) << " " << H4010_scale_vec(y) << " " << totbio << " " << smrybio << " ";
               if (s == spawn_seas)
               {
                 report5 << SSB_current << " ";
diff --git a/SS_param.tpl b/SS_param.tpl
index 3c6147ea..9a86f578 100644
--- a/SS_param.tpl
+++ b/SS_param.tpl
@@ -235,7 +235,7 @@ PARAMETER_SECTION
   init_bounded_vector Fcast_recruitments(recdev_end+1,s,recdev_LO,recdev_HI,Fcast_recr_PH2)
   init_bounded_vector Fcast_impl_error(endyr+1,j,-1,1,k)
   vector ABC_buffer(endyr+1,YrMax);
-  number HCR_anchor  //  basis (denominator) bor inflection in control rule
+  number HCR_anchor  //  basis (denominator) for inflection in control rule.  Select virgin SSB or benchmark SSB
 
 //  SPAWN-RECR:   define some spawning biomass and recruitment entities
   number SSB_virgin
diff --git a/SS_write_ssnew.tpl b/SS_write_ssnew.tpl
index d8a61230..e7080a9a 100644
--- a/SS_write_ssnew.tpl
+++ b/SS_write_ssnew.tpl
@@ -1631,9 +1631,9 @@ FUNCTION void write_nucontrol()
   NuFore << HarvestPolicy << " # Control rule method (0: none; 1: ramp does catch=f(SSB), buffer on F; 2: ramp does F=f(SSB), buffer on F; 3: ramp does catch=f(SSB), buffer on catch; 4: ramp does F=f(SSB), buffer on catch) " << endl;
   NuFore << "# values for top, bottom and buffer exist, but not used when Policy=0" << endl;
   NuFore << H4010_top_rd << " # Control rule inflection for constant F (as frac of Bzero, e.g. 0.40); must be > control rule cutoff, or set to -1 to use Bmsy/SSB_unf " << endl;
-  NuFore << "# Also see HCR_anchor below" << endl;
   NuFore << H4010_bot << " # Control rule cutoff for no F (as frac of Bzero, e.g. 0.10) " << endl;
   NuFore << H4010_scale_rd << " # Buffer:  enter Control rule target as fraction of Flimit (e.g. 0.75), negative value invokes list of [year, scalar] with filling from year to YrMax " << endl;
+  NuFore << "# Also see HCR_anchor below" << endl;
   if (H4010_scale_rd < 0)
   {
     j = H4010_scale_vec_rd.size() - 1;

From d2acb1e435fbe85d7b9c2561e95267adc386c4d1 Mon Sep 17 00:00:00 2001
From: Ian Taylor <ian.taylor@noaa.gov>
Date: Fri, 18 Oct 2024 09:43:01 -0700
Subject: [PATCH 29/29] revert change in capitalization of Recr_Virgin

---
 SS_readcontrol_330.tpl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SS_readcontrol_330.tpl b/SS_readcontrol_330.tpl
index 14bcf479..0e4dfab2 100644
--- a/SS_readcontrol_330.tpl
+++ b/SS_readcontrol_330.tpl
@@ -6495,7 +6495,7 @@
       active_parm(CoVar_Count) = j;
       if (y == styr - 2)
       {
-        ParmLabel += "Recr_virgin";
+        ParmLabel += "Recr_Virgin";
       }
       else if (y == styr - 1)
       {