APSIMInitiative / APSIM710

APSIM
https://www.apsim.info
30 stars 47 forks source link

SDR for x degree-days windows centred at flowering in APSIM #2120

Open tefera21 opened 2 years ago

tefera21 commented 2 years ago

Could someone please help me to write codes of water deficit index (soil water supply demand ratio, SDR) for 100 degree-days windows centred at flowering (0◦Cd) in APSIM classical?
Thanks

peter-devoil commented 2 years ago

Hi, I've been using some code similar to this. You'll have to hook up the properties page to the params. Report "SDRAroundFlowering" at harvest.

Note that flowering can span several days, and this algorithm's window is based on the first day of flowering.

P


   [Param] public int preTT;  // 100dd
   [Param] public int postTT; // 100dd
   [Param] public string cropName; // sorghum 

   private double[] tt = new double[365];
   private double[] sdrVec = new double[365];
   private int FlwDAS;

   private Component crop;
   [EventHandler] public void OnInitialised()
   {
      crop = (Component) MyPaddock.LinkByName(cropName);
   }

   [EventHandler] public void OnSowing()
   {
      Array.Clear(tt, 0, tt.Length);
      Array.Clear(sdrVec, 0, sdrVec.Length);
      FlwDAS = -1;
   }

   [EventHandler] public void OnPost()
   {
      string plant_status;
      crop.Get("plant_status", out plant_status);
      if (plant_status == "alive") {
         int daysAfterSowing;

         crop.Get("daysAfterSowing", out daysAfterSowing);

         double DeltaTT = 0;
         crop.Get("DeltaTT", out DeltaTT);  // This name varies amongst crops
         tt[daysAfterSowing] = DeltaTT;

         double sdr = 0;
         crop.Get("SDR", out sdr);  // ditto
         sdrVec[daysAfterSowing] = sdr;

         string StageName = "";
         crop.Get("StageName", out StageName);
         if (StageName == "flowering" && FlwDAS < 0) { // could be  any other stage
            FlwDAS = daysAfterSowing;
         }
      }
   }

   public double sumAround(double [] what, int whereAbouts, double lower, double  upper) 
   {
      double s = 0.0; double x = 0.0;
      if (whereAbouts > 0) {
         // Sum growth before 
         for (int day = whereAbouts; day >=  0 && x < lower; day--) {
           s += what[day];
           x += tt[day];
         }

         // and after 
         x = tt[whereAbouts];
         for (int day = whereAbouts + 1; day < what.Length && x < upper; day++) {
            s += what[day];
            x += tt[day];
         }
       }
       return(s); 
   }

   [Output] public double SDRAroundFlowering {get {
        return(sumAround(sdrVec, FlwDAS, preTT, postTT));
   }}

Some variables may require fractional values on the day of the TT cutoff - this method ignores that.

peter-devoil commented 2 years ago

Here's a working example of the method, with a few spolling corructions. SDR_lentil.apsim.zip

Note it's always important to check for potential divide by zero errors

tefera21 commented 2 years ago

Here's a working example of the method, with a few spolling corructions. SDR_lentil.apsim.zip

Note it's always important to check for potential divide by zero errors

Many thanks Peter, you are so much helpful!