Пример #1
0
    def update_crop_parameters(self):
        """Function to update certain crop parameters for current 
        time step (equivalent to lines 97-163 in 
        compute_crop_calendar)
        """
        pd = np.copy(self.var.PlantingDateAdj)
        hd = np.copy(self.var.HarvestDateAdj)
        hd[hd < pd] += 365
        sd = self.var._modelTime.currTime.timetuple().tm_yday

        # Update certain crop parameters if using GDD mode
        if (self.var.CalendarType == 2):

            cond1 = ((self.var.GrowingSeason) &
                     (self.var._modelTime.doy == pd))
            pd[np.logical_not(cond1)] = 0
            hd[np.logical_not(cond1)] = 0
            max_harvest_date = int(np.max(hd))

            if (max_harvest_date > 0):

                # Dimension (day,crop,lat,lon)
                day_idx = np.arange(sd, max_harvest_date +
                                    1)[:, None, None, None] * np.ones_like(
                                        self.var.PlantingDate)[None, :, :, :]
                growing_season_idx = ((day_idx >= pd) & (day_idx <= hd))

                # Extract weather data for first growing season
                tmin = vos.netcdf2NumPyTimeSlice(
                    self.var.tmpFileNC,
                    self.var.tmnVarName,
                    self.var._modelTime.currTime,
                    self.var._modelTime.currTime +
                    datetime.timedelta(int(max_harvest_date - sd)),
                    cloneMapFileName=self.var.cloneMap,
                    LatitudeLongitude=True)

                tmax = vos.netcdf2NumPyTimeSlice(
                    self.var.tmpFileNC,
                    self.var.tmxVarName,
                    self.var._modelTime.currTime,
                    self.var._modelTime.currTime +
                    datetime.timedelta(int(max_harvest_date - sd)),
                    cloneMapFileName=self.var.cloneMap,
                    LatitudeLongitude=True)

                # broadcast to crop dimension
                tmax = tmax[:, None, :, :] * np.ones(
                    (self.var.nCrop))[None, :, None, None]
                tmin = tmin[:, None, :, :] * np.ones(
                    (self.var.nCrop))[None, :, None, None]

                # for convenience
                tupp = self.var.Tupp[None, :, :, :] * np.ones(
                    (tmin.shape[0]))[:, None, None, None]
                tbase = self.var.Tbase[None, :, :, :] * np.ones(
                    (tmin.shape[0]))[:, None, None, None]

                # calculate GDD according to the various methods
                if self.var.GDDmethod == 1:
                    tmean = ((tmax + tmin) / 2)
                    tmean = np.clip(tmean, self.var.Tbase, self.var.Tupp)
                elif self.var.GDDmethod == 2:
                    tmax = np.clip(tmax, self.var.Tbase, self.var.Tupp)
                    tmin = np.clip(tmin, self.var.Tbase, self.var.Tupp)
                    tmean = ((tmax + tmin) / 2)
                elif self.var.GDDmethod == 3:
                    tmax = np.clip(tmax, self.var.Tbase, self.var.Tupp)
                    tmin = np.clip(tmin, None, self.var.Tupp)
                    tmean = ((tmax + tmin) / 2)
                    tmean = np.clip(tmean, self.var.Tbase, None)

                tmean[np.logical_not(growing_season_idx)] = 0
                tbase[np.logical_not(growing_season_idx)] = 0
                GDD = (tmean - tbase)
                GDDcum = np.cumsum(GDD, axis=0)

                # 1 - Calendar days from sowing to maximum canopy cover
                maxcanopy_idx = np.copy(day_idx)
                maxcanopy_idx[np.logical_not(
                    GDDcum > self.var.MaxCanopy)] = 999
                # maxcanopy_idx[np.logical_not(GDDcum > self.var.MaxCanopy)] = np.nan
                maxcanopy_idx = np.nanmin(maxcanopy_idx, axis=0)
                MaxCanopyCD = (maxcanopy_idx - pd + 1)
                self.var.MaxCanopyCD[cond1] = MaxCanopyCD[cond1]

                # 2 - Calendar days from sowing to end of vegetative growth
                canopydevend_idx = np.copy(day_idx)
                canopydevend_idx[np.logical_not(
                    GDDcum > self.var.CanopyDevEnd)] = 999
                # canopydevend_idx[np.logical_not(GDDcum > self.var.CanopyDevEnd)] = np.nan
                canopydevend_idx = np.nanmin(canopydevend_idx, axis=0)
                CanopyDevEndCD = canopydevend_idx - pd + 1
                self.var.CanopyDevEndCD[cond1] = CanopyDevEndCD[cond1]

                # 3 - Calendar days from sowing to start of yield formation
                histart_idx = np.copy(day_idx)
                histart_idx[np.logical_not(GDDcum > self.var.HIstart)] = 999
                # histart_idx[np.logical_not(GDDcum > self.var.HIstart)] = np.nan
                histart_idx = np.nanmin(histart_idx, axis=0)
                HIstartCD = histart_idx - pd + 1
                self.var.HIstartCD[cond1] = HIstartCD[cond1]

                # 4 - Calendar days from sowing to end of yield formation
                hiend_idx = np.copy(day_idx)
                hiend_idx[np.logical_not(GDDcum > self.var.HIend)] = 999
                # hiend_idx[np.logical_not(GDDcum > self.var.HIend)] = np.nan
                hiend_idx = np.nanmin(hiend_idx, axis=0)
                HIendCD = hiend_idx - pd + 1
                self.var.HIendCD[cond1] = HIendCD[cond1]

                # Duration of yield formation in calendar days
                self.var.YldFormCD[cond1] = (self.var.HIendCD -
                                             self.var.HIstartCD)[cond1]

                cond11 = (cond1 & (self.var.CropType == 3))

                # 1 Calendar days from sowing to end of flowering
                floweringend_idx = np.copy(day_idx)
                floweringend_idx[np.logical_not(
                    GDDcum > self.var.FloweringEnd)] = 999
                # floweringend_idx[np.logical_not(GDDcum > self.var.FloweringEnd)] = np.nan
                floweringend_idx = np.nanmin(floweringend_idx, axis=0)
                FloweringEnd = floweringend_idx - pd + 1

                # 2 Duration of flowering in calendar days
                self.var.FloweringCD[cond11] = (FloweringEnd -
                                                self.var.HIstartCD)[cond11]

                # Harvest index growth coefficient
                self.calculate_HIGC()

                # Days to linear HI switch point
                self.calculate_HI_linear()
Пример #2
0
    def compute_crop_calendar(self):

        # "Time from sowing to end of vegetative growth period"
        cond1 = (self.var.Determinant == 1)
        self.var.CanopyDevEnd = np.copy(self.var.Senescence)
        self.var.CanopyDevEnd[cond1] = (
            np.round(self.var.HIstart + (self.var.Flowering / 2)))[cond1]

        # "Time from sowing to 10% canopy cover (non-stressed conditions)
        self.var.Canopy10Pct = np.round(self.var.Emergence +
                                        (np.log(0.1 / self.var.CC0) /
                                         self.var.CGC))

        # "Time from sowing to maximum canopy cover (non-stressed conditions)
        self.var.MaxCanopy = np.round(self.var.Emergence + (np.log(
            (0.25 * self.var.CCx * self.var.CCx / self.var.CC0) /
            (self.var.CCx - (0.98 * self.var.CCx))) / self.var.CGC))

        # "Time from sowing to end of yield formation"
        self.var.HIend = self.var.HIstart + self.var.YldForm
        cond2 = (self.var.CropType == 3)

        # TODO: declare these in __init__
        arr_zeros = np.zeros_like(self.var.CropType)
        self.var.FloweringEnd = np.copy(arr_zeros)
        self.var.FloweringEndCD = np.copy(arr_zeros)
        self.var.FloweringCD = np.copy(arr_zeros)
        self.var.FloweringEnd[cond2] = (self.var.HIstart +
                                        self.var.Flowering)[cond2]
        self.var.FloweringEndCD[cond2] = self.var.FloweringEnd[cond2]
        self.var.FloweringCD[cond2] = self.var.Flowering[cond2]

        # Mode = self.var.CalendarType
        # if Mode == 1:
        if self.var.CalendarType == 1:
            # "Duplicate calendar values (needed to minimise if-statements when
            # switching between GDD and CD runs)
            self.var.EmergenceCD = np.copy(
                self.var.Emergence)  # only used in this function
            self.var.Canopy10PctCD = np.copy(
                self.var.Canopy10Pct)  # only used in this function
            self.var.MaxRootingCD = np.copy(
                self.var.MaxRooting)  # only used in this function
            self.var.SenescenceCD = np.copy(
                self.var.Senescence)  # only used in this function
            self.var.MaturityCD = np.copy(
                self.var.Maturity)  # only used in this function
            self.var.MaxCanopyCD = np.copy(self.var.MaxCanopy)
            self.var.CanopyDevEndCD = np.copy(self.var.CanopyDevEnd)
            self.var.HIstartCD = np.copy(self.var.HIstart)
            self.var.HIendCD = np.copy(self.var.HIend)
            self.var.YldFormCD = np.copy(self.var.YldForm)
            self.var.FloweringEndCD = np.copy(
                self.var.FloweringEnd)  # only used in this function
            self.var.FloweringCD = np.copy(self.var.Flowering)

        # Pre-compute cumulative GDD during growing season
        if (self.var.CalendarType
                == 1 & self.var.SwitchGDD) | (self.var.CalendarType == 2):

            pd = np.copy(self.var.PlantingDate)
            hd = np.copy(self.var.HarvestDate)
            sd = self.var._modelTime.startTime.timetuple().tm_yday

            # NEW:
            isLeapYear1 = calendar.isleap(self.var._modelTime.startTime.year)
            isLeapYear2 = calendar.isleap(self.var._modelTime.startTime.year +
                                          1)

            if isLeapYear1:
                pd[pd >= 60] += 1
                hd[(hd > pd) & (hd >= 60)] += 1

            if isLeapYear2:
                hd[(hd < pd) & (hd >= 60)] += 1

            hd[hd <
               pd] += 365  # already accounted for leap years so this should be OK

            cond = sd > pd
            pd[cond] += 365
            hd[cond] += 365

            # OLD:
            # # if start day of simulation is greater than planting day the
            # # first complete growing season will not be until the
            # # following year
            # pd[sd > pd] += 365
            # hd[sd > pd] += 365

            # # if start day is less than or equal to planting day, but
            # # harvest day is less than planting day, the harvest day will
            # # occur in the following year
            # hd[((sd <= pd) & (hd < pd))] += 365

            # # adjust values for leap year
            # isLeapYear1 = calendar.isleap(self.var._modelTime.startTime.year)
            # isLeapYear2 = calendar.isleap(self.var._modelTime.startTime.year + 1)
            # pd[(isLeapYear1 & (pd >= 60))] += 1  # TODO: check these
            # hd[(isLeapYear1 & (hd >= 60))] += 1
            # pd[(isLeapYear2 & (pd >= 425))] += 1
            # hd[(isLeapYear2 & (hd >= 425))] += 1

            max_harvest_date = int(np.max(hd))
            day_idx = np.arange(
                sd, max_harvest_date + 1)[:, None, None, None] * np.ones_like(
                    self.var.PlantingDate)[None, :, :, :]
            growing_season_idx = ((day_idx >= pd) & (day_idx <= hd))

            # Extract weather data for first growing season
            tmin = vos.netcdf2NumPyTimeSlice(
                self.var.tmpFileNC,
                self.var.tmnVarName,
                self.var._modelTime.startTime,
                self.var._modelTime.startTime +
                datetime.timedelta(int(max_harvest_date - sd)),
                cloneMapFileName=self.var.cloneMap,
                LatitudeLongitude=True)

            tmax = vos.netcdf2NumPyTimeSlice(
                self.var.tmpFileNC,
                self.var.tmxVarName,
                self.var._modelTime.startTime,
                self.var._modelTime.startTime +
                datetime.timedelta(int(max_harvest_date - sd)),
                cloneMapFileName=self.var.cloneMap,
                LatitudeLongitude=True)

            # broadcast to crop dimension
            tmax = tmax[:, None, :, :] * np.ones(
                (self.var.PlantingDate.shape[0]))[None, :, None, None]
            tmin = tmin[:, None, :, :] * np.ones(
                (self.var.PlantingDate.shape[0]))[None, :, None, None]

            # for convenience
            tupp = self.var.Tupp[None, :, :, :] * np.ones(
                (tmin.shape[0]))[:, None, None, None]
            tbase = self.var.Tbase[None, :, :, :] * np.ones(
                (tmin.shape[0]))[:, None, None, None]

            # calculate GDD according to the various methods
            if self.var.GDDmethod == 1:
                tmean = ((tmax + tmin) / 2)
                tmean = np.clip(tmean, self.var.Tbase, self.var.Tupp)
            elif self.var.GDDmethod == 2:
                tmax = np.clip(tmax, self.var.Tbase, self.var.Tupp)
                tmin = np.clip(tmin, self.var.Tbase, self.var.Tupp)
                tmean = ((tmax + tmin) / 2)
            elif self.var.GDDmethod == 3:
                tmax = np.clip(tmax, self.var.Tbase, self.var.Tupp)
                tmin = np.clip(tmin, None, self.var.Tupp)
                tmean = ((tmax + tmin) / 2)
                tmean = np.clip(tmean, self.var.Tbase, None)

            tmean[np.logical_not(growing_season_idx)] = 0
            tbase[np.logical_not(growing_season_idx)] = 0
            GDD = (tmean - tbase)
            GDDcum = np.cumsum(GDD, axis=0)

            # "Check if converting crop calendar to GDD mode"
            # if Mode == 1 & self.var.SwitchGDD:
            if self.var.CalendarType == 1 & self.var.SwitchGDD:

                # Find GDD equivalent for each crop calendar variable
                m, n, p = pd.shape  # crop,lat,lon
                I, J, K = np.ogrid[:m, :n, :p]

                emergence_idx = pd + self.var.EmergenceCD  # crop,lat,lon
                self.var.Emergence = GDDcum[emergence_idx, I, J, K]
                canopy10pct_idx = pd + self.var.Canopy10PctCD
                self.var.Canopy10Pct = GDDcum[canopy10pct_idx, I, J, K]
                maxrooting_idx = pd + self.var.MaxRootingCD
                self.var.MaxRooting = GDDcum[maxrooting_idx, I, J, K]
                maxcanopy_idx = pd + self.var.MaxCanopyCD
                self.var.MaxCanopy = GDDcum[maxcanopy_idx, I, J, K]
                canopydevend_idx = pd + self.var.CanopyDevEndCD
                self.var.CanopyDevEnd = GDDcum[canopydevend_idx, I, J, K]
                senescence_idx = pd + self.var.SenescenceCD
                self.var.Senescence = GDDcum[senescence_idx, I, J, K]
                maturity_idx = pd + self.var.MaturityCD
                self.var.Maturity = GDDcum[maturity_idx, I, J, K]
                histart_idx = pd + self.var.HIstartCD
                self.var.HIstart = GDDcum[histart_idx, I, J, K]
                hiend_idx = pd + self.var.HIendCD
                self.var.HIend = GDDcum[hiend_idx, I, J, K]
                yldform_idx = pd + self.var.YldFormCD
                self.var.YldForm = GDDcum[yldform_idx, I, J, K]

                cond2 = (self.var.CropType == 3)
                floweringend_idx = pd + self.var.FloweringEndCD
                self.var.FloweringEnd[cond2] = GDDcum[floweringend_idx, I, J,
                                                      K][cond2]
                self.var.Flowering[cond2] = (self.var.FloweringEnd -
                                             self.var.HIstart)[cond2]

                # "Convert CGC to GDD mode"
                # self.var.CGC_CD = self.var.CGC
                self.var.CGC = (np.log(
                    (((0.98 * self.var.CCx) - self.var.CCx) * self.var.CC0) /
                    (-0.25 * (self.var.CCx**2)))) / (
                        -(self.var.MaxCanopy - self.var.Emergence))

                # "Convert CDC to GDD mode"
                # self.var.CDC_CD = self.var.CDC
                tCD = self.var.MaturityCD - self.var.SenescenceCD
                tCD[tCD <= 0] = 1
                tGDD = self.var.Maturity - self.var.Senescence
                tGDD[tGDD <= 0] = 5
                self.var.CDC = (self.var.CCx / tGDD) * np.log(1 + (
                    (1 - self.var.CCi / self.var.CCx) / 0.05))

                # "Set calendar type to GDD mode"
                self.var._configuration.cropOptions['CalendarType'] = "2"

            # elif Mode == 2:
            elif self.var.CalendarType == 2:

                # "Find calendar days [equivalent] for some variables"

                # "1 Calendar days from sowing to maximum canopy cover"

                # # TODO: check this indexing
                # day_idx = np.arange(0, GDD.shape[0])[:,None,None,None] * np.ones((self.var.nCrop, self.var.nLon, self.var.nLat))[None,:,:,:]
                # pd,hd = self.var.adjust_planting_and_harvesting_date(self.var.modelTime.startTime)

                maxcanopy_idx = np.copy(day_idx)
                maxcanopy_idx[np.logical_not(
                    GDDcum > self.var.MaxCanopy)] = 999
                # maxcanopy_idx[np.logical_not(GDDcum > self.var.MaxCanopy)] = np.nan
                maxcanopy_idx = np.nanmin(maxcanopy_idx, axis=0)
                self.var.MaxCanopyCD = maxcanopy_idx - pd + 1

                # "2 Calendar days from sowing to end of vegetative growth"
                canopydevend_idx = np.copy(day_idx)
                canopydevend_idx[np.logical_not(
                    GDDcum > self.var.CanopyDevEnd)] = 999
                # canopydevend_idx[np.logical_not(GDDcum > self.var.CanopyDevEnd)] = np.nan
                canopydevend_idx = np.nanmin(canopydevend_idx, axis=0)
                self.var.CanopyDevEndCD = canopydevend_idx - pd + 1

                # "3 Calendar days from sowing to start of yield formation"
                histart_idx = np.copy(day_idx)
                histart_idx[np.logical_not(GDDcum > self.var.HIstart)] = 999
                # histart_idx[np.logical_not(GDDcum > self.var.HIstart)] = np.nan
                histart_idx = np.nanmin(histart_idx, axis=0)
                self.var.HIstartCD = histart_idx - pd + 1

                # "4 Calendar days from sowing to end of yield formation"
                hiend_idx = np.copy(day_idx)
                hiend_idx[np.logical_not(GDDcum > self.var.HIend)] = 999
                # hiend_idx[np.logical_not(GDDcum > self.var.HIend)] = np.nan
                hiend_idx = np.nanmin(hiend_idx, axis=0)
                self.var.HIendCD = hiend_idx - pd + 1

                # "Duration of yield formation in calendar days"
                self.var.YldFormCD = self.var.HIendCD - self.var.HIstartCD

                cond1 = (self.var.CropType == 3)

                # "1 Calendar days from sowing to end of flowering"
                floweringend_idx = np.copy(day_idx)
                floweringend_idx[np.logical_not(
                    GDDcum > self.var.FloweringEnd)] = 999
                # floweringend_idx[np.logical_not(GDDcum > self.var.FloweringEnd)] = np.nan
                floweringend_idx = np.nanmin(floweringend_idx, axis=0)
                FloweringEnd = floweringend_idx - pd + 1

                # "2 Duration of flowering in calendar days"
                self.var.FloweringCD[cond1] = (FloweringEnd -
                                               self.var.HIstartCD)[cond1]